FaustWorks-0.4/Resources/translations/i18n_ru.ts0000644000175000017500000007750012130743520020465 0ustar miramira FaustMainWindow C++ code C++ код Error Messages Ошибки Binary build error Ошибка сборки Couldn't launch command %1! Невозможно выполнить комманду %1! Script error : Ошибка скрипта: Script crashed Скрипт завершился аварийно Script : no output file specified Script : output file(s) %1 not found. Скрипт: выходной файл %1 не найден. Faust not found Faust не найден Couldn't launch %1. The file may not exist, or you may not have the rights to execute it. You must define a valid faust executable in the Application Preferences. Невозможно запустить %1. Возможно файл недоступен или недостаточно прав для исполнения. Выберите правильный путь для программы faust в настройках приложения. Preferences Настройки Setup the applications parameters Настроить пареметры программы &Build Target architecture Целевая архитектура Choose the exported plug-in architecture Выберите плагин для экспорта Build options Опции сборки Build options used for $OPTIONS by binary build scripts Опции используемые для переменной $OPTIONS при бинарной сборке FaustPreferences Preferences Настройки Faust compiler path : Путь к компилятору faust: Find... Найти... Target configuration Целевая конфигурация Add Добавить Build options configuration Конфигурация сборки GraphicsSceneMainWindow Add a %1 file Добавить файл %1 %n item(s) selected выбран %n элемент выбрано %n элемента выбрано %n элементов %1 Code OK %1 Успешно Save the %1 scene Сохранение сцены %1 Open a %1 scene Открыть сцену %1 Load scene error Ошибка при загрузке сцены %1 : Invalid GuidoScene file %1: неправильный файл GuidoScene %1 All (*.*) %1 Все (*.*) Find file Найти файл File not found Файл не найден Can't find the %1 item's file %2 Невозможно найти файл %2 элемента %1 Find file... Найти файл... Remove item Удалить элемент Reload Обновить Can't load the scene %1. Невозможно загрузить сцену %1. Choose the path of your new 'workspace' scene. Выберите путь для новой рабочей сцены. Workspace scene Сцена &New scene &Новая сцена Create a new scene Создать новую сцену &Save item or scene &Сохранить элемент или сцену Save the current item or the current scene Сохранить текущий элемент или текущую сцену &Save scene as... С&охранить сцену как... Save the current scene to another file Сохранить текущую сцену в другой файл Save All Сохранить всё &Open scene... &Открыть сцену... Open a scene Открыть сцену E&xit &Выход Ctrl+Q Exit the application Выйти из программы About &Qt Show the Qt library's About box Показать информацию о библиотеке Qt Zoom &In &Увеличить Zoom in Увеличить Zoom O&ut У&меньшить Zoom out Уменьшить Zoom 100% Оригинальный размер Font bigger Увеличить шрифт Ctrl+Shift+Plus Font smaller Уменьшить шрифт Ctrl+Shift+Minus Add &item &Добавить элемент Ctrl+I Add item from file... Добавить элемент из файла... Ctrl+Shift+O Remove items Удалить элементы &Copy &Копировать &Paste &Вставить Paste previously copied items Вставить ранее скопированные элементы Clean history Очистить историю Clean your history side bar Очистить панель истории Select &All Вы&брать все Select all the items Выбрать все элементы &Rescale &Масштабировать Ctrl+R Set the scale of all selected items to the scale of the first selected one Установить масштаб выбранных элементов равным масштабу первого выбранного &Horizontal alignment &Горизонтальное выравнивание Ctrl+H Horizontally align all selected items on the first selected one Выровнять по горизонтали все выбранные элементы по первому выбранному Ver&tical alignment Вер&тикальное выравнивание Ctrl+T Vertically align all selected items on the first selected one Выровнять по вертикали все выбранные элементы по первому выбранному Bring to front Поднять наверх Brings the first selected item to front Поднимает первый выбранный элемент на самый верх Bring forward Поднять Brings the first selected item forward Поднимает первый выбранный элемент выше Send to back Опустить вниз Sends the first selected item to back Опускает первый выбранный элемент на самый низ Send backward Опустить Sends the first selected item backward Опускает первый выбранный элемент ниже &File &Файл &Edit &Правка &View &Вид &About О &программе &Window &Окно Edit Правка View Вид Resize the selected items Изменить размер у выбранных элементов Change the abscissa of the selected item Изменить абсциссу у выбранных элементов Change the ordinate of the selected item Изменить ординату у выбранных элементов Scale && position Рамер и положение Ready Готово %1 Code Ok %1 Успешно %1 has changed. Save modifications ? %1 изменен. Сохранить изменения? %1 doesn't exist. Re-save item ? %1 не существует. Сохранить заново? Save item Сохранить элемент Save the %1 item Сохранение элемента %1 History История Storage Хранилище QFaustItem Invalid Faust Code Неправильный Faust код Faust Code OK Save Сохранить Save as... Сохранить как... Browse Diagram Просмотреть диаграмму Generate Math Generate Loop Graph Generate Signal Graph Run Binary Запустить бинарное приложение QFaustPreferences Name : Имя: Command : Команда: Remove Удалить QLanguageItem Reload Обновить Unsaved modifications will be lost. Reload? Несохраненные изменения удут потеряны. Обновить? Delete file Удалить файл Remove item and file ? Удалить элемент и файл? Delete item && file Unlink Save as... Сохранить как... Save Сохранить Z order Bring to front Поднять наверх Bring forward Поднять Send backward Опустить вниз Send to back Опустить QStorageGraphicsView Drag&drop an item to store it in the Storage Zone ResolutionDialog Choose resolution Выберите разрешение Detail : Детализация: Low Низкая High Высокая Image resolution : Разрешение: TextLabel FaustWorks-0.4/Forms/FaustPreferences.ui0000755000175000017500000001150512130743520017022 0ustar miramira FaustPreferences 0 0 835 383 0 0 Preferences 200 0 Faust compiler path : Find... false Target configuration Qt::Horizontal 40 20 Add Qt::Vertical 20 40 Build options configuration Qt::Horizontal 40 20 Add Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::RestoreDefaults buttonBox accepted() FaustPreferences accept() 332 127 332 73 buttonBox rejected() FaustPreferences reject() 332 127 332 73 FaustWorks-0.4/Forms/ResolutionDialog.ui0000755000175000017500000001117512130743520017044 0ustar miramira ResolutionDialog Qt::ApplicationModal 0 0 250 150 250 150 250 150 Choose resolution true Qt::Vertical 20 13 Detail : Low High Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 1 6 4 Qt::Horizontal Qt::Vertical 20 18 Image resolution : Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel Qt::Vertical 20 17 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok true scaleSlider buttonBox buttonBox rejected() ResolutionDialog reject() 240 135 249 149 FaustWorks-0.4/Resources/FaustCommands.xml0000755000175000017500000001106012130743520017365 0ustar miramira ]]> =]]> >]]> FaustWorks-0.4/Resources/FaustWorks.icns0000755000175000017500000041320112130743520017070 0ustar miramiraicnsic08 jP ftypjp2 jp2 Ojp2hihdrcolr"cdefDjp2cOQ2R \@@HHPHHPHHPHHPHHP S ]@@HHPHHPHHPHHPHHPS ]@@HHPHHPHHPHHPHHPS ]@@HHPHHPHHPHHPHHPz4Ϧ:aHQ.5K+m9SS(!9Tbޡ19Ò.1Gcx-ϱPr*/[CN~W"];]z'G O֑h5p:yo7oρwWPγz{IsQN!璸ee3p0KXOP[D~+Z\8 ;|_yx G^y5J^AK뱩 &8LQMMϱ31s;'zϼ}\n{B L5:4*xH96}l#hd C|vJ`aI4]C[,w` Q@"*2R(11u[8dIim 1G.i p}b:S/ٌ5d[J Lϼ> ]@aSދc^壟hh^'$_#f866U#ڷf(;:_H2!!M?×2Kka\f<_E\{%*;:=6o,;QO-I>H. k™`t>Аei7<=;_̬IːWaߝy~ul밐: 0p )txB .fyȽ~:tP=(縉z^J]7ڇNA4 iʩρ8B{u,lZH C+ä;㘴;cz6L[M]D b+rFҮ :ߦJ!uwTJ_Rb\7FVE-]F$8ԲkM՚v?--,綵KH[%]W v6TgfЌ?%#39 R %e?4jW`?zm.OZc肯C[x,`N[eٓ`s]У|rEk l}+Jo?¸x{p$ !3߃*{fG^CL`&a?,'_^e͊U#fqš%V f gw5sF.U#1[$1KcF\Sxx9u]8R5Mr3t@@HSڟ?;X' nm3]D m{1w#H-Rf-b !c V9Na{frgC7X\iuED?u"Rׄކ[Ј5XqXt.ouBH Cq{VMq:z0xڒ͔)xDkgV.be`TKP R% 3D-e0kVHf<'P$kI[wG r yC1cCߘsrGOc\>D 5}O.8i";-mw>l1w$>[Dbp\}N<Ȗnbp,ݘp,U*CMI՛X)Nbfas528+CT@0[ЀZs)rAuvrߌ=H']Z:w#&g}: 򼸗krw=у*mS'@CtSRqZB˴fj%>Rp#] ߠLU>!܂Hi h=-͚+B6K{/Ͻ3Li6("I1W"Y[~4Iīxg5p™'?:<"{U,^^i.;I7r$b'Ɉ8MQ/هb,hvFlmB廒Zύe/,w"%\H`.5jn,`FCN dà7G?IJeG4Ņ.1:!nBG(xSV6Zb츣&BW#!@r,q +]Tv-G v_H+8nh`w*pc2 iXM̹Ff;v32R>pVD>~T|)˜;(Yd 75 {l\#Kx@_MasaߺmE%naVg0&w:HyV)NN&Z{wG}2q7T.8/'5ϼj}p_QHdl69Р#ۆf+rԙ i;Sj3n; M$IqߟLW~ $kٱ ДzK.$K{MCwMi)h7E$8lY;:s1Qs]ıˣGD&L.YLBu!%džLuanG u$*XDl7Y4ߒ6E uD{? DRX4LY9|ܰOE3J ݅ei@n#& 醐#C-J˺B\94\j{b ;M#,UJb/rd\|g7MNK/gM~غ>3":]O&5_i[;~FlJt=$ZWZ !}G?ЂkY}wXof`#= @(R&[L.<rƞgݨ_/P~+Z}2+O6$ߘP1yojQeZZY@Do 0$iStw.\ʸTFTu݌OǿZ#Dv䪧  T"\}&~,]Hͪ_b0a8}W:N%lBC점< bLhyL=׮cmo$gXakh'W`[Ři._qpch>~& %W#>TA4$;m;4OS/@¤hYP.fvp 2T"d(iĴjvp\1iYmф]@%H]>]jH0%r@Z$Y kyZT*O gt@mؙT sl Ñ!_6]t`ѻF)ZAqzXɻ(p _N&;E'478C> 2 E0VsNd|UmP[Ŭ /QzYi|JV7Dof)W+A ԋ=Q2yT|6tfu}6_gAcյ >+:w*jq-6-NMYA[? #|-\p7kBۢtEu1Şe0m$(e|t{9Fqg{"ŸR}u+{DS/4BFX \Gs݂'¶d<ǁXz.#qR9"Pw&X߱jKEp=VbDue|x vqa`]W;q(Ѭ#nf)3rBS"}(R]ըԳ[̫ܟKNM[Q1yNy :h^kn6'&2 I;CL&\7]oQGx3)s[ iU"2BP8e atxI;DXRNaA˖#lfnewnHcM} Grx鄩b3^p֋!ìu?>{9p+C@jFg7_|oV|PtJʷLncZwO Qh0ɥJW5{L4TYO%qmyߏ6}QF]\1+(B]&ٳ-~uz5OTLyMd>k8Q >_Ne KVQ"},]5crk,DP=Y} T Ӎ5Vϲg걨_~VL;jݩQccaTr<%Cε+IBu~jeNPJ$Bhpy4IQzU<(ZE}B2/ G8bqAm=S+KGtO..1}k§8[D-Qp'IE"ڀ%k,\c޲@%H%Qe*&xqc`'KN6jJhm~iPֿ3 _o 3*4׆-^uRr`Cˊ:QkẏmZz~b[8BLK^%KF4~({[UE&9Կ9{ |siP>rb"K>kcu#,l̦-=w|}ib$lsB[.y`A&BVg'zYPy-H-h S'3EbkDW.fm[C~>Ni7 J#zPͶxYӽu(Gț+.j;h`;ӟo{P-56~[#/*+ &vCdSVEõыQ˅B}`c=oƒjsA&"61>Rfyb޽lTϬghW,$f=DVؐ8*kiM;[-L*:kbB avP{91< xŕ<:9G0N3`ӤӄBm1nb#hSDW6VŨ4O;omlA)EY얚'_vyt]h9MlgjeET+.3%U*cL+pdl>^ẁ"9'Lr'>z7.Z \U:2P Bî4Cp{yhk!ud,cJTBsʒyVqMRYǞn Z*Aw0|ShFޡ8Ŧ7~X9ۅäx&Uكփ%ޜN񾁅ěy#&6` E[|NJcwׇuvt8 ۨ+"2;IL6lNaa@vT_ (XL; 3WH3IVQ;` _p.x1~OὠU'SaSq-F$7fJF}O] r"պCi;eڡzK葵yBHUMLf $#+p}N<̟ @q8ZH3$yϯ ,JdHN>i|G?1Bb8$5fe"şP&3NmC=?]˧3X'%…% 3BEn(]'Enm5Cy1{Z:!{9T^Df4]խPJ= M:4u~zה۲M(z?ɮ] bN(D9 &=QAF4rP DڊBTZ%:OKU)/=n [ w54%so^>ׅDDFZm%74Z1]M2.}坩˒FԨX *2wkշa}|xd/GR{q8f.\:5>SM!| C{-A)~ 8(jx(rJ,u>Sy?7\vn1ldhޣ,5?H؊sQ@Ftv)r懝07׺B:ǎc @@vb?<Fk敕ҕ >w[ }N~ F`Å/q키y.SŒDC 3OA\GqZ8X>oꞚ o -+.ݓL՗$ c/0,|,  >\p[dĚfN{_@ul؎XqRm{,z:VjBw3D l +cyORĆ^4[B ⼲=h qjb-@јc!].q[%drCJ;63w~йc m23"ҜQD!XXU^@(o>TxVduSD8QVHm!S)~Z'nD.p;daJ2dfysY?;sm7<߸N9zPA~*xph_r<6)SՆ =HsA1*BHS aIG;8eKd[!1+¯e1ex Ul/L4|֢+J2$>eʉ ۃQEy ϼ}zAVEV,_כWRYj?ڊ`u NJu9q6S JQA 1 AKbK#y:Tսv~1zows=GC$8g;B+ Qpّ`9hs`Ow\dIypoN)CBb3 |.q6jNDؖПEèЌh~1ۍPm^~ZZzg0@9%h |*Sy>HB:3,2MG2bT9?(nl&+s qۆ]#v'3R!b\o`Zپ&@+% ;k]v^>6HrsanPB9H5y@}瓅FdV% %Y40`_ 5kgzSlqC O Y.3?5XY@^^VGvz3a:uky԰U;#M+&'c @"`FOӲê$fΪt<)hKIC·4P3D_ ECb\ox__QdyOg0-hS4*_5уA^N_ãKY=xL`F b4)d Z^vnsL2YgKu6-#PbZDCv'ߧ~_ S!V] oŚġ<(WY8cҋ/Ef% _0cPjh݆-1 /ͦHۦR7u3#w&=,q:wNkCOFcN8UCի_/u{Io#:ُCcu~y3i J7jH1|CT|3l u) GfdR{{>ieJ9ap'S!@H we^>W4/QL^A%S2Ks\,2{xy5]Q dsxi4Cs5 &tE{Ӌ &j)p$f/ȥE' *iǰwE=z4sƫ^E̽QVɬxh>$mFkVEIUeJ!B^DtBpUK-S׆ɽGWgyutA+[ Je5KCOKhR˘AcA8B7eZg,YPS0XvF3o}#Q4%jSHr| N@ڶHjfMTѢ(|~vD2Z!y౧潥Qw\>QfpgxYNj4(l }74DqTܦ+^luq`th4x`-9f@LhY" '2.@p,}<{O4W^zoމ <EA:FK5ew B9o(龆p0vA |Lr؆D ,6Xzԙ=H8",uȒ]0|qhR=srySxa睇K[`!OJNJ@B">ӺdjY&|mcCE+H"uo~WcTTtNEL^2Q)#Uo@m0Y K*(<M·@GBu(@1F oVcqM#3;ܑO*U|$m SurWj 2K"u'Ci0X%UCl5A7>gߢs& !EF!cvr$\́[ju\Ii(pDVH,ɜhft[r] BJ_1  )xUYt/0.bC['T \DIHv J͜S@ sK %zDn^Qfz3[O :(n1Vri;xKU>WkpJq؍.,ioa4Nm5}_nv:C2'a d"= pzfO[clX,a#Ih1Z\cK2Zf1wmnHL}ǕYvua<9վ:;N2XcPDAht^x"S;U |G!2"~2[-,FO{, pw21 tSWCT{ ۖPH)ɥ=<]=X=ʨk{O)Ln-|ZF+OM @ywʋ(NJlurkNR<[K子SxIMQ__;ecè@$V` %+q?Rp Fx_Nin8KO6WxnQ Ǜ@o撹A Q~e"|64tO?A$Sf  Я v -3(Tzbӆ 3E C?Mŏ ȯ~rYko:fӀ|7 2@}R8{W( 8lpMb.9_؏պI@D#:y :C/&LvJC@UJ=[Uy-t8~,߱ejKN~?X Ǭc Al5 uBƜMrIVΰ'%hPeW?EnlB/N¡"n@M\E4FXs&2EJYnyy h=| MY;KBm4QK_K8YBt>/L e4̩sT V:Lfgќ݃ ^* UۘMMݔc #ty0(3?wb,Ѯ;uԎX};կT06Bl2ӛhqdt&T-C ?t%/Z[ڶQN f~9_b2]ʭ{H`)_]$y&]GLډxthC64D\_- zQ?nAԨ8?jm.ߚloO}kp=Hm*V!4ˁxrv": l(58r6m #wlE;lVLSDso)3-%>&ץ[I2Rj7K2I\^g ƶ՝JmFurq2w|eeRr p ڱ0Ǿ h3vkW@Ug88`l%p޶o^]iǀZ(sSc.rȥ{yw6UoQ*:rAOD=ccv|DqAىԫys–EwkDR82 sǿ'X>kd ldX<A>fVOoєZD9InM~Ht߆Tiw̡>nR36 ҝ&^ nJz&&$|p&ΤJ:$eSnZ{)\y_:$q4*} XASҿYcnfQ\VAu*/TL:r5dIYBzy'ʢ%"&E iػ}^6US hgq<#1ٻ66ú,]2uBr͖qP=tnʟju HUL8Q7y{s?=?L5>% M/ͳɶӬfU T_hnˌѓ;E# b#n5%僙eAzHXzϙ'J3VPd;k)!1Zb]d4Է'sW4>L{/*LƴBxaG(و/nfC8AY\ʟԦlb0ܽu:W?PIRB" Lk SX+J %93 }Nb:}Cx d/$W7،!/ddy zXobFO_Jf5΂T)bF7瑭U%|:2O2p]wCop&*B@Am>7* F5`6A_@x߱oVt-_Ai.d(P+A8z_rzes[tAQ X-)*e\DzD&S|cIzO\p%#,'&&Wk^DFB_Ak~Kij)*VRkwi. wuh#*u3NvU] n*J2}) %Ŏc)vkrgZ#}T3X Jort5'MGň*X, ͹z/QlošW^>ׄ@ (3Wk{n_F5˓Uv,#>NV283ls 6fE4IGQ |/LPgM{ёO|Ye1tV+s 3!1ҵ}\"U.kdl@b>6q\`wd u7 VfR@(+^ (6`N.G-I4b ߻cA~c~.'>Aji-ϑwĥ"[J%eaVz<[5Lb7[+( -ߧD[t:9UTv("ѵS2D$ #h>dx(v$Gܪ@qz.n8{aHJ/ӸHJ]yC'}-Z4|ĂzΚBNf=ndbҼJsriMjyA^+Ŏ6CM?K!dbUe6?nd 'hjpHkg~Ddyj"IsXPIZ ^yO-@rG ]?yJ;;2{D^jxh W! Ff 1gv'\Y <[a'{Zkr,N10}|ш5iMQKf- vׅ`'ة0vV]oaABB`3L߰" cBq3x6لiXOd.&f %m*iu5nyPy%FwCne)M\]+U*أ=_,ݯ^D9xfNO[qR02>˼~:R] WLSOa/Dx*ewI+|hfh^遟X\DߋD pI,8l7S7^I^550$zO%cJS1;*Nڪ;B63&@W-_gvuudޢ[ok:K†+.f%a=2tHL#( ܁nAĤ[v[:y[m 4[r)Ξ%`T;Uc$C4߁<0[wUI+\)v[NiC:ҽaYg&xNúɥT$ d 'gE"؜j0DG( /MQV)`|b'?YA!:4#J?.S=>ZkS>}#O4P4Ye#^~Z8!ʲi!燄 fw yIxJ7v[ <{1|e&@a@ qCި3Lo4_S1$c^qN͟&i(hL%9SN{7c=gYt͙ҷilal?$d6)b4F̦>ƣb;W-[`z94 c܌'5*#XoB,8K qH.pUjonVudc_8a6Gt0QXm@Ұ;HIޭ[((ABl'Dy@Lߧ%Rl(W3c׀OX .-T`qߡV`&`p௻NǕ Cp/Ϟ ~ pOǪfE̲5Yb7eGsoRlU5T9_/Qŏ[61DuG: #w_G2ѧ,(NG1 ^8/0p̵=zn|\, h:,jebLZ5+=oo'gSì"x+tRC_A;G#jf܅BU#FCRG"]RكN;5PѸ.I u`dޑ$l ks La|-jc4eIJ-TsM2Y`bK.JLH[mؼ<)Dq|bbo"~P!LZQZ:*HSQ?`7$c# LVC;ܦz[#RF wTrVW c-WkJO8Qj8P KW1pT aG1iv7tB`ЍyG?,vvڦ%QNҎ}1>$Cg|=pM3q(]-]T &EEE M8+)Y}tČL1`k-k7>Bf*#Hv}꽻*XLt̘VvYh9r=" y0zZ3GڸSDutR!^N`r>ށj03)[R Cc`$y.7MUE|vrr랹xpJ\skI쿈**c) |EFG?gNzcS/h|5ӀckQY yb-!*-XR\ȍ,cV!wڍ9{+DlXǣNnј[=#-2~1z.)Yպ ysxym0ذJ.HFou@>5?L긥 A#sjO|/S.Ea[Q]$*N9T8-gcyeUƪ䩎Mp̏&iد_7DBЄ R2@B< m5m~}^tW`|O2:$z״Of "g Sw30M"NL{MKOWpm˅|>0]388-H1`rZUaSS&PD5'f./JS3GJy!w_nDa vqo~:6CpJ85YKI?_yYGqd՘AJm++ J,N[Bc(a{}X (WŚY6t66wxO$-;8BO/2B VIx r6kXYm/.L^7n1f@߱Zrz1ems~YkrpCO'koWQscYޯ?̍ViΪ oc0sWUU-Xwf,QgBuj'եD^?88B #ghz2"|OةD(ΣL!P,ËaUK ǁ>!SOR۵Jv@;v=Lj_WkrG0)P@y_=71_ڈih&܉kРaJؕAŲW'pApV5A%,3XNH46a֟!@?ޗ.uo?/jwENZ?x"a_SRۿ3rGAY/@]XDf]]{Ukp1&`_1שCc/|vi\uB7ir& t e5-(E8'9!쩭6J:.OjjZ}*Fd3W` 榊!ӊŕrз(sVt6h:)0G|unuu=aQRCw&Z8@RѡX"i׏@LI8⑦^YkhOs ßu"b!@ C`NʸxNQ=Jd 뇂Z4=9ЉޜVK"1؎S&DkT<o8a?dQ"cJUƠǻ|;H?Sq 0GJ ^\^*"HdPfnFh ? 49{5KZ.- m@E|ϲл 8^Kc#IXw"^{5lEY\GymP \-t__[~Qs2@<ӫZAHuoV^L섭]Ϝ "ZfhFr?zPÍފ t~ !jbUvL.cTWeeBVj/54¨:S]sMV˰Lp%~@kSblJ.jV:RNPN02%y&XZVTn.rH1Kq[}8םFʨ$|O?;W'ֵt" !(2žWV%+r5qdH7:\ΩZ^wb2q{qUE/,P s0?]Ma`i̼@Y~ل>?Wu@@4R':*OS5\ tb,E08 $;݂rikv7t=XPw }GvI-My/wC#{ ei*GXrnii!trP}R=2)a! fw!5Nok[V.b{kyPdU\%]HA\4 Гp7eW342Hy]ڂ_9)ds"РyABIvm% `qR;ؙSX٥JKXb,>39L斎O1")xxuc;p!<1VIŴ)yjQ(2oG-@<[iY{.@""H$Rŷ,v-wiHNN}!4+$,5g`bZ=rKlDyEQƂ4p.6EVgѿ[n鐱6>:?Z;l^f[eg*WV=gqrfQj?VE.H[*(Xm2_po*Uօ6^/hKH"2599aM#,vФ~EybJ_ῼUoPan{u|f9KrsJٓ:ʽ[3 a+o39yebP씹X & a_W7oro)Hj0럝*Q;lhcb)y;ۜpI?~?*he揘p1]3Vs'W6g;آ+9GVJɅ~ו?|JkA/lu(i}Ԙ5N2g p};7{3># (U.mEs6óLa ͓pVN|#^ \kbmN_Q,u$oVMx+ym qg T#yy')_OpE]B *q!Y \:'-ǮuZAJho=+Dݚ)/Sʢ23nF.̢(ixaI`K'=?7I/m듈zTFKt< a`d65ŜN'b{*Bv6a XF) x_7|7|7lϚI2]tR{xx^orgqzEjii* 7;"=aDmyBEȂ5Bv[m;)C8ܴl>y,1 B 7ןӠtәwp w|c}h?o#'}OpO=P/qs4IvwQhςo_vHA6 C <2S,뻟({ EB|N\MgQs`8Kw1[@Ƥ孡U|` L h1EV_1%/BkDgelf-%@.fAJ}&p$%psTmHV SFa[|甏iW.Gk9h C,9EEïgFUgb/G^1 U$;<NiixO[rCNZ\A5CI\S]fOn&rS hv-!wK2t  @LhO"ͺhoSa{$U8W jXaʜ i5gæ >ZGj*REI&7K#8]s=Wce]Ra-C``s\wT*-g*'̣|BfzDeL; ;"da.7T@#~8? ,C?hkA+mHI z7yʁ#`^O&>A)[\zoG>A[y&y2.OQqݼRGI:ktH<ǁMcdxpĸǷkN0qP• 鉻F_ DJ6ۨX9Jt4u:3;>m'цxF{BmSIjXG::Xk%pzn a/S91R!F85PuD/Ծ|j|af$jOm6& Ѩ'B)GPxjme;?)~к#hŵ2rXD7:;) 2(i\gށleL O-3?s$qx6 J8 !/͹d6.O4b<7/N\r")@.& Bhϴ`X0 Ddd&Hδi}hX`WSARwzIb2nZ o18ٸE 3 eS~4. 2q2A2/]ԱJТsCjF$p]9\kjBZhŽ!C]F ۭuSհIidrEciO>QjaY-j T.DHPg(7'Ƥw? \b7dLf/ 6؈}puG ,"SԨ` 氡D1;) F#.-0 y,ϖ5NӒPX`|CpG~x\ EeG35"32{&A1+T8<ӻɯg%uhkD f3<:?z.nBz.$ 7ycY+J-'ppVFܒZ:W5C'z:C|hd}}mz+S5@GSr򽔏1 ,YPJpN G.DUQeWbWAPc:n5"Uuu[(1y-TzLkQ["L @@tWp 5%<& 7Dq~u:f)|l%5v hQE쾵wԦuʪ`+ *'sk/#a*ez)P+#dɑ0H(p0J.JZ⮛aV-VA#U!)C UV7=*P+ ˣբ9(2,_Lvw[(~r_"ǼT ֻ} y͌:&foiN* 3^z9a:[j~GfAn.5~B(rW/4͍XbF?oEJ2L{n /G<\qS<1yf6Cfg6 ܙFh^\'AZrp;i%};X6{~}M6la s}<4>B33S}j᫕و<%~wAeshu'<bպlZf.{4 K=e'\7C $Ѐ]s vwZy!25[WDti Bvd5B]%emom7~qKģ@cwnvn.lƹ$s[1?\fOIu*3%"^q<ww B14҆BAV+Ḅsi 6+"fBf,%E 5/= >\N/\݄D:")ܴ6&ዴa0@3~RƶvIk*$y8)6dQ|ɸ3\/&fBݼ-aqrgU=?i(gͧ&=\@4L}ۓZë÷)=nqoz9} E6M8Ujߓ!7/k}]N͖aʎō,3|̗4Z8.*c_҆sm2r4%<Ν <%{.np&cSC'(oIZܺ4Ƃr"a*!X* j):a[d~=3AdKFɀ.hb=Q[>t!ל˛=|KO&n͜0,\,VPOP;ό8QJl"#Rʿ" ƴx t3z_)5ZrT4PY̶ws,ɝ P!B&!u>ovN8q! ?XIh+2+抆ieI?I>ЯjHGb>1ɦh2!S4[vΌjAE,p&8xdVewNvUcvNu֠V,"PfolhnnQ# 6WadFU3efU/:לó( **xN֫>Ǿ&.y)(."a"%Nua $Qcgs@AacwpEt-H/~ЊQcAcy tOIF?Zp*Zbm`hQܒV wھm׌ÙIJI /yM-=O8%ARAlZ 3FFc̨+VTaz>.0YVͿVY\.]Bl{ZG T#'UKnx9ˡ"Fdyy / L%a("n<=w0{!9 ՜I2Vm܈+ nq+z&$Syxs6Zjq}҃Y.$!4P'Z,G휊H'sIZZ|[#/Nzޭ̏ڿI?_lu 0w_d3v! o[XÒsːU-i ùD&2ߢ'!6g> +D*ڋ05p"])lƤ`ۈ^ i@UꝀd6n@yϸ>h*jb ژARflΨOͬo\Y,H*S>`H<2Cq;5k8I`].FrMG~u+SYxda-ҭlP]f`饁(+Jar0 d5μ9ݏ }qڮu.l )dŠ3 ܎M]'h^UHG*Nεs:ƞrrs8r[xXaJ&m\_t7R~[tt!F"*}(G1?DcZQg`ZÕYF7{ya1R u\йQ~: =?|)%Ma(WJ _`|v YK#[df{ 'FBOݒ(Khɞݨ5`ji;؏&;[B׬՟Q|Ú{" |Q9,go /S3aLJ՛dO7觰w|*P%(C`2c%i|>4dHShAnquhbɋe%8U;J/Ԙl1(dtB,+d,/2BUfЃGv]~[ТN׍ZyTmiT8HT8msϼX2LlGzw,}=C签y`Am/*d>[܉f,`l߹ٶ $S2a+Lf'D7풮EJjcleIj u=N %!լ/|UI0oB,FU?:Bz\q;H3Zwp_D;uLKexg;mCg_IPxsR{ũ#솶^#/b4ӣ/{-Gl㖴A4α/Uƈ(#N Z{'ů`+! =B ܎:,`AgvAbJnǑi"b7Pחjh琿yd ܳ{nH{$`W4@oG8^ 0zo'Aq4H~.oo=3Zp"/G@>6b`ˇ/A;@|bFт*}uDlRLB jvWefi!h~jqœʎRhe4mrH4+k7Xr)#L>wꊗI=ZuBEǓ*u'XͼlsN${~,C4~2`syA S׍R'AxB7iXܘAJQzMNC!@U|qa FKF5 `6iř7C˖~ihLՙP:, ?w;єwq鸨N.X2 8cUBO ) rȫ/3m7.g7`^4Eb omӲa(7!wjux.FwSbQ\>t){8lr 浴__!9I^@E3?0ŶN].Q ӕ_;< ˿AI7p:H9X"F 8Xk/@曝hr!"P <=/-AɧYQ+$  w/^\Ep؂v&M  Sa?5^lh9] 8vt0 ɏs)iv@$g1{N4&k2]-crpPiqa~8f`ǔ1$t>Y cYqXU,Hc=h"b]&=;}R b}iqI-٩i~CoHRҔi,s GUTS.Yɏ6>#Y(?K"8Oqt_lSe/z9b%I3)BY_띌5ф&{mM)8pcP#")"=_QA(sU \YJuJ<>EA{76($TAw)PQ}jx0Bw( k\pg>JN>FZB[`[r 5M(l["@+yFDT;+V+?GS\7>0}^EjA/!0W*f!ԩĶWJmU.632+(: RLcu@K5fuxPZD ĺ9ZwTA1C0v)eI^Y5>uYkE Pezx뼇q}DL?iccRӲPrIUhg ׁD[Dh7aQUjq{w*֟`pWtCˁI- …LrpȫM9-T{ z{xk"r~%n;7y1!*-]_RK N%ю>qa2 sgupvNs#;_i҄)$AR-_;'!hy*T3QpVBz _  ;cA%L^-zq'9n89CȓfYҊaqoO q8jFO3S1_o *JVT5^ݕD Lu6Pv #ǺJ" KdŻZ4cVEQ(l s <"e\I4 [.5p,~$!165q ߃,"<')67Bf^$]GpiMk~ :g Jxpi>).%}ىar@SC7[s *cL:(w]Е VΫƟ)xTsb(QD߽OLJV%MZnw/1Wo/KyʛK&Pi'j\+,ًoBx9<Ւ6Aaj!ۡs]I/^3d | _zpйl?끵b"HBX^M@_HQ36:ͳF=KJsG-Aps uo~,1Lf#&i 2u&HzPqq).ֽ vz0Dlگqz O<1{U*^QBA9\x[weJdyλ׺5N37tH1<pƨwY}r;S[6 Y Ĭ,2%~LiF>W+?5ˎjtҜ=LHjX>R>'-80 s''j5KAK%= ^')[rnGMmڹ#zQ8|?yQRwǟ"TE5fUغD;M4 P;;OC.'05OR&q=q6{aTN3庆MHA-9'Խ {O,bp16.c!+ܦ .]}!JT#7usY{$sf[0eGБ00sWu CM}MBR9f3٨wI|v"+jc~'*ʦ̒,/-MFv-1f1f/5 UR}#`TMUǩD*ohN(D, Xa/b wBY:<'.3jZ5 DҀ㡃"ӳvZZ&^vInz^R+\}ly.H5g\ܻ(DO[N&u3NHe<,ȕ8σK}ԣW!tV I0MmX̣πz._UlW x!`@3 ,I4eGg~l*]*YĎWK uZ1jgbLp(<^NJ*`W2ڍuJ)1b<4vY!y&\|L2q[-d_v#J-A@{u qw)u>&Cl7!KM5-,qSfz:#w v 5ŷXU3)W!h{dФ 3\D~F<Y' rnMd(mA F}ǭ]?.vfW!Y44[$8dKJO*c(^xi2}~̒&s>5g?"3;{`5:ERºO0ⰶٱF31Vu?YwdfDy^'<2M֪[$]ܵZ{A1 N֤~,X8wm,XiB 0 XJ`lpi ?2\. h]?ZɃ;NVS%x5(K"x*?j$Rjg9<XF\WT#cP *vpZcȖ Fn:<5۝JʊO%(һu>Ą 3\}u6}Yq0ܪ4O^=|4o ߷;b}X_WRjL+_֯`j].ʚ"*[ tPd i[,jt7aӾ-H<Hiv@LTهߥϓZf'aT\v[\ap c|fFhBck_ :YBuB u6bNU^UkE9w=@][˾H)EJ=->k!% ĂʳmAs{6\"sD~\1\Al' `O $xъPb o jnsp:ھuJ~_OJӳ%xVch~aod%JQŰ '?H!a0z<4X1.19@$RkKTb.u_% ]褰HWaX ,tyaV2Ļ)9''^ZΞiwz$*8z\3W% 1HC c ѥ'YS .9d<DZ~Lv'iK0*@|w*zͩID28O/cڪ*\H$(]HBO, u& >}=!?lEO'<@1nmLUJ[:&\U2F#z N2E*ОlWI:Ӹ!?-B#@CV~xBV-gzP\xM~{RŐja})OK!Ms$;U FLOr\@6lΣJy1*: ^1Xsp*?KV,kE'fj( Ή-tm"9sztycx:o'~ƶӐSwvE]/"xЪ$#+Zo0[lq>獳:UjtڬL*3<88>^' /fG+:^20)HYg$=`hW5"qg_<Yt!./a١ۥOC@AFZeClA wK3 Vczޖ@`Hzt^ 9v5Vz#e;ܭ y}E `)e:?Aםg*-96Q`|Ryhߖ?ӷ'zભה_q3n2 vU@(0f%/Y~Lj\`vyr9qCXEnT$tK;Q7fL ``kz_h@{/l?t=L͡Cԍo2PCawut~ޖ< A A腻%\jp3)78< HBupʹ ݨtwt箚-}ۿ2 h}uR4$1Ԯ?JJ.XZKW,U} XKe{}0t~_e?/Db|U+KSȻay8P4 14^! ԞGv[HҊT6V/IO-v6Umb[գvkܰ10+fG&9'A$ނĻѯmk+W/.矲BT&a:"XX\I!mvp>^.YATQs#;5U*/Q >oc7@+ ubȰ&\LؽqLRq7.RB2/Q (a/4hZ xp2 ?u7z9QmPSTڧVW-N%+29Bgu j>[uWT"g!rW':V7EJDBN& Z67 KxnH$'cHJ9ҫ^N8Q?#"CrwY;)M!v)5oݩ,AxC$aNن3gy4)ucG=j~P1[5777':xGdO6{plZ5JN4``J[v68j ~ϼ^GOx]h]x|r}ZWDf^-Huʔ;E0B huu{9FO/'Q=_55W/.-H@$߄'j-|ydEҘu~kE"x| zõW\ImI$r@kI\Ho@@=/ ?6D&D)@EӮo,=?9C1꺶s{D fѽQEyuzc yǨSÓE) #6{HCh3F˸:4gA>W@}zl ݹv-Qpw2_< ")Gk4rLkJ<ʌicEao^Scj2 rkw'ׇ-k5\Hq }xUKNrȡ  ?[5ٌSj._}܃iԎ+K.HTs̳w`)X[.gm̬BJJ%v 0cߎZH 9_n`U}pU/nqp/Ŕ r |YZIո[RrΞo:D)6+f9h3jC~)+ 0X&anTekh*Yܫ*S|FպlGL60l>@k;Z{7;j=yj^-'ljEVcyA_~vW̝i %2WUq 麄ʫĘ-4g6#c睓"\Juʆ_6[6z=`YAͯRPy'lT_='p/cFZBx.yDj0Qr/1GUsoz+Zɜ E HƖܘ[\HO-*^z.Avst5rfC#lk; -飿#lLÛlxqoڸNK:S{}Vdmzmap:~vEC̋%Q>r,65^,=v,?d:! -~N[tI3 */]6X`!<\??у~ b"i!xK ~7hm$v?S2J*4A3&LzGzed,7dyn8ܔ BĢq:U]̘"ؐFtх$!WhtiŐ8J"7di"niCN $mqN!k ՜Uhil&Gt> bJ`>>4U׀JK5a(+5[t?ӍqI9CIp$w+otqC29e#E[ժD +ìGAk/qJ m#*ΎGI5yMsr,Oc*|aC "%d07=,AO`FC"yW5h&t;^gŝd#Ghsn4{?3unv4ƀ?}>܉Eo5g!0٫˷ކ@/veAh| gXCH.(&P3,KJtO;%mA>;x5lGhʼUQ՝s:֋FѺѝƫi3P=%m$xEsGAe;SO~0f7TɈ,|zE,ͮFhİ+eh}#i/V^d-f/ !7fJQgPX>H?L^il[ :4!BP=gާ>vy'2ʂ9:Emff+Ijx +Wg{WF/\$,G_3mNvNJ۪ʌ&-@ cȐ/lٙ H _-NJՂS_( +mӵӶ/j/@#O tpDI5h"].KUH(UkeeIwxZEORA軹#s&~Y}{!|tlE`h6wPfJV5aŠz] 4+4D"Q n FQe,83cgB=Zo/P>ɦ]b`~(?iK FVƴflXr3I'QK1ηjBA( a!nyzS>^^{Ӹݓ<ŴVHlx' Vx31T˂?v#U'$^rng:lyj&o%7*jTv#~ cJI/а < zQZ>֨FK{hqZ'11yr_;{ x=p/ԩ:iY8zc l7}Kz%B>( LuOTXJi)roH]S3$]x׺_x譅|A b" 2UUvߝfb륲Z {*uhU;/e9 ~͉Sj8 E bx8+ kz LYF9?ݶd8YOqN@2A(}]fppJ &b0 U"0^/SQ"pkK90rdYݲiE:X;$ Z4ΕK>#2nO+Z4h1C(`Ἧ/s){t$̅Q|ARx" ~/[?dxded,ГHl}ȼ|ɣПve>lV?T!ICG~)CN)\pt5X0޾zMZQOk+S@226%矋`^JK<Y t6PEgZ^w-wJ$vDuO9kDdtO6:AiW0'$2&H) xD|BbʘXkK*J>?WYA Χ}uW Fu8%{|RF]ˑWf&20f h'gYc;` (м8YAfY{: Ǘ\p9[rz"D'+K [V16t8j=B}DY0̀NM?q9Smn87z]pxix!NKʜϙ<-#zSD:we`N2'8 6|Bpt-OSrj5!fS,-##}=N]GK5ѨY>?5 mJE_SR*/ )J*,Ҋv j}\d:lxU垔Ut@,͇'`K(YHf~%/M6"/A%_alK@.MkqQ\ЖqqsZo DLtRA(؞1" .<)nf\H ( f"9CTfFlBdJ3oӹ!hĩOGS_*}iŨn!C {#9e)*rBris[HT_ 3!}<*f4*QרHbske2o(&oBӆ{)beH Ų ~̂],hFRҍ̭y 15[S !:(⚆5=^:9o^P>1 /A3bRýncV=Zwz/T Lوr'GGĈu}'{O塖2z8!eueL-t(Mpc9PTye,^APƚ(vf~U}?7D$ F3E frSݲL}dm d5c^G5)NaL# 6FH٣+~AyBmh0ƽƌJ nR!~b\oѣcHh!Tݍ-.ptýZHf魞YQ^qc" Tf>\JL,u<3{Y3n\H%f^@(Sk X} ;R0N=+VNM# +t3S&}"$"kTAX*K %$ ETg+(pރy~"  rꚚ.x+W Lak8ؾSf79-}E;Ncw:ZWu!4/-}p ӥ-#&fP ]OϱkWad=M`= j21?y~b\ S?v?-=>,WyޠAcޟ"BEL.L{/~ o0X.KCilWIO$BfN*삝|5_tȐFh`sxyDU\j]l3D< 7^U|j]l݊kze|@^ޕ'{mUiK*Ɋ8cdlj1xf^$x& ~Մ`xg Ie*bCN7хrSB0pq 1Kށh폣Z}NvX[G `JPUhL:4b{&;_ ^QơKsօG7}<9 yK,G ﺓH+lЖ (uJc >S1FZarI~|@ZDdvi,_4lEs`JȔ)(4ך = O |S:KRS3m)/FIS>YD6)gFs.EgP{K ΋Jwjt܌% xro rxY[wO|Uߓ=H!Kr!+]SӨ2nSXVJb})0u@&PBQHq]j0Vtj}$@-p'DniQ|fc/h\B|h=}I*t @g1n:S# auw7ƨ ؤhuxI?$WjEY-^woD7+޴ԝΔۑyp"9: 4TDԞsM{zЁ`h!W5D6,KHjCu<]d&;]U0 o=;r4RA%3Nd-c5ٝ_MLm C/ID#9b3XLmj{h<&AGEK" }ʪQ`C89>ZvL+ӿb6M[_im;J#·ZP4R,iā |kl_:94DN;a<ǘWT}y[p4@[6. ̕gơS+K,tnܙ+HC[ 3u;W1PQ'hJ|Z/'>sSɟxÆf(Kyϊ'Ϧ:uy$N`xnUA=&r!M#d~ yCI(P`5ņ4]aI&sCNuoV?% Tϥތ0#xCiq/ 8{Y&5ɣͮʸ=.'>`x@6Ӏ⪢ 5Jj;*}]Z9t:v[a>RrvE=a]֣W-Z slº+'}DpH^9.M[E6|täj1}XTr ߼KVQnיϳp4bA9lj; yߪ]h?{+TF2:AJ>B@J~` \vZ;09:Op^)l3?LB |~g <{oFy+_.] //` KHw( #iKWziK \zNo=/6~@kz+JڂS)g8 "@?ORZH@{0َ˥1a_]% cOt2q3ɘōNЊ}A|Q-@Cw®LT-9v($^ c>?*LZ_dž!8&d2FZkI86y+i=gGe+6lYr_v&nB+UG.6njG@/[E}ej BD9'jw?蓛Obå 3uؾ'XC9dUVEuFAD$%\&U.62{bVjR eDb!hy9N 5F̺X w6Q#ZXP;2.M"Ǜ\)l%)?)Hil>a0dvSfKˊ>v%N~&"h"O IY&,cC Znu>8i\\l@GjyZ,lT(کM/Gw$o.hTo#t,+PAэA%5wֽ.޶l 6)]*=M!勮WkӞYS_u/P >ޓҞFEp)&}v ϋt:/ŴQr/[Gyg݇Ts,4i%{EՔiOT\@Kj}q+j~NevswrTnJ#?TgH*;g^6 H_دzcO萗=DjT"\t 0#Y%4һEh SjH4n;?/Ā$p߯5Fh$'֩:ROԬ%*u]$]It 4+X]ss":2t,גs6+͔u_ $:ߕtZBڞ%[ kpZE3b02!uQG9oC4:i _$v)$ꊯR} xā`>i;iA؃)&JEa>= ^ ̰1ϓQoO_B1VA@R["E _| sS8?Q]]SǴjxhun,XRQd灢Si7hH>ր-fumWVWEo$Q/ ݔdcZp1[ߩKZfC }daHcԁ!#h;2! >ͷ=wR\+`JZדAKWp ',c/ͫ4P:q~[Wb*xF!Ė1O;.A- pk(/$]ğW|eFs@*%lHCiU~t) Ol PpqΦzV5B<gIz.|3SiHOgu~Fc^8UCc$hA2*kU㴁, ܰid}%wʁ,~?ntKT.Iz"Kվh 2c@1EFld.1Ypy؀(G/xZ5i(EHsz<:/kp Œ:]ݰ 滣E )EP+@PtaIMJ5,/N7[ŜP>]޵LCQrW΄6d qﱦ`Ο$B@{S9Ϗ's7(e _@ǘp &Ws$ROc}xx;(MikhMt_=Ǘ}MͿ?yws}X67N#Q<֞Zء!d/^9IE RH[ㆳ+@ m]bT1 nCB2nR'Dz\lrg(3f?/U`u(I{âaNS[HIq벐Ş(Gѩ ν1\H՛{{9վ aCBHV:M5m_$m"\8pSݞ2ز&2zC(VLv^NC`8yQ@iVpa(EPP 0]lDgAe q`K9)yo[7 lZ.d il}_);\7ڤ}e|G+wlv>)RDu5șM[.K$%J0n9Pk;sZyEƕۋ7`Md8V]ʬ`A p΂Dm 4]Q(I&N&؟"C{r?^;eTm | 'r\]EdWd2,X|kn2kVHBpnS*h /4Z,J>ZY@Gj!s;*  Gش-v0MU3#<˅hˇ\/%/*ۢV "k+p k5C:kms8,O7Tܙp=-:0^\~ٞ`+3ĞҬEx*Il7NIepSFݻWGCj1YL^B4#(7xf@lv$ ]p1Z+U g `?SF dz MΌ\>8 }?a=kOz>;Ze4+CKO^_ns-ġ v&5.,_•R.*J*E=:N1.AEygR {gǫ1 F][8_Eu?pyBϱG]Ȝ30*8,6X?s:)%.!?|\vMAِ/fs!?a8a#9Ch{Ki/)uH{3<9Vy4n5M-"=l+ n'P{?}3Su "WVHCA}Z6h hr61J2x-e1.|BZ Rpyyܩ @݀ngt2-%-YIg2[ñJ/םMK ,?Q=C㌟Ol;E,kesPart8 T͡ai0~bQBW-{=D(;?t(#3u9q1o1C  $ qJž 03r(eqTj?+xeH3Sz )Z: QV6)pO=.?̿T`:CPN"HdyPR+HrSr|֧Y+?Ƅan$#&T 22V[]Kti4il(yobqٶAu K[*&Y꓀ ,]-c4H!@ QPH2sKpu~~H8}`O$A=\(5CR7I>bRϊX 7*KtqN ~̱8sB֯@_򎟍; b0jtjKh "1)Mcoݭw (ј|e7Sm} :-xLV5znI0%g i;G`%;bvy\Qxk;tӜ#"jmm($KR[4gAj|n;20֋WT8¯oAIWGPJI[U/2*:RԂ.p&yeH-OX(9&Y8h3M ^-(-_|T_'V0K;"Wq4B6j gKe^5-ZցJ,w?W9s.Q}䣎V H&Q a9z+m ]TF͍IJI(4AP yHy;9x5(I}qI2\#{0M1mWuaw⬁%(w.1DF-{6\>@ D֧u#ŧHm(CVMu˔S%ibBƆ& *r :CG<?Tc5jSRH fRQ iJ8wemkd^t%r~Mld`TN4^I6S$ɵpj?TPogcǁ_??DŤ>=nFZA-w U<*N7ڔPw+䶁yHiϨ"E'i%5GlNVvd1 [)5*\n^[6 u M09B Od2-K_ui!ǿ\qOTUtu VZr1iyt6,k4rKξ皈E;B//)[dvBvs{G]#{n&y m!<ݍE3TՇ+ўޚv\n ̭J 5x?z)HoW[ofMJESzn;b\-d"sF g\\ JcOHhTpYHTJ"w@Q3MLv8bl< 1#Mytoƕ;|5h/{4"eWu ɢ.̴τ1XiBL -6VwHN'1i.*7”wNȻW!syY5,/P/n ]fX \r}uUPdqU9u%MN[O2宦*ظa}}Zk^aϴ#geЊ@sưWdJКeYuؖQS^8ۄ[+&W.(Q1Qd2‹64hxl wpn $V< (1;Hca -M 1ˎ@Ǹ`YKas+n8t4\֑)ײƚ^ޘa<ٶ`3FMinj+C6 !jeͧ+< >>41`~@a^Ma Uv\T^ YH7׵UF0y44?=/[X,:Q"KL.f)H,S/_ ԁ$`aK"3[Jgh:#KIF(ьZ=7aKA8dlZmh3!܂ 22N)+34&ed_QJNRSbC%ވWuPT=d 6l]+)mVfN;:-rHihVůg_[krf״NFS@&| U" РM$#{.<йyV$^S'(3wpz g!E f f,$36G]!'9hvVX4ѯ*Kŷ vȡ(:e^ Bll܍.*F ՠ+ͮ}MY@n?ݪY2D. tv0KIŵAVA `ՐgeJv [M,ŗ:_\G̼Oͷ˄#!nBF@YKP((ǓShm^G 3| YVgo(XR(ζ>. ~[<Ls9uPɶMFS'c4?~}3~!qwN|e^_9wS}Ńd6VzFy+ %&M*%sϔTXP: M-ܞ,i܁Qаj0Ǩ9w ml-*r)v +f_"5H6n6 Qo~4f5zT7,U D'N톎\a8 >Y Y ףeHG,LƢhQohWY]~*®P!/ SfVN?XH翲kQLK}J1w~"«fRG5E曇M5P& i^:wSvE,ߗhT+3(-p X|El*x΢;& ;o{.^slm(cbBs,)wچ9\9~6W6/:e.83CC GI`ݘՍP,ϙ:B* 8dTe0;*bM=Į  ;d%Qf[z}~lLj%ꃉo'<2Nmf&{i3Pdz+0X$ʜY@VCs6~, (MK ;UƚDI EW7!DG]fmIXHG ,.0Vr5^!:Pm_z3L\VoQ{P2&57=#G`J&#Wмqn>BsloJ65"v,KXlߜĈU5- )RX$ iAꃿF!flm>lEYsfUaWĄיERl\yQs mΖ-ʛdpM"pZhp#5f{"7dnlžOE<nP)PVGԬ8=oq =P JS^RI}r,:l^J"-$atƫwA]wAJ*JNοBD8<DŽD<:JB*v!ABƋ2is~dA`^ru%˰ %%hE!mЈ @ |&HqrT9=03/9|\/-E3JS UNb7ȬhHNf>o8sr`_xE'|D}f2k?Y4'N֓TWqph~LR>{]^%[u4T$-jj$ds$rR 3xV$ԇ &?{6):D^w.q*:L߆hCr@SƱC)lvdȮ*sO#oq&*=Pҡ{1 xfa&E7pL Db74nqANքresIm eU1=AjOܺtR&@F.!sַ0^"3k"=b59/w%`ǣÄ́ 8x)TH cH UD pSln:DvtAKmw?^ <ȓ(ɰ]V;!|E!Bl  / rȪpr} G![u1O\J3x duPJI:_) ^aA6H䄛3*]f(? I//LL*ـ~.)/5MܠIM36EaV,!& )cƿ8o Sz<&C RwqgN|Sڥrz~1Aȑ;wԿtS4p"!/iEmL l-mAҫb$ߔ g]FYA4+"䳋ItToPuuNqM_9܁ۈlh 8n?JĢW { HA'm*{}z,)I}P v<2Ls^S"p;h> MnrdL>?2<|F'FD2r|9{ iuVMACػXC^e*t)Cd^֙H(X-?$%.:9!i}AP e0 R#Do9:W*;`1A>>~@S}dBh'՟랊^>ْ8v|F( FnތZ T! u eR5۪" ^s)&WEA#w>4SlzCsE9S%n!\@q )$g{,쐰o3Gd -W^2>.=}~,쮩VPCwa \GC8zfA;ٖCqf`>n.+f7H:l1^ݛBZec䵏DEڭO)+ ,U8[T\g[CЮVahm38b.L ! @2Sm=P:-o{*Vw ڎpNQU3*Pב g}*Hh^A\@%cRœ=%)gK9 Q5Cj d˻> |Y Vd,c~oT׷|GD޹AIӞUef?kzV-t(HLQs*3qmErj%JL>[2W9SZy^zO'K`!r@@JNXn\!B\Q5 ࢋNYrلBx3aIvdf4vqwZ2̦3}pLRo-;lJwQ+Xn0,WvM]ARXx +TOϠ2Q7~Dj\mI$ao8T9E*K }9˔']eh%'xP 8Wʟ&7 Р:sFѮ'>``0(>Z #)FݵYzfveC%-yDzz>Q02VL<׿H1v2z`-[fMr3{RcCӃ\EcOQ{pi}kC ӁӂPrZ>eKUmIN?} EwW4>_(HZ(`339#hr#h}oЦX;3gXDR.FQj#i|T>* a5*+E)@LJ_r^,C;_"1bp|Qwtde*b^N^ž vIt_1\:LU`U-Uܵ!ģ|ouPlr-V٥۴-2] H 56l1 (B4P9eU}x8MIᦇ,V*5d_'K;X\Y_~C`GCAfu.j3+t^E `av̠~Mђ4j/8ls.mM@gr;\5κU,Znr_X1J}i_q==3[iTIIgS}T}#8D@}\7č}šS\ %Q" dUY׮PW3hH\"$ ^wۅKVvLD4>`}id~MQ0&p2^x6'B,g髟2BMlN]6T-9J -2-(8,@^t ͱ9άB+Q=<)5JJ;W6E7NdM#+uu!v\Cw:9~)g+*E$ /"0h q @nM;auO! :Q(Sc>+uW.% Ch po6A-?iix ԭpe]IaySKN h>{*2hP7X:\!qi7Cߣ,Jh%KLZ)b'KI#Y*& 0vIzDm#M$7/UXP 5l S(Z%l5 ,Q+Z%gz0M=VS˜ҠڒvDUըַlhՂ-_'F0RS^Lo\F% Ē7z <yGyq,M_BCY\Ћ  3!^o !GeoKEMP)iLo989h[a*RDv?R$}] ?0}8Xn%@8'O"8d/l z ؅FVL[Vu@;3օyʁ8V4h SC*| 9~7J,ZY+% y8-횊u!|c+Z:f&Zr3Vÿ1Xvo>+!M dMM|r-mpd?BHa)~#u5̵": 2&8~y8Tb5[ \]da(,m  ]<]%Q$djQqB( 9简J&_:<˚ &t Ŝb;K;f@ZZYUI@iH*cR4ʆ 2Dā>o'6 hZz'ft\(13Yq>'ڟO)X!d1 V&LnJ'Y/g"`}c(2p o%ik,kSɽӺ4zfg7bi0|-t죥7dëSH?_j?zZq-/WJr2-p=?j弄s~&UzVKD"KC  ?,*[X&?F@2<c%qOd6Gx_[Ej#.6473ci3Xl‚S`{<&b9 >1yiXhxVQS7w,Ly v Rn7tA}9$@0^upL?MAfC!ܜbGMu[yMjey;RW*& QLeYU9 IN[3pAPsE1)LW촘[L;MHkc·q4^۰hБ3ySY#Zm^i rn>$F2HES˵j~EI#weU8dQB\hE/;&H8dȰǎ5MvQ6t~L|X"#*}űUvHmyZ& JI^ 2e ڏz6ɽiR}?좚x: 1l8"a `}UvyGѠD{R:yp40g{B;D4Djf 9mP!ikQ"EhL÷nJD")Gǝh7] nH&^ )eg`npzǙ6e/eQNćL% %l[0K9WGd m%hfѫHQ@y[E/{;@)6}f⻋9K(pi9v:md?%&P=/Vֹi@*&"\hUJN#~) JVԦElFv N; TK{E ,ۏ+MA=Ю:kZ\wSKHOCEa;mvF\?Q/k їYa,-WQ!ZTa'$<ςA 8p2V9."v-$†;<\ mѺy˅xHJZ yAjFO{Mˑu 7zPf_^rU;R )6+. ϛtNHc Y 8k!܎<( 02&, MoTSʞyE+2^HH+ן/}_?yg~:7B얿"/X+ )΀`; $%ZmR+l,:Ce"Y TiQm߾O0a!$Y% Q?)wBz0eD`OFv_y[=y,[|yD ^ vOj NlG*@Q q P84iRs;#$w\2$4VD/HZNV,'­#^$wB(|8)I!{DVC?U儅ⷄ1 GJ;@KmfF'Un2 $v t >y$?={["{"X~DƇ/9$O`oۚNJ)輊K$"j!!B80{ $B>hBjSrL?f$[ܿ^IDcȠT5E;^PG"AVYבKXY˯˅ P<=<´ Ǣ?it32o                   ',,+**))''&%$#"!#     /--,,+**)''&&%%$#"!!     )/.-+,*)('&&%$$#"!!     //--++*(('%$$#"!      //.-,+*)''%$#"!    //--,++**(('% $$#""!!        //--+,*+))''&%##"!       1 //--,,+**)('%&%$$#""!      0 0/--++**))''&%%$$#"!!         0/--,++*))''&&%$$#""!         //--,+*+))('%$##""!!           //.-+*))('% $#""!!   "      0/--+ *)(''&%%$$#"!          //--,,*)''&% ##""!!      //--+ *)(('&&%$$#""!          //--,++**)('% $##""!!        //--,+*(('&&%$$#""!!         $ 0/--,+*+))''&%%$$#""!!     # //--,++*))('&%%$$#""!!       //--,+*)('&%%$$#""!!      //--++*(('&%%$$#"! !      //--++**)(('&&%$$#"!         //--,+*+*(''&%%$$#!"!!       0/--,+*+)(('&%$#!     # //--,+*+))''&&%%$#"!!       //--++*(('&%$#!"!!    //--,++**(''&&%%$#""       //--,++**)('&&%$$#"!     //--++*)('% $#""!   ) //--,+**)(('&&%$$#!"!!       //.-+&*))('%&%%##""!!     0/.-++*)('&%$#""!!       //--,+**))('%$#"" !     //--,+**))('&&%%$#"!      //--,++*))('&&%%$#""!!       //--,+**))''&&%$$#""!!      0/--++**))('&&%%##"!      //--,++**(''&&%$$#""!        //.-+**)('&&%$$#!"!!      //--,+*)('&% $#""!!         //--++**)(('&&%%$#""!!         " //--,++*))('&%%$$#""!!          //--,++*)(('%$$#"!          //--+ *)(''&&%%$#""!            0/.-,++*)(('&&%$$#""!!   ,        ' //--,+**)(''&&%%##""!!  '           0/--,+*(''%&%%$#!"!!  9         //--,+**)(''&&%%$#!  5        //--+*)(''&%%$$#""!! '          . //.-,++**(''&%%$##""!!           0.--,+**)(''%&%%$#"!          /..-,+**)(('% $#"!!      /.--++*(''&&%%$"!"!!    /..-+*)(('&&%%$"!"!      /.--,++*)(''&%$#!"!!       0.--,+*(('%&%$$#""!!     ( 0.--,+**)(('&&%%##""!!      /..-+**('&&%$#"!        /.--++*('&%%$" !           /..-,++*)((&% $#""!      0.--++**)('&%%$$#"!       /.--++**)('&&%%$#""!!   !      /.--++**)('&&%$$#"!     /.--+*)('&&%%$$"!"!!      /.-,,+**)('&&%##"!     /.-,+*)('&%&$%$#"!     *  /..,++**)((&%&$$#""!!     /.-,++**)('&%%$#"!      /..,,+**)('&%%$$##"!       /.-,++**)((&%$$" !    & /.-,++**)('&&%%$##"! !   ' /.-,,++*)((&%&%$#"!"!      0.-,++**)('&%%$$##"!!     0.-,,+**)('& %$$#!"!    /.-,++**)((&% $#"!"!!      /..,+,[nnml kkh4"!! #Wg]% *_`")]] [~b- HYYXWJ    0.-,+0Ă4Z! ! BWR<[$j ˈ     /.-,++*1߃F"!! R;[$^~__} 怪   /.-,+0&$ #"" ,6Q< [$ %[   C /.-,,++0&%%$$##!"!!VJqQ;[$6?     /.-,,+*0&%$$#!""R; [$K0      0.-,+**1&&%%$$""!!9`HHR<[$-       /.-,,++0ZYXX;"!!q/#R< [$p;%     /.-,+*+1Å"!'t,R<[$.ݯh"       /.-,++*0Ȁp"!IQ:]R<![$kM      /.-,++*0&%$#""!'R<+[$ (Hx0           /.-,,**1&%D$$"!2tssrr;OAb# f        0.-,,+*1&%$$"!` z=Uw       /.-,,**1& %$$"$֠$)v      /.-,++*0&&%%$$">pNL"'      /.-,+91&%&%$$"|: %j).DCr, $u    /.-,,++0&$<,!.ִ~Hɫ   C /.-,+**/&%%$$#G` BV wc |o   /.-,++**>E9&$%$#,?='!58'%:L^I6.@P[F7 *!  /..,+*)('&%&%$#""!!     0..,+,=A@@1&%%$$2;::2%5540:LVRF*&(' ##"   3EE:. /.-,++/㊀%$)$z ,}ްQ΃ξw+  Iр8عw  /.-,,*+&&%$9?L_ L3a /.-,,*+h8&%$Sa1ڀ gH "O1%߀   /.-,+**?^&%$LA&J28hoJMj΀V R/VT$&5g" 0.-,+**2&%'!x(i"A 1 | U,   /.-,,+#&%68@L x[+ + /..,+*+)r3$KIW,t+E 5I ) aݝ^8 # /.-,,**)EW%x%FH;, WYt 'Ֆ= $ /.-,+**)4&!m.D J  /.-,+)+2a!R0? # 9 y$h  /.-,,*+*)|M>!8Ỳ48 + z.c  /.-,+8*)L$!%Q+kfU  E| ! "0..,,*+))6"!!5u, z ` A}P /.-,,**))+j"!!Z;g$ ? sق,  0.-,,+**)(F! = yѤ,  pa=x۸  /.-,+*)'T(!'[B ;ހx-  /.-,+*)'9""! ;` / u^9݀ B;  /..,+*+*)(+cuuttH""!! ?po_! Hf.]e> bA=aT+_^X Juo=   /--,++*))''&%&$$#"!     /-.,,**))'(&%%$$#""!!         .--,++**)''&$$#"!       (..,+*+))'(&&%%$#"!     .-,,++*)''&&%$$#"!     ',,+**)('&%%$$#""!!                                           ?w `~}|{zyxxwvutrqrqonlmljihgfedcba_^]\[ZXWVUTSQPNNLKJIGFDCBA?>=;:9765320/.,+)(&%$"!   ? a~~}{{zyxxwvutsrrponllkjihgfeccba`^]\[ZXWVTTSQPNNLKIIHFDCBA?>=;:9765320/.,+)(&%#"!  x a~~}|{{yywvvutrrqqonllkjiggfedcba`^]][ZXWVUTSQPNNLKJIHFDCBA?>=;:9764320/.,+)(&%$"    |~}}|{{yxwvvutsqqponmmljihgfecbba_^]\[ZXWVTTSQPNNLKIIHFDCBA?>=;:9765320/.,+)(&%#"!  a~}}{{zyxwvvutrqqponmlkjiggfecbba_^^][ZXWVTTSQPONLKIIGFDDBA@>=;:9765320/.,+)(&%#"     c~}}|{zyxwvvutrqrponmlljiggfedbba_^]\[ZXWVTTSQPONLKIIHFDHu?=;:\}G320/.,+)(&%$"    b~}}{{zyyxvvutrqqponmlljiggfeccba`^]][ZXWVTTSQPONLKIIHFD_j=;F320/.,*)(&%#"     ~}}|{{yywvvutrqqponljihgfedcba`^]][ZXWVUSSQPONLMcUHFDiH9~/Tl)'&$#!   ~~}|{zyxxvvutrrqqonlKjiggfecbba_^]][ZXWVUTV^QOTH[A@?>=;:976?p@1F)4M|;!   n~}}||zyxwvvutsrrponmmkjiggfecbba_^]][ZXXVTTdHFDCA@?>=;:9765320T<~0   |~}{{zyywvvutrrqponlmkjihgfedbba_^]][ZXXVTWxdHFDCA@>>=;:97643209iU    ~~}||{yyxvvutrrqponl_jiggfedcba`^]][ZXWVTTnNfӽXIGECCA@?>=;:9764320/1s*+-    ~~}{yxwvvutrRponmmljihgfedcba`^]][ZXXVTT]YN\QIHFEDCA@??=;:9765320/-,B*+{i!    ~~}{{zyxxvvutrrqqonmlljiggfedbba`^]][ZXWVUSSdLKIHGEDCA@??=;:9765310/-+*/+!     ~}}{^yxwwvutsrqqonlmkjiggfecbba`^]][ZXWcgjh[lLJIHGEDCA@?>=;:9764210/-+*0D8?;4!  { ~}}{{zyywvvutrqqponmmkjiggfecbba`^]][ZX_NLJIHGEDCA@??=;:9764310/-+*(Xb   j}}{|{yxxvvutsqqponmmkjihgfeccba`^]][ZX]MKJIHGECCA@>?=;:975431/.-+*()Έgoձ   t~~}|{zyxwvvutsqqponmlkjihgfeccba`^]][ZXXSSbOMLJIHGEDCA@??=;:875421//-+*)'21#"^%   h~~}{|zyywwvutsrqponmmljiggfecbba`^]][ZXYw_ONMKJIHFECCA@>>=;:8754210/-+*('&,D3  ~}|{{yxwvvutsrqqonmlkjiggfeccba`^]][ZXXWONMKJIHGEDCA@>>=:98754310.-+*)'&h0  ~}}{\yxwvvutsrqqonmlljihgfedcba`^]][ZXWVTd߶OOMLJIHGECCA@?>=::8654310/-+*)'&\g"   }}{hyxwvvutsrrponmlljihgfedcba`^]][ZXZtONMKJIHGEDCA@>><:9875421//-+*('&D帍\)  ~}}||zyxxvvutsrrqonlLjihgfedbba`^]][ZxyONMKJIHGECCA@>><:9875431/.-+*)'&-q    ~}{\yxwvvutsqrponllkkihgfedbba`^^][ZiZ]TOOMLJIHGECCA@?><:98654310/-+*)'%$1+2[.   ~~}{hyxwwvutsrrponllkkihgfecbba`^^\[ZgY\TONMLJIHFEDCA@?><:98654310.-+*)'%$0)0X.  p}}{|{yxxwvutsqqponlmlkihgfedcba`^^][YyyOOMLJIHGECCA@?><:98654210.-+*)'&-s     ~~}{\yxwvvutsrrqonmlljihgfedbba`^]\ZYXYtOOMKJIHGEDCA@?><::875421//-+*)'&D庐]*    ~}}{fyywvvutsrqponmlkjihgfedcba`^]\ZYXWUTc߶ONMKJIHGEDCA@?><:9875431/.-+*('&\e"  ~}{oyxwvvutsrqqonmlkkihgfedcba`^]\ZYXVVOOMLJIHGEDCA@?><:9875421/.-+*)'&i/  i}}{|{yywwvutsrqponmmlkihgfedcba`^]\ZYXXx_ONMKJJHGEDCA@>><:98654210.-+*)'&-E3    ~}{\yxxvvutsrqqonmllkihgfedcb`_]]\ZYXXRSbNMLJJHGEDCA@?><:98754310.-+*)'21#"`%    ~}{yxxwvutrq]onlmkjihgfecbb`_]]\ZYX]MKJJHGEDCA@?><:98754310.-+*))͆elղ!  }}||{yxwvvusrqRonmlkjihgfecbb`_^]\ZYX_MKJIHGEDCA@?><:98754310/-+*(Wc   i~}{|{yyxwvusrqqponmllkihgfeccb`_^]\ZYXVcgjh[jLJIHGEDCA@>><:9875421/.-+*0C9@Fy$ti    ~~}{yxxvutsrqQonmllkihgfdcbb`_^]\ZYXVUTSSeKJJHGEDCA@?><::8654210/-+*/*!B@|   ~}}{]yxwvvusrrqponmmlkihgfdcba`_]]\ZYXVUTS]YMZQJHGEDCA@?><;98654310/-,A*+}g!m.1U   s~}}||{yxwvuusrqqponmmlkihgedcbb`_^]\ZYXVUTTmNeҽXHGEDCA@>><;98754210/1s*+-/Nhq:q  ~}{ yxwvutsrrqponlLkihffdccb`_^]\ZYXVUTWvdGECCA@?><:987542108fUhq$sQ   ~}}{xxwvutsrqQonmlkjhhgedcca`_^]\ZYXVUTTdGEDCA@?><;:865431/T=1(j\vuTm   t~}{{zxxwvuusrqqponmlkjhgffdcba`_]]\ZYXVUTTV^PNTHZA@>><;:875>m?1E)4N}Om_~^`lU`  `~}|{zyxwvutsrrqqonmlkjhhgfdccb`_^]\ZYXVUTSRQONMVH[Q?PUTQ=8}/Sk('8#u  i~}|{{zyxwvvtsrrqponmlkjhhffdcbb`_^]\ZYXVUTTRPOOMZVrME^7maB܅)'GJ?=v:6y $~}|{{zyxwvuusrqQommlkjhggedcca`_^]\ZYXVUTSRPONMj}D@L׼o6LH)'IN=;s?8} { ~}||{zyxwvutsrqqpnmllkihhgedcbb`_]]\ZYXVUTSRQONMViFDBmwJ٪7G1>V)'6"u { ~}|{{zxxwvuusrqqpomllkihgfedccb`_^]\ZYXVUTSRQOOMKLdTGEDgG;m5102P4*('&%6n\v]_bSa  i~}|{{zxxwvvtsrqqpnmmlkjhggfdcca`_^]\ZYXVUTTRQOOMKJJHGED`k<;F310/-+*)'&$#!'kZtsRm  | ~}|{{zyxwvvtsrqqpomllkjhhffdccb`_^]\ZYXVUTTRPOOMLJIHGEDHw?<:9\H310/-+*)'&$#!gs$ tR   |~}|{{zxxwvvtsrqqpnmllkjhhffdccb`_]]\ZYXVUTSRQOOMLJIHGEDCA@?><:98754310/-+*)'&$#!0Gen3p  i~}|{{zxxwvutsrqqpnmllkjhhgedcba`_^]\ZYXWUTSRQONMKJJHGEDCA@>><:98654210/-+*)'&$#!h.1P   d~}|{{zyxwvvtsrqqpnmmlkjhgfedccb`_^]\ZYXWUTSRQOOMLJJHGEDCA@?><:98754310/-+*)'&$#!>=   d~}|{{zxxwvuusrqqpnmmlkihggfdcbb`_]]\ZYXWUTSRPONMLJJHGEDCA@?><::8754210/-+*('*MI!)xt&S2wi   ~}|{{zyxwvvtsrqqpnmllkjhhgedcbb`_^]\ZYXWUTSRPONMLJIHGEDCA@>><::8754310/-+*):A t  | ~}||{zyxwvvtsrrqpnmllkjhggedcca`_^]\ZYXWUTTRQOOMLJIHGECCA@>><;:8654210/-+*)Uػ+I礳  { ~}||{zxxwvvtsrqqpnmmlkjhhgfdcbb`_^]\ZYXWUTTRQONMLJJHGEDCA@?><;:8754310B7+*)rB^l*u*+   i~}|{{zyxwvuusrrqpnmmlkjhgfedcbb`_]]\ZYXWUTSRQONMLJIHGECCA@>><;9865421l~1(9&ʮF~b.,$  z ~}|{{zxxwvvusrrqpommlkihggfdcba`_^]\ZYXWUTTRPOOMLJIHGECCA@?><;986543C͵>fS#a%V   ~}|{{zxxwvuusrqqpnmllkihggedcba`_]]\ZYXWUTTRPOOMKJIHGECCA@>><;98654320[#H`_],!/Y  { ~}|{{zyxwvuusrqqpnmllkjhgffdcba`_]]\ZYXWUTSRQONMLJIHGECCA@?><;9865421K+vW&#! !r*m"  z ~~||{zyxwwvtsrqqpnmmlkjhggfdcba`_^]\[YXWUTTRQONMLJIHGECCA@?><;9875431L80F(&$#! 4;   ~}|{{zxxwvutsrqqpnmmlkihhgedccb`_]]\[YXWUTSRPOOMKJIHGECCA@>><;988UZRB2*('&$#! )'17  ~}||{zyxwvuusrqqpnmllkihggfdcca`_]]\ZYXWUTSRPONMLJJHGECCA@?><::8UC*)'%$#! ] ~}|{{zyxwvvusrqqpomllkihgffdcbb`_]]\ZYXWUTTRPONMLJIHGECCA@?><::8ye\+*)'%$#! VB5 ~}|{{zxxwvutsrqqpnmllkihgfedccb`_^]\[YXWUTTRQONMLJJHGEDCA@>><:98j91A\-+*)'&$#! M % ~}|{{zyxwvutsrqqpnmllkihggedcba`_]]\[YXWUTTRPONMKJIHGECCA@>><;:87^6.-+*('%$#!  [" p~}|{{zxxwvvusrqqpommlkihggfdcba`_^]\[YXVUTTRQOOMLJIHGEDCA@?><;9878{/-+*('&$#!  . j~}|{{zxxwvvtsrqqpnmllkihggedcba`_^]\ZYXVUTTRPONMLJIHGEDCA@?><::8667bf.-+*)'%$#!   z ~}|{{zyxwvutsrqqpnmmlkjhggedcba`_]]\[YXVUTSRQOOMKJIHGEDCA@>><:9;OL.-+*)'&$"! gY | ~}|{{zxxwvvtsrqqpnmllkihggedcbb`_^]\[YXVUTSRPOOMLJJHGEDCA@>><:EĴ5/-+*)'%$"! 5İa | ~}|{{zxxwvutsrqqpnmllkihhfedccb`_]]\ZYXVUTSRPONMLJJHGECCA@>><;SK4310.-+*)'%$"! ;֮ { ~}|{{zyxwvuusrqqpnmllkjhgfedcca`_^]\[YXWUTTRPONMKJIHGECCA@>><;QىNOV0.-+*(&%$"! ;#4륀 | ~}||{zxxwwvtsrqqpomllkihhgedcba`_^]\[YXWUTSRQONMKJJHGEDCA?>><:><;98Ap502,*)(&%#"! \ ·xwvutsnmllkjhqcb{]\[YXWUTSRPONMKLDCBA?>><:98z3<{5+)(&%#" 3< 1 ·d||wvvtsommlkjhqccu]\ZYXWUTSRQOOMLLDDBA??><::8}.)(&%#"! 貣  ·{wvvtsomllkjhqcbuc\[YXWUTSRPONMKKDDBA??><;:8EƯmk)(&%$"!Trs ٣k{wvutsnmllkjhqcbcϟzjZWUTSRPOOMKKDDBA?>><;98653205r))&%$"!T  ޅh|{{vuttomllkjhqcbauȗeTSRPONLKKDCB@??><;:864320e-EO)$"!#\   h|{{vvttnmmlkjhqccb`gSRPONLKKDCBA?>><:9764320<0G"!cVP6  ·|{^xuutnmllkjhqccb`_^]nmRPNNLKKDDBA?>><:9764327ȺP뉒y"F\p8s  y ·دuusnmmlkihpcba`_^]\[Y[RPNNLKKDCBA?>><:976532<܂-uC"jv)(r   ·lvtsomllkjhmccba_]]\[YXXQPONLKKDDB@?>>;:9765320BD)(:3ٓ'֙d-Ei  · ǁ[|tt}ommlkihiccaa_]]\[YXWQPNNLKKDCBA?>=;99764320//-*)(dMMP$   ·~}|{{zxttsvmllkjvecbhi_^]\ZYX\QPNNLKKDDBA?>=;99764320/.,*)(I"+ܵ   ·~}| zx~usrylL{dcb١rb\[YhQPONLKKDCBA?>=;99765320/.,+)(.+DîY  { ·π~}|{{zyxsrvgdcbǹ\QPONLKKDCBA?>=;99765320/.,*)(&%')!#   Ƈ~}|{{zxxsrrwۛifdcblݚ_RQPONLKKDDBA??=;:9764320/.,+)(&%#"!   p~}|{|zyxy}trqqpxphgfdccaabsuaUSRQPONLKJYaXDCB@??=;:9764320/.,+)(&%$"!   p~~|{{zyxwvuutrqqpnmllkjihgfdcbba_^\[ZYWVUTRQPNNLKJIGFDDBA?>=;99764320/.,+)(&%$"!   ~}|{{wtsrrqpsxhfedccba_nnmlkjibYSQPONLKIIT[YYUA?>=;:JNMKJ<0/.,.BR`_UI4!  Ӏрׁ~|{{yusrq~͏idcba`^݃EџhONLKIIB??=>sZ20/|/   򐆅}|{ uts gba`^aLKIIC?@wY320L0   ~|{ut{̎~ba`^Ȃ݀LKIIC@yEY4320tnC=CNy/  ~|{~utumlkj ka_^WVTn LKJID}X65320(&%$" &7   ̀"ۆ||vutmllkjia_^WVUXLKJI%X765320=&%$"   2 |uusmmlkjia`^WVUr5|LKIIW9764320}tR-!  ܃|vunmmlkjhxb`^͋QLKJI(V:9765320GڣT   }vu nmmlkjhlc`^]NLKJI>:9764320/i<%  Սxuuomllkigrb`^ rONLKJI=9765320//Ix   򑁍wuupmmljiha`^ gNLKII<764320/.,+6Mz'  B ⃁vuuw|mmkjiha`^^aQLKJI-q;65320/.,+)(&)?2  Ƃwvutmmljimta`^WVU LKJICm$:5320F;,+)(&%$g2  ւywuutnljtda`^WVU\RKIIC@k9320M+(&%+'  xvvutstba`^WVUTKJI+C??i820å  腂wwvutrucba`^WVUS]PJIC??>f70C   ΂xwuutrqt xdbba_^WVUSTJIC??==;:X~~xA/3>gU)   ~}}{ yxwwvutsrqponm4liggfeccba`^^\[YYWVUSSQPONLKJIGFDDBA?>=;:9765320/.,*)($"!   ~}||{zyxxvvutrrqqonllkjiggfedcba`^]][ZYWVUTSQPNNLKJIHFDDBA?>=;:9765320/.,+)(&%$"!  ~}|{yxwvvutsqRonmlkjiggfecbba`^^][ZYWVUSSQPONLKJIHFDDBA?>=;:9764320/.,*)(&%$"!   wc~}|{{zyyxwvutrrqqonlmkjihgfeccba`^]][ZYWVUTSQPONLKJIHFDDBA??=;:9764320/.,+)(&%$"!   ?q~||{{yxwwvutrrqqonmmkjihgfedbba`^]\[YXWVUTSQPNNLKJIHFDDBA?>=;:9764320/.,+)(&%$"!   ?v~~}{ yywwvutrqqponlLjihgfedcba`^^\[YYWVUTSQPONLKJIHFDDBA?>=;:9765320/.,+)(&%$"!                      ¼Ăƿ  ƀƺĿ ʯ ߶«ނ߮¼ —׌  ,25_0* 7WY4j`1VN0K}D.`Ҁ(wP:uYMm.@`68.j>fAh55@;r?D @@+8rE.*7 uK>֥ +0>}( 8fQ/.h LQ˔A>;X 2K2u*ʃ0Up DdZ Dd2 4^4  w4؂f@ O>69W56TD4;D 'kMQIk, գҲ.+ &@A*9rE-*6D..-kd. D&.l=eAh66A:pAD1}Ԝۃՠ}-9'yR9uYNk.@^79+{Пעy)<1V~N0J~D._B10'me'01C8YW4k_¨0,  ,34]0* {/ĩ, ֈ0I--T- E3/7 NI?=J9 )*a\,& M*A-, 2Gc7xhX0*81eP8;BETo<-.[ ITn*W0n&'&E37/j`=UO(ؾV+l5g0 <.dE>.>l+ *.-) ?, &%%$ + -+ҫO .YňcqѠ + -+%$"3ĭL.A a   -+*zX.xt3 b  -+b_(F0'->~w b    -+%$Iളj"( . b.   -+%$nCM}aF b  $ -+KN%$e*c hY1oZ *9* -+z%,l2H13ro) {\|d,{** -+0T!nP9@/֡t* -+u[:'J7 /+1* -+Fl = 5+ -+,X& A+ -+)/p]v5 OK!w0&* -+)|">. H2Y) -+)+2,!!*(!0   $ -+)'%#!       CMLJJIHGFDCB@?>=;:875421/-+*(&$#! D}{xvtqnlifca^[WTQNJGC@<951.*&" N}{xvsqnlifca^[WTQNJGU>`g1.*&"  N}{xvsqnlifca^[WTQOes:>&"  N}{xvsqnlifca^[WTQP\pd%"  N}{xvtqnlifca^[WYYQ?=99I|U  N}{xvsqnlifca^[WWqvGC?=951=n}P  N}{xvtqnlifca^[fJFC?=951-3tO  O}{xvtqnlifca^[OJFC?=841-)RY  O}{xvtqnlifca^[XMIFC?<841-)9.  O}{xvtqnlifca^[uMIFC?<841-))5  O}{xvtqnlifca^[uMIFC?<841-))5  O}{xvtqnlifca]ZWMJFC?<841-)9.  N}{xvtqnlifca]ZOJFC?<841-)RX  O}{xvsqnlifc`]ZeJFC?<841-3z# b  O}{xvsqnlifc`]ZWVpuFC?<841=n~b  O}{xusqnlifc`]ZWYXP?<88G}k_[%  O}{xvsqnlhfc`]ZWTPO\ocxrk O|{xvsqnlhfc`]ZVTPNer:>D * O|zxvsqnlhfc`]ZVTPMJFU=`g1-)%,  O|{xvsqnlhfc`]ZWTPMJFC?<841-)'3b]  O|{xvsqnlhfc`]ZWTPMJFC?<841-):K  O|{xvsqnlhfc`]ZWTPMJFC?<84SSQo{ O|{xvsqnlhfc`]ZWTPMJFC?<84Tu-45I O}{xvsqnlhfc`]ZWTPMJFC?<<,%"U@ N|{xvsqnlhfc`]ZWTPMJFC?ܮ˃  O}l`VhNV4V1"!  Oؽuslj`NNg747K  Nuxkm`MNF402^  Ou`VNtEIOD  Oށuth`VaO?pWk  Nxurqu|qfb`daVSWVJPJ?;@?40:<*  D~|zwurpmkheb`]YVSPMIFB?;740,(%!  CLLKIHGFEDC#B@?=<;9875310.-+)'&$"  ¸¸էֱՓֱܓLjܰܓ ٦ܰܓ n܄yܰܓt卨ʃܰܓȄσܰܓ뫊m̂ܰܓ}ܰܔpܰܓψܰܓψܰܔqܰܓ}ܰܓ몊 mܰܓȄ ~|ܰܓt捧uuܰܓm܅yܰܓئޑsrܰܓƁ 􅂃ܰܓ geܰܓ iܰܓzҍoȨܰܓإ{ɋܰܓrܓ|̩ܓt˄԰ܓɅkܓʋw܀~ΰhyy аč|Ǜo|ܰ܀ܰ ܰ܈ܰ܇ܰܰܰ܀ܰ܀ܰ܀ܰ܀ܰܓܰՒֱէֱ¸il32 ŀ  (+(%"   .+(%"    .+(%"    .+(%"     .+(%"     .+(%"   .+(%"    .+(%"    .+(%"  8 .+(%"     .+(%"      .+(%"    .+(%"     .+(%"    .+(%"    .*'%"    .*(%"     -+(%"   .+86, * *   .,~TE"'^Pgv8nm  .,h;`e'^P]   .,M6l%aMN!  .,%er=3>(U6(   .,L%D'1,*i73_6 1   .?*ȔJ'VDvp .+Zŀ}hF-b .*sSF϶ L$ .*{d>CɒFK~"l* -*8o,-T*If< (*'%"    y{xtplhd`\VRMHB=82-'! {xtplhd`\VRMJtbC0'! {xtqmhd`\VRv}'! {xtplhd`\VqH=8>G {xtqmhd`\jjGB=82.\ {xtpmhd`\MGB=72,?/ |xtqlhd`\LGB=72,,C |xtqlid`[LGB=72,,C |xtplid`[MGB=72,?/ |xtplid_[jiGB=72.\S= {wtplhd_[VqH=7=}zM {wtplhd_[VQu}\2.B ~{wtplhd_[VQLJtbB/&\|zL ~{wtplhd_[VQLGB=72,B]~]> ~{wtplhd_[VQLGB=7Asv]_ ~{wtplhd_[VQLGB=9Gi++en ~{wtplhd_[VQLGB=iS& \ ~{wtplhd_[VQLGB=],& * ~wtvllg`oaX[VQ@r,& lC ݷ{|lrѐNR3& /o ٪|lbQLA=Pz/  ] ԛک|ldbLA<7Mmf ̅ˆswfLA<71+bRs/  {|dxsPLfD<<3-3#  }됃PD  ݵ˱mmYDEx9  ګlL=1i:  ݷ[|K?  =xsdkUtpp_?vRg|S  x~zwsplgc_ZUQLGA<71+&   ӫˑ ׁقրրق򞛛˒rrɳ ӪÞ  碹Ǒԁ{ԇ䉧󣑳 ࠲⯤򋰲˨  is32  )$ )$  )$ )$ )$  )$  )$  )#  -*!  u]5RW{5t%  kCwgd];eP iWIW_rv:=;i5yh\MB.qhO[VVlT  +KHEA=950+&  M}vnf^Tk~xF M}vnf^}pA8p7 M}vnf^J?41a M}vnf^J?41` M}vnf]}pA7pyV M}unf]Sk}xSnfM}unf]SJ?8VzV M}unf]SJ?`Y$Q1M~vogbXQD{)UMqWhB;:M|?;lfS Moj`K MҸĉ>` M}vf +KHDA=94/*%  Ƅ؄؄ն؄؄؄؄؄յӮ؄Т؄µ؄׭؄؁؋Ƅ؄ich8 ̣ͣͣǩͩͨͩ͢͜ƜƢƢƨ̨쪩͜ƢƜƜƢƢƨ̝ǣƜƢ̢ƞƤǟǢƜƢƢƢ™ǼŸȣƜƜƢƢƢƢƟ™쪩͜ƜƜƢƢƢ̢Ƽǣ̨ǤƜƜƢƢƢž̨̙͜ƜƢƢƢƝǞƜƜƜƢƢƨžƨ̟쪯͜ƜƢƢƞƢƢƢƢƞǢ̢͜ƜƜƢƞ̨̟ƜƜƢƢƢƢ̢Ą̈̄ƜƜƜƢƢž̙ȟƢƢƢƢƢ̢Ǩ̤ßǢƢƢƢƨȞȟƜƜƢƢƢƢƢÞǙãҤ쪯͜ƢƢƢ̢ž͞ÞƢƜƜƢƢƢƢ̨ǣŸ͜ƜƢƢƢƢǙƢƜƢƢƢƢƨ̟͙ƜƜƢƢƢ̢̣ǞŸƜƢƢƢƢƢ͜͞ƢƢƢƨ̢̞ŸƜƜƜƢƢƢƢ̽ͤȯ͜ƜƢƢƢ̢ǟƜƜƢƢ̢̞ȟ͜ƜƢƢ~ƢǞäxN*xN$Ɯ*Ƣx*NNxx0**Nx͜͞TN**$ƢNxT̙¤ȟx$TNxNN*ƢT*xxxǤ͜rNxx*$*xx*TxTƨŸ£ǟTNƜN**x$Ƣ$ƢƢ$xṬ̜xNNrƜ*NNxNTTxNTxṬ̤xrxxxxƢxNxƢTrNxNƜTNTxTTxTx̨Tx̨TTxN$rxN**$N*$*N*~ǢxxN*NNxƜ**$T***̢TNNN$x$*$Ƣ$NN**̜*xN*N***T0*̢T*NxxrNrT*TN*ƨx**r$ƢNN$***̢*$~ƜƜƢƜƢ̢̢̨쩩͢ƜƢƢƢƢөǨͨǨƩ̩̩̩̩Ωicl8ƜƢƢƢ̢̨휜ƜƢƨǞƢƝž휜Ƣƞ̞ƢƢ£̤휜ƜƜƢƢƢȞƜƜƢƞƨ̞휜ƢƢƢҩƢƞ¢͞휜ƜƢƢƣ̞ƜƜƢƢƞ̢¤휜ƢǞȞ£ͪƢƢƢ̣¤휜ƢƢ̨ƢƢƢƨƣž휜ƢƜƢҪƜƜƢƢƢ̢Ǟ휜Ƣ̢Ǟ̟ǢƢƢƢҤ휜*xxNxTxxx*xxNxNxxNxN̞휜N*x*rx*N̢ȣNxrTNNxNT휜xxƢx̢̨ү*N$$*x*NTx****휜x**r*x*x***ƨ$~휜NNN**xNN**N*~N휜xrNT$TNTN*N~xxxxƢx̜~~ƜƢƨҩίӪίics8ǩͩǢƢƣǝ죢Ƣ͜ƢƝ쩜Ƣ̤͜Ƣ죜ƢƢǤͣƜƢƨǤ죢̣͜ƨȩrxxxxxͪrxxxxxxxxxxNxxxTӣrNNNxNN*x*T~죜TNNxxx~~x~Ʃͨicl4fVefVefVefVefVOWwwwwwwgvvvvgffegwWuvvvvvvvvvfvfWWwWuvvvxwvfffgv|uwWvwgfvxvffWwuwuuvwvvvggffgvu}uuwgfvfgfflwgwwWvvggfwffguwluuvvwfvffvffWuwvwgvvwggggvvfg|guwWW}vvggffWuwuuwgggf~}wfg|wWWwgWgw}whfWgWwuuwgfvvvfgwfgwuwuvvvvvvwfgwuvuvvvgfgfgwuvwuwgWgggwf~fWlwwWuuwggf~vfgguuwWvvuvggfgfuWW|WuwWgWgvff~gpPwwffgeW|vlfuvvivg|w |g|vfxvwfUpWlvvf}ffg|wWu|ggWgfvgfffWpp pl ffgpPp``gfgfUp|pp |f|ffg|| P`||ffWw|gwuuvlVffWuwgwgfuggfvffvfVUefVVVVUeefefOics4WgfvfffeWwvwwwvfwuuvufvfWwvwvgfgvuuvfgfluwgwv}vwvwWWWgfWWvvv~vgvwWggfvluwWggfe|||||gfvl||gvvlw\|uflfw||gufVvfgVffeich#HZowjV՗ҕki+k[Grjʚ[Wmʫ]䨷Nw,]QVW6Qեmo_-OҡEuo֯WuIkТԞw[]OUknoVٿʭ[ʪmUʪ[k{UUʨ!"2҆0ISUZoo# )$1$d5D$l_ȄD.ɀ֕_~дտ߿ICN#RʭVoگҫ[_U;ו[oʭ5_w[+f[ʭךVW]w}M}TYRn'@!#__]ics#HƯ]w[{7umůo5Rgt8mk@WʘW****WWʘWW****WʘWh8mk l8mkZZZZs8mkFaustWorks-0.4/Resources/FaustWorks.ico0000755000175000017500000026475112130743520016724 0ustar miramira (~00 Nh ^!00 %1/  T he( @ l\lll|~||N~GψψxGxΎf|Όgln~~dNxxΌl\~nfN|v̌~|fldGlΌ|ff~ll|fLfn|lΎnffGvlnNf|~lllN||fgΌ~gfLll^~~lLLDLLDLL@( |llΈw|Ljh|~~lx|lll|lΌglnflgw^|nl~l|llL(0`yy  '  !,%+ 5?3 9=&#,.!#-** 33:<339<4 1=<^@ [{ xf j k g s t | z s q HIRQXVCHCMFBDI@M TS Y [ FJEKUQ_e do b w p e `dkblptzD&I!A*O,[$V-M2V1a%j d)l-t ~ u(~-g=j9t2{1}>^ArIkYgg{ms|ryjs  #'++329:>BCOKBFIM\ZPTYZ[dabotw{q}{cimts{}uzœƢʤΫЫƴͳ¹̼ҳԼغJKKKIIIIIHHHH KyyykkjjifffeedUUUSSQONN..,,,%%##KkjjixxeedggSSZZOZW..PP/,22& K졩jjhdU\Z.s KjܥdUSXmrl KjzfhdQWY,,/ KjxffdQW|,,/r K{fdUwWq,s0#& KydZS[s1 Kҡy԰jedvQW²NY/oտn KäykkxxѶfe~ɳZQQv}N..,,,%%## KԢykjӭeɻSQN...,,%%@E#6  KۢyhizeedUwSQN...,-]+<=:' Kã{{iihedQQN...,]FB KԢѷj{ifhe~SSQNN..CR*%# D< Kۢk{ifheUUSSQN..M?%##6Kykj{ifheڻ..@%%## Kkkj{iffzeduwU\ttpp[.^,%##7KykkkjjiiffeeddUZSSQOON..^%%##9KykkkjjiiffeedUUSSQQOONN..`,%##B KyykkjjiiffeedUUZSSQONN..MGL%##B83KyykkjjiiffeeddUUSSQOON...&%#D4KykkkjjiiffeeddUSSSQOON...,G>=$('B KyykkkjiiffeeddUUSSQOONN../GGF:6 KyykkjjiiffeeddUSSSQONN..,,,%%)B KykkkjjiiffeeddUUSQSOONN../,,%%(;5 KyykkjjiiffeeddUSSSQOOR.`^,%%#$ KyykkkjiiffeedUUZSSQ`A-*L" KyykkjjiiffeeddUZSSS`_]>><9 KyykkjjiiffeedUUUURRN./.L>;55 KyykkjjjiffeedUUUSbaON...,,*A>] KyykkjjiiffeeddUcOON...,,%+?""; KyykkjjjiffeeddUaSOON...,,%%GF KyykkjjiiffeeddUUQONN...,,%&*! KyykkjjiiffeeddUbSOON...,,%%%' KyykkkjiiffeeddUbQONNN..,/%%%) KyykkjjiiffeeddUUSONN..,,,%%*! KyykkjjiiffeeddUaQQNNN../,%%EF KyykkjjjiffeeddUcONN...,,%-=E KyykkjjiiffeeddUUUbaON...,,*@?E KyykkjjjfffeeddUSTcR....L?F KyykkjjiiffeeddUUSSQ`A]### KyykkjjiiffeeddUUSSQ`A-*## KyykkjjjiffeeddUSSSQOOR.`^,,%%# JyykkjjiiffeeddUUSSQOONN..,,%%##JKKKIIIIIHHHH lllllllllllllllllllllllllllllllllllllllllllllllƀl( @"  =--  &#-+-,-2?30173=89<= 39:$?*F] \{ m e m i t z r } BLDRS\S]DBMAGHJHLB LQQ U PV Z ] DDNYSZb i b i t s j `adehlalpsuxz|K"R*_-S<b!k!f(n+v ~!s(x(}+f1u6x3q9t;p>gIiL|KvTxb|f{rr  "'%'**,),-368>=9?DFCNMDJLPUSVT^^Zldmhs~`eeeihlorvr{}~•ėỴ̈ʫӯŶͲԲغڿ|zonlkhgecTSPLKG*($ ̤nmͺfvSs+rt ذYq׿/ hN+$. hx[VW- }RW p}}ɪePN~M*+&, Ϭ{wLG*($\?8 趩zhfuLG*(F65 ʮ}huPPM*O91һz}h΁XO"4znmyhjfdxiY[ZZM:40zpnlkhgecTSPLKG*CzpnlkhgecUSPLKGG]B2zpnlkhgedTSPLKGG)D754 zonlkhgecUSPLKG*(E:921 zpnlkhgedTQPLKM*(&DA3\ zonlkhgecUSRLJ`^E$A33= pnlkhgfcTSPa;A <zonmkhgedUSaI*('33= pnmkhgedTb_KGG%$$2@ zpnmkhgedULKGG($!  pnmkhgedTNKG*($> zpnmlhgedUNKM*($> pnmkhgecUPHG*(&!  zonmkhgedUb_KG*($$A pnmkhgecUSaIG('> zonmkhgedUSQa; zpnmkhgecUSPLJ`^E# |zonmkhgecUSPLKG*($ ( < 3   " ' ( , ;1 6;?$)7174;8?><;WVf n f ` l y p x { } QSYSVCFJNBFAJD S T ]QX`h k p }fbgnou}W%K5~!`;o:j=q5|;VC`MfTvVP}V#$$*.)-5OBI[\RWW]_W]iledhtvghjq{vyȟīҲ1Qq/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQqQ2100 2b|]}wqadVTnS2zueR2vkch~jwsMNLmJ2vbytpiPoU$"+2yl|`fgxOrI>3 2_\YGFDC<;7( 2^[HGEB:86=,*2^[HGEB:86.%2^[HGEB:9?)'-! 2^[KGEB:A@5&%2^[HGEB:W6#2^[KGEB:W6#2^[HGEB:A@5&2^ZHGEB:9?)'4 Q210/ PNG  IHDR\rfIDATx&E6{0 ̐3H "51  "I9,y 77W]U9}powsSJ+Q###s`f7ִjo?ϟO{{H6HoofshѢ;z0)SnU}~<Xɘn'' }ٗ7*gEG*ϙcY:k@ט7$"I: ,XtR (m_S1C3rt.Y1?ȔܣA=RL0Yw1\2PV[_[xPzbj,kw̴.@Y>.kh}6ht'::Ř[꿚7urkkf7*(D!X!svqgM"M3WHӍ.KY~>s[ Jy[mo[u'Z>xv߉'jM|o?F>g_&a\ <?jAKjrxy e#12Z+ɳ>4yRe$ޗP>DNn=#iSBv!ӘP1ZUkry+I2pvV;51)w:/m. *c l=+y50p&{^1^yba 򭴜?@x ^1( `D`@@ P"M0Q{M3w}AU(R6{#C L BAJ s%"0 H>e2y@5.csz=@K/$AT|VR)0~UO]WPj?<@@h*JezzzJK4/|67(kgb`0mHV 'M"Lvp<1eB0C( \B #hY>0 SyBF-B ,[#DƑJ[9Տ0hl C9_K,9Y0xTvyj- oYyHH<`_3,'t!&>e- */Yx~oxy2S_20p-1Wkhꯏ5jO-(XJF㠶A v8XaԄk%2-W3D/?PP&[3Q@}L BI@K@@PPFK/m~wJ\CV8ko`RoVhV}`@XJ(RP̄S$p2< c))#(1XA='QI27:i/[7d m32-^Nj30͛`n'y#TU|LidD]h؈SBF} Rr)cI^5Q-~XX\o%T(WVzTF6r b'v"zpFIڮiy ~̴済~F1 =_2n'<<&C#sWOWE~&dORC^I5޷)7+XɂB :ʬhCT,0[*DH%>g:|5+<`CY&W0bEF{B˅x 4jߩR.B@uH8A/sǖ&a$V@{@,A!0 +L_@8 6N'ʯ+9 &}QPd  ΦmU*]} sW$r*46ĺ8@ĊnL*ҒǬ[ F%TqCrl2aO Y~XʟÙXFJb9c qBy-t47`f6>ZAy8 `$V%q2҄jv&俣2#ei\wpUFR@A `fMZz#+L! %!ꅦJFXK5]$++GrExV؅R=5ࢂv"x eVOʑeБzz~SYLӸɢ2g9I<uSPD!`Bre(V\esǐ@@)٦ˋ@_~br*aA'6KzDxY29$ B郿A@,F5QT 7O%:Qڂυ%}"a|#J]X ƒedUpȜ5 W 2a:\KJ!e6BqR o 2.zTYh>tu&ķɷ3[ [(}6EcjOFZef99j9CI*JSY w`?"ށϝ*eLO-1Eᭅ1[8|)t-r=0xgzbSծ%qdKeܰ2Kb6eMVSNQcFY!dEkB+I4̢&A8)nd Vf8&;JtVeC{0/&D`[(b?2Wzn_/nkVwX0횣hA9w]Qa&g{3 ZF'6ONA2R"d6"vaLe5a2G@ PXCr@嫤<&EAW4d1 VZ 7]Fo@=)/ NQJFB/kzӋ$ I`&-m4W`Kf>r]4BҒQPJO8ްG쒙Hx9h `BuqDE9rUwIP_J 1~P4Һ,sd,(.r+4|5 m v1.F b H@L[XQ?-L!?VAЮ8Oe<-QDZEyYhUy-`VVc l~,Yg;a(5{'*W| 9]]ږaZ2c> c: ʕ}[L;C0`ڵy?,WaNs?mԷ섡?#[vVyGILܵcJjֽl\][ߌi_= bgaz ;݀棛c[>]]iVy0z/r_uw=RLܿt9 kR ~ܒj`fz63%.2 9} }w5" vhID12FEe'd$5αN W\+CPO4F2`vPL\O,T4O PM4%\G'/sXz6{ݞLg~t/@&$B^6 C)T[IJC]w'` eR:D__*4)7BhWvapNqV-Px(ס.?~in>vz6k屆;_D{ttmsNKK,`*ִ׬~z<iu{ձnluuvtKl[6qe,p `gB-Q$>=\kYи+b_)`ʭVH F=?"eD9f9/@gi"_r#K <:д7#&L-3m h<xyYoK8֥e01tzj#RhmHmDq6 &R$.^K-~Qc(oO1NPPHJHV>\xKfKk!ԑ?W\Psh ȂbJ%u- {˕ e7>qgaXܞ{wcNL1 K`1^ogKc?9#9ڗW}Q~ֱ^ZWgfkMw9Sfu~?Ctm/y/:NƖ@0q&` q ߗEZܦrd?z33v%/3Ay.@PoԊOFMV $/q2NE ~ԡIjJf6G鯠/k~y ZV/g{K'',n-jh=|e۸e?h%&ne_[6:u.@e$&:}X _pLC.q*+-a ~o׸.[} hc9=b9 &; [d(AQ,=!} OHҾb}cZ15aROY+r-|C>)O9j{i"={FCI#~Rf4t9ˮ돥G3ҏkifWvX ]u^;c-`''?DmAQJ>ںO[0][܍ZCŵ1|1ˬ߷h͟??=\CÖ,v,XՂD?ɬNdKt-b 1;=45/c re`6@J,'Qt=6m)dT:RVz~;B+GRKXuBN= ,GLj"R`3FK]rL:/X[4v[Ė./M1ȀSW{SQ& U:Sn7>H dՕVg,A!׾4#ye;eC>Pĸ(~D_um+,\c[ȶh]4̛g7 s2dNsAEbHalho)X}Y:q][߉nw˂C眀ዏvj>VkQ! j[{'?o &3B2`eP_LP8hz=?,O" )CD -XA Av#B (l hޱȖ/ ,t+(ybsu16%Oo֝ße#o{*]M ڜF܊NFKV{_ZEs0#0vH}ERV~a} ^#K"|E賾:5K`aסP4J2t0UdTzG1v^87bB_JbYY K1c+h ]N`Sb -EX@DUPW, %[ﰋGtOG%ƈ $R u2B*|WSp2Өm}Ki=3oyj<`}'X_]3<ݮpev^]7 ?*Pe,LY\-^J}*j?.^ok=w]ƞ׺E:tky􌸽W,yyuatoy$,kxu+Qm)DnzfyF1h 4dL/=yb+~p2D 20 H"+\ \pe>Z5x 㣬7 A$Eed8c{Ff>A9ė K23F{ķB7#0z`-Fm*6'k-o?jC\XNm~M3 Bϛʊ>ɘXsV0ȳ̊j~crTW I5;+ms1va/4*O0CX0rAtښ\+Y:,$@$G`ϮxR@ \U|uV(g*#o}>uRfBl£3E:) /{HZJTn m7q4@gU]v_>di_8%Kw~/PLc[a#0>o?W;V =(ML@)T_paĪxc*g+KP[iwy-0ˣ0vnVJǂeg0zݛ1O&dTbူLXb`y5<e7-+@R)e(( {UF*+9SBMmඨou:Ǿ\z/-oԉNVpoK\o/eYR^! j|d,8+=dA2tˏAmv ͫ7dH=GS4ց@ʎ?QeWf)9͂U0#XHZA3zHVH|$ $ <O:_|^i?.>LHxU@`DQL2z2X,aҙRzf QJ3Ƃ\ yTZI,(<%D P[#=X,L[΂50|7Ѵ Ξ!g߆ܿwnGsߥ_qt$3 [VяEs, WnַoUOWJw=o G յ{ctkٌZ;/730'2>}" (䦧l\`{ ':ɢVfQ/B'R0(: V􊴲o;)] 2ceϖ %zY?[ wm0|Ih?iNb4dǜ]ʲ>0X/%=U?'}LZCKYGBmDPbܥ嫀K./Qo4k%p̆8PUtg| ˷?>DO`m /- WJjϠSQs;ض.,^P@Yqfϳ`!:Cc *2Bu߈ރ.1tۺ.>@QlRrMÔKGR::\D}0nOiݖg4琾Lkh{yՉ%K@x($Zȃ˿ (Ja˯v/C ! BASYRX2*hF,YXP@ #`&/S9b!&rH{i^9 =K%ymM_^kHm< 0c )[X&X!@)kXn9\G{ KKVz@uhcuC~ҪG{ܿN{ۺFou{d{N6L,%,0w q%ɑJ{CUzDy+gxOq Acکϲ F,RL]L_P+aD=;;ѭ$Sߕ)?u/(D"nN wʬҕ= iψJHh~u0\+>FE3 Ć$M Q0I]L3vXzg||CgE/[ jtoi.+T#8Qp֗fJ&-k/ J#껐zr+y)JqD䴝h-bpqQBaP Kq}~)Bk[Ce[xUwtVU7]H,՝>՟j輾;;,ّqxkFꈿݣފL  IIA>#;';BgFglPZ_ԛmjk- _ enjG=}@ Ks" Q/t.YLu04Q.<*j &nu%) V^ gKd >/) cfb_)Scvu̕K>Tg=^=rַzxvg˪rڏ>?|mHr&&e;ĸ]4>8)*E"c?yKgΜ]ۡĆh/XيeO(X~,u.9|ÿ8+AT1ǀXN$`sRpbvt@ule:0$E 2x$Dۣ|gŦI-&$3EXsSk+??ᬼNvֳiT`Â_җxBl#.[KZeg Ȓm4%LwS Y&U ?tołF.~7:zɬ}0ҏ:L 0e.G<.٨'яoqY}Ai8.K[Z9Y=q"Po㉳B;Cy(cYPt;z*A ʥׄA@b$0 ~upR/;,+NVՏ!*UJk$,^QÊAXg ڮY!0`Vh(~eIIA)f|`.ƭ dKg3I+ߕt@ 8MXd@|Pm .x%czHvc:, XL ϗ,r_ @6e)_^PU] 2Q$PE꫍k_υn907[@Gcr]ȒGb|ɨ4xe#688.[c0e^,inͻZ%CЁx,bs5Y`r >pN.Ȱ{A™q&z5v,{z.tK^QO4;䁥^C"!@7/D.Wk_CH@`Dќ_w(©yY4O1#~xɆW1BN _4gkty=>k?/Abv겻G8J4&Vm42 sT,IJYڢ  ;uaUc4o grvfm|?g>c0rz,+ *ZC@ RA06,+}PG2e etp L3c֓w 6, +"s[L,=L~$PX"V O٘> 藃Ǭ"@ eW>|q i 9b;eϝYC-%-#jw*SJ=쿢ϙtJgr# eZA$TH9H \ dBBG, }o𥇠&hZZy~D[[|  @-o ,iVnC.zxe5X@7 ցS!(ฃ wA[ HPPù^H* pHIy?,AAOAcߣ3<]P@܅lQF 2uHY+z WE[Iy/ :|K͎c#&=r{득`PmƟ&1|"JqROхЪ/3<Xvf5iHֈEYxLs^o1B J~t^'$G 5At{KS}Z)_ =`3ԇ棛bayuՒ%_FJG3>ݏ2d5=x) <,ܫ?F+/,.qzy휩 e udMGd/#%CMȩ,V @jq_nV/ $=18}){mD;:}J] Bź\ paLVd!ˀȩ2 Q\SV@)N8, DjP|a\J:-K90Y`FjG ʂL!MEK8ٲ¤AV,tὨTf  `.陁{w-FG/>ƝWT^Ef( )Shw$!V.=>!H_n1Ki|D~|lc]?F.;( 28& Q/frKղ D֘[Zj_UWz'a;S \>(G8f*bqm@"I#m&1팬$}d!Փ^)t:I#N`_/:T׿AmփY`+hA^F˭ uH-;5 wdI`2bI^!P\)H+hA}; r^6 A BMV JWʠ؊uWM&djzPq%tf@Ҽ׬ Y2A(]Xz'4rLXL mr;z6>Г6Ұ@rr!oEISY:z~-4溍A똸`(@en.+PeGyȕm2hY 3,뇄ޒ[XI=94gsy_`3N^Щ\'8XWh"w)Att*k>ky*0 GXY %\F<ҪTC񊢭Nݎ籂կw |&i*ނ4x0Kzyu_]ER]FWxC @~ȬEN<˪ D̓IuS$]Y{F@R(a+-`+!\hF/X˒~hgb?y]aw2v~[)(@tIJV8GJ3baq QXhIcE?sK7DJQ.Dc S SyBB*HB".گ՟%!GU >zǛ5 @Bn# s&K+4Wi@`2NryC'G} 9qQ|:9v-0x]ŒAVJʣ2 9P>8Zct=I؞h;%%?(h\+nb] + E1bC6\5hMk{r-uAn/:WXhU y?A\v"bB,5M+Y mڦw_P.TxIߠp@'>y\d"QVHA% jA!@ɴW˂jgT^ZJ2e;瀫&}]'O ?+μTb<1sfrm@Tʑp0I!KMi l= $. DaQ*ںmkVD+6+RbpY 0^yD=fA+0{ӜD޿v>n,ZHǯ;3< JEd#weW1!$9VJ%a vدнu8{}•1qvkp>$2#PbC3)_|;  ƇV>(N=?zcPX<EX IL℟h\|ì]Q U)prLG>f$ *X(Q$'lb&;{ j ~zn152* rEJW`Xe}?_[ID)08Jgcyn M-uǂ7˽,!: go?=`㧣!2_Æ@/t1(Ȝ`Pay5`E?vb%[E"AR yI+ RRQ |\ [ VX ifA(u"PчUx0 #BXee@uEϻNj?-:gXKvYd.%V׃4|9XVnVȲ㈭]~-LVx'f +)+3nȾcsUR~A,#iN@f/| c=R1.T1(Ot^k oZݑ?OfDh# B*} e+AWz>=>77&9Qo%X"E DS8ۑCز;54 C?8ͺ`W[]ޒg36ū _a =ٳ)^0 ߍ^'YiWT.28b XO1D=GFk:(L XioW(+ee\@0MJ!Nҕ0OEmӻ@ U]lQ ^؜G jE._] bOFFiYwBԲWZvY:%~w!(.==oB{ L<)%ŠSκtD*CN֞Ǹx, *@~  VU%YXmjQ1כ2X V pwЏ7j;gcA>w>y"*KuVPqPQ:^9%8I΍jo~%QP3U>z:zںGm' ILܳ5nRMAWӭބ߾ֱzX)߯Oߡ5c7팑~uVTQ2݀&g^)NJ"g4# 3V4=u?ݛpqTF a()YAtR `0GJճV.=}} ?@q6 hz^KX35~Qt2Sw.7 ^?ƱRi2PGc[o ΖAFڞJ(=/uqk[`_AJ<9л ,tj"H?DXb/)EVϥJpt{=)K]U`bɖim ZϮDcA,_* ktO dN)3w"Z5ۀVVP)>!, F{@}){h3GP)z"J^Š?1 J|&2R.@յ0|wvٝ. yq|t}P,?'r*9' ıa |-#q̹@*d#G%Ǻ;ߎsf_ n+p܇_OԷ{+{woP]yt^Euvt,bKh>5 #jh?&Vpt~nGв6|}\"@ Hìn!h( z9\ju.>CrrE)epu`d /31 ,= !ʲ˖,lb o=gxƮ~F/L=.Gw]^v oHQ'wA)I\sx$qɜkI{\w\ ӪbYE}~ҘϞv/Im.-czʩևӽ lw'7DeBK-L__7\Nw|شol߻_:cק,SG 3I Hˀs!:V=bp}*@dI ">:Od'.`CU*n f }l4"PEEGY@,p賥iosLj8 6#}xcߢ-XJ{`0#D)W#\؛YPS_uUK<1~nx,9cY:uS , HYSOA—|DW {h7Q)- ~ͽB,u ^?h>WuĞXSyyf˧T2_  ڇ@( b& = *@#D o? Tw@@H@DlyTq+0ACYAZX%؟'fJ3h-Խhz%joGu՗ez,n?ɇXPkbLU[SCiJArVW==ou:Yu_c7셱vJ4ۧ~?,KYzRJoDkL,bj1Ac/\چO7?%_WGu?pGvL_%oǒuV.a3* 1BuYeIGxEW_wwI>nsI9+̿ kZf):m;_?] 0|{bcgPv{R\_ sX!u+ G^ϸ6.1zHJݙV0݀) qC^Ŏ5ET߯OXd -[#33*z69(+!G{b-SBR?QwϞvr<3$fJ oAq XU ,kiVG]}82ԿrL}oa:7}(hlyn.@,^GSɳMM}}? F.}F<x ZvxL- c쏠y@zZ8òkbGǻb]QR umj۞Qώ?h"Fͧ B^%z%Q؛O*NAD]%B @&Pn('Rb2,IDy[+ȿ/.@4NЇ*U}ɿPծ1txz|ުj|K$|h{^X;{REo޳+>>r{81x[ ǝw3ڋsNƻ Hwmueא}[~}c;&K= xر'ق: ,u+ 1_\ ]=oX ( p S<AD/=C'@d/+ޫOH<  2jMJC+/Yj ~EL}PU,Xj$ 3_# l~?ھFޥt{VYJ0ڻv䏺F/l᳾&sVm+j65zAPUwxg0C˔;yk?łl6ʭ,Y6UW^ׂ"^N]]rOkA`NCahUa?S4Eʜ)8Q>WNuiHte,f,=m1OZơn-Gx4ʊ+I@+Fʮ4V!$`օ"KXꋳ>t6Dmb z gcAڡfJ%8ŀk;}K i@IrDcߔY1~a1 &[C}ѼwgL<6uu}f-+qy]ͳJ{'k͂_?wK]e}?kmY[x\b=M J3XA>rQ`Gwwt_u70G[~QcʧDe߼+aT,Eu]_,1cE@y@ BR\tD[jAa8PVG=22%ա(7ioSҖr^2qgUIА㿂ס:ʯg瀋KVqp&Om;wy*LF,jf[vpoLYRl;CX 8GQYu  {ןO%g{sDu:_ vT_n݄YF.?:h~iiٕ[#dAb箔zP F^%iQ9A؃dR̔]Q 1RoV + D VbQxt@ 3 D @3zapweP[1 Kh"wm}3>VA^v7zo>y{g־Ҷ <㿕@]oUu0z Gp6okls?afnעk1k}Xpks??{uz+!vA?'ǒ~m NWPxv=4 ǩ>ssGUfFzݛc1~pJlP`( <=4}S欜e CnVBQD M{O)2= i&S4$K,++S6 E4Ԯe5{>ZP#*'o*G>}ԯ4KYY.8_Cm{\`6hxv3*VOЙ'[>VzJkpm5+=tw9>zac7ko{ L@ royu~a귺`` շ|\t8e?qms7~ܥq -Fu[c#,<\B*'ȡq'C!#l F̡+j hon&~.W<tߖB!HB}o4e!슃J)?DrlOZ֥ 4+jjy?~.kwq$ 6;Atb9qBͨU-c;dWvuWнۭ9q-c{t7LWnB -(#I9jFbF,R#"Km]DwV֏f`Wk򒂸~KO bPsAc5 I@MW2ݎ)KG{0qIhr5_·᳭ls7aW c=yadݖh_q~~gp /9sBO:g+1~Ik=m˥2WϜ„UnƮ7?zA¿gVxtPv҃ }οO<=e8]׌mI}ցDʏ!‹ <`=,* *@7<-^QAe[lCO~?d%3Q^p'9 ¢ew %̸$3J?D_s;_O~Yy34 WDuWP-kV~' D4<uFDWX˿cOKS{usg97hKq$ZϬH @== !@!B)H)[Z(RCPkM`!@~ݙ9wv_׆޷#{;3N]R`SG1Ԍ{CXzod(3=yd+ [\=|x9MhӬ&Lu m PRb܁D!|.ʍ< Vhn rYzgEل>qVrE ߝ'+KR4D h"@!N%@-u m7@w_VlBj~MvfjK /LzmqVAh [;?_6{ӮAڑ.WkbT&:^-ןW gauڽA5y3tGOf3Y{1,z <> ")}4b4vuL[Q^ {:?D3 /V.zDK };E XhJ$L5 '2@VtW"N ֍¹fPHdbv0QV]@_WBG`'SdC =jfUX O.dUu\}`U~=\Zq{W Kl@'MWCVhM`#tN[ꭞCk=˺m<]oq@DHdFkc0 6a21WkTV֗P(G_Ñ7zwl`Yű/O`Rnf]zyKrPT;p?9}_S> O] d/ 0Jy_:Y#i\H"\y+ K"[cҺm u ^YM䀞sd6}N.%gw(["( (MzQ;ZSy&ͷC٬A"q l96Xϝ(5@7 [[BK`孀MnϞ+_H-[[3p%MFOEm:onOaiW>R{-u&:MxuG#|P$8qN'XL&}Yah|yV`!W~P̃O7f utB$:7(@}E @/AIa9)'L; *`Ta84ݬ3g4p:s@}&Slzw~A'm YgCUp" ' LesʼnAˀOã P-P, 1HR#~4`RYOVhĔPr2@s0fYBER󱟢k_❈")vgfoڝA՘iz_ߢo沶|]v:~f~g4/;/8h;Ƴp'wR"; p߈9dHPAܽ?к0S1}iB1 !'08H9~nWPTf ܇{IO,@LqAoy{~8(&*g#.Q2hf'Qq?s8"Y6 R{fۗk}b-&Ǥ F뭇C3cp蝚 eڜ~_֔d~JԖz Sd%bKs2?Dt~% q)u$ +-"rߛˈC1v\WS򧊬U1:bR Pf l 5 炫Ax)}eD#)(BQyl@MN6|8>n@ϻ >Kg` z7xʵaiI&hW@aϵA@S.Yz)a*ln@;OP8=VPyVj_C;s[9D Ɂ 0/@t_𱙊Kfrdbp9p) JX3Kz NRjf QF>~v0][eyc j 6zɃ5may+kt^@Ns,4z*Dr vf$̀Џ9$UߓǫRQMy- vD.岾] ˪Tcl/%ߥI͍R)XsӚ,ؐ&UP9\9=7ǃL[2KHPV 7I@h8v y]\WOj:P9Hitd?tO}qOxW`IÁs$8 o+z;q_[gAO[l+D8ƜmȽ3XhL/xɳ$E[i#\ "3%fDJ{؈%ȗ 7>KBףf.fa{?0-FiKiNd!{9~U㵄ھ1{)x_QoEY%D z q"P(Bh1 HADHB G$r{"%0U//XV98UpJ @XVpG ~ T$\]s [RL}yt,Q.@1@XEC-s8B"JS@S8w;`Iٝcf0Dy`=gm\Bu=\3sN`6CߜM/; }3VƢ ΰG>:K4g:Tm?lh/ASPԪjaS0 g#i~/EcJmq.s FCX'|,TAWBPh>2?Y%*ZYl!6Ov'Px 4"TUˏEN %5כƼ}9 `G p^V2{np(BV\ H.@P /ت2hjӕ*( I4}[dŋs rD(3vKD_z$Xzh"%THנ .YJPVICޒb`N?O+}(f"7~!jƽ`;S_= {~X G_հs=eCRמlb#,<\**$-J)gt[dp.rSZL>䴠|WaU!b qU3.C%W {r@PDt YC2ʵ>Bܡdt(_n&N j?{V ۼDՈ8}$N[& L=cGǣ> Qz=kޡףQo_1c58(!cg֡GXVMZN)E I(.мnDZdȪ3cTXX\m@,Q]G+(d | 4XXqTV*Sɀ;\r MǷɕE1Y:RN`[,pت+VCoDڝ: -’wT' 5G˵ǡG+ K;V; p!^+}AߞGaFԑpR]GNtM@N6pv/W‚S3nkDpM(ooYī 8AgIrTXo gJ!v#@uϧ擝,]`E/+StBFqBV*(fً~Ԝx6BbJU'wGw~*VM5۾׷@U'ieKQg6D'jZ)*VLVT 櫎rӺ EǼnA;k#hpJ `gS6Q?! d!L Hww|AU 8 l ] K‘C E֢{O- Ks)cX.j ; G}]hCWN"/x2=_w,G,_@]n-C?m *rx5URk!o`7s%p,: ɀ 4}A<l8F|;ʆ̅ߏ|[y0Zn<%-=~* =DLV0|z˭ Zms蚼.DA_88)# rJZ2Hqe\r4$+N "WP]ު}|=4$"7ϳJ_i:_߈:#/8#=MjD{ \"~)b)_vנnoMGh{/jwz eK͵ϗf-hj7K h߷y0T[f/oF ߂6+EAz.ŵX[~f`@ȏSо~dzۢ劣,Q1 d˃~4 )W,-zq!zŸ9[a).,|l=ܝS )pC }$J/Tlq@:raˈ^Z5-1x0]E/ 'FD'Rcb,W=^ŭ^_Zrh@{Oj0{>P{qw[ZohD}= U_N.`rO:k엃h ~A{bz)v Auߡ]\k:}v d[,8B& OA"׸ 7 ` ^i'ʏ9;r蝶Np Xlt \V@TZj;p1P>x> Zo<(shc,ag (SD v~+vdf{,ޠ}$4BXHYQ #gY.^7^ 9!$Q>yK}!2'eKV#_:C n\ ~叔GOR`Yl'96ȫQ?7QuNFWr)ك]h`;*ў`xF~3*jc'۱ @ [ө5\yj~Im'76 &' ?i1Pg gcç P$~x KbA@_nd3;&&'<l\tـ^@C_2x |]d2S^jGӊ"(B1%GI/HM)\3`Tvewʅ>!ʗ5s J?,xtgmYğI[힃_6gz!#V9 WB> b]aeǢ0߀Uf`]Gi 8g׻E`=3* 1o+)3`$R$/dIz>T*BJ˔ /VQ9^lu h7 ʙRc&F&q@$9c&!HutpM_zR +V}F{(DM~zŸUEmz=ތڏz+% V2Qx|X!u=̓ut m V\] lL@3Nw%P"eUڬpVh'. X;*gӱwk%3ouļ~l@V<ۃ+d ,XUg2/ m%T}Ǡq1-`LO$}Z7A`(o'E#)[-)?Cm؅.?_ %&?w;},6~'/ihG bJΔ3^vl}7,{`Z@B i{qyd޳)=3 CW k#mr1dʟ;'?LZ, >@ɀ(R4O4/7M%y յ$KHX9b]}<)/a_EnQg;g5Gb x`wf!ePR ŒH+gg}D(NQf7H岲K@ ^ h5]ж޳:fk%H^<Hd LS1JGL 2 dRP>r2H_Sy3)`?+]|'6gc%xI uvTH1-#Dd^m 0. : E K2C!_j4>ܡ蚲%z\C.Qg 3P6Ң+k9}-AGLYG~B{ҹ6dYb^lNGeCi7+ִLj+xM}5hJ;J%/..!m8 + `RLxD kQ:zE(P5ݬZ+1(P+hLW6^{V hIvŔM9% +w`)vtX^2 EŒ fh<"?QhDZzck%ؔ$ʚ)[Aχ#yñl| Dgr<k]Kڽ߆Xt虺%K P6yh ٔb91v-t.T7 b$!'9SuLED^A AzH өϮί)^dlWLs$+v!4]bhOYҸP|w885mA2|f~n@ͶOi.,֛_55tMW" d[:36\Oq8 fENP7B=?j5h:*oF!'ojnFt{8(AbV]eC.BLe S]"+pSǰzA&k(7h"gMCEI44LE& .D,$^{P;A#=ypK|ﰵ@ٵTX?hq)I~{+GîFxj/h_FS2VbיzxO.qY]D,qD&<[Ӂ€s.AYc;J 0Q`$}_`'=YJ@S27)Z;[9kxp_K*J(ڤ‚*x$3ж@I`U3$gN p(j^Ddwy(O+N4^09V1%TobWu<;<}oVH0e.י\- fEȵ;@O+~8m",$S"@2@NJH8x?c = %CCxʦA ogXrК_hNtE+]1zʗ*4olχh:zDGkQxs>[ E֮$f;' koWh>߮W5 S,r}nJd%e#r,8{B|TtBV]RUw] x4fFK SNv'wۥ$ B(pI}3j?}D&Y]ơGr_!cٗn<=J%@~`6Y #TJXj"@!b`Ʌrr342-j %S/GMR Y.BB@#9'ۜWzI# M7Y2% 3wH6*Y?'{QXf*H@a@uUcv$sȝ"`C!d#E(+NF+G!we~@3c,Pe)0?O:%4@: 蔓XRL"ECw9O1]w*<(f:+[DH1:]N\⮧C'z *OW'L,P=N .ߕ!~ *@|AN xܙu B?Ze3t|,$".$lzZ7. **hdޛc ,|OM~qTJ? A_J a蛹]Tz MoaJ^w'!Tn?҆BB|)aRTN = ˔8(>#] A(t la _zHXE|?_`QQB^JZ߮miE oZ>j꿗 E;c>#]SF㞽P6i(ԜyP*Cy.@8] $i"UsѼ RBO:XpCݕt/K@,)T&A (9\L{b$T-P;qLiL@'2@Lߢzɨ6?4߬ѴRwU)]Bu<]Wt! @bV(b8 i=؋#ap8 '܌nITvVBzi?O@{e1)BH.\0(W|gQIgD H Uu guȔ}Y%eLD?m|~'|QVx{gBHV&9P$-2-A4L.CX3@9F\̀PO^7W>ZSWKTw];cU|Cyv ̞]o'Vх.PusnBk3BI32N-{Q W=nfQ6l^ fԢ_ս%g1Lu3FNXU?ATϯwi$tΒ+b)4Ya^Cڤzn "& b:$nV!VVF0D%(' z;ef[ BYr=[ɖܻ¶i<,p+*֘f螺!:]HMT?[XW9&Q|<^Ls*jP>2lv/˶;KPt6*`#dANM#HI Սò YO#;Y2JJK֜7jOBTy^P6W&9L%QYr:)V.M89_\~srsWYC|Qi/_ DY6|qh~F͊}]Q.>rf~~"b׈ACXx\ ٨>@(np V !2 9e&$hCE+c A 䤢Y4@#ukEDQw2μ U fw~-Gsx/O*\g@z! 3WF{{V蛵v@ټlNx5W.]_ >LrJ+9*@Wݦ=UZ؊sQ{h<TL߫q̏0W(.NȪx[Pgf)PA0`Aq81 I1!cVxU,0Yٟ'0؅`QɊA8( YՓ' nVlܪ2ͿKL\}P |s&nAkhH.`^Ed]&>S}oWkZr1hs(* kOeE; &x胿Arߣ0+P?(wO$%O-W.J.6 U Jq.qn =ěςv7.G)Wi@q0Q5]mey3mMLkyZPhP8jH?su:(ʼn5tm; 4:[ h~Xg?韉g6 v@v%v)x"CZny#0 HpV#'3k˞^dgʈ2ÀN֥th?,B 3QO4@AF8~;IpůMR! };OY+g_U!M&fv96~Ӏ>qocǛ n o5ܶM+;esx BݞBƯkyn꫰.@CQ`.pWtڏ"*;)sޅA $ρ5;e~3GF;A-h;@Ö`"KᢡӠ]YOi?PF8Ԗk~nw1rfY#KgwF0ЅM\­+( %^ ^2hHw#bK J?MÁ+$6(iإAvk4+y[ݬԧw=CXn)`5M4++߷iI] 6ZڑOv{ۻL@N_լLNc,/,c3`}_CA7jvQPˠw*v}@MD ng#ɧwg8AuԟʑPTm6*VacI}G!@m.cԽsbA@fCƪ0 }f..~AOFJ*s4|c֖5i>>fTAa=g!)WBlotes|yWh096|z *w(+uo9!&ҿ `Hoݴc/XA ȱ/ FcA v%n:$~7 Qnl^Tx*f/C5ğ'FהQZ4 #RGe,GzSP2 ♆W:C4/,4gt6:6+0k.< D$t*xp0h`jL1=̄oa c]F5;&+|P[ӺL<>+/y A 8L .C* uUgP}Wі{`H5: |K2O]LBg{0kYHn#Z7< {;@'C#gZD Ɛbͨ *t1wޏFbʮ45+k GA 2OF>~6A z 8tMj;PHZXx¹xIs-~18 "2,7 UlqCH@>+ivݎ,? }szI[yl>o{h 'Ĕ`H]q1@}+ r7״cSݍ*\D\d@((tI4v&UZ] G>`0gLPWLwjwwOwL@̓-\sWGy{9s uN뱒 Fml-ZˆAVC[P290t_G]BNυ18(8.:~]J͏h |DTX8bLl`\#K4՟ Za͵4;/~L{~Ph@ DYY38LMuqvO}\,(Ngʡ.@<3 WJܧ VUfy4s1*VoW@۝ؾ)v:nVd*Vw~˓$&~!3L>0,"S |_߆D㱷xF㙱VZؔ|1 ]_kkF-BfKr1`Nu=|,d8Պ:?x :i=6^ 8E[MWIoTuڗa3vJ;[ ]{̔EN6@dP Kk'|/Շ `Lg}Gk} {0k`53䅊:X0*JfB/ H̝:Dh1Қ@XEaJ2hUVP$~V=Zv?)뵇Vo0뽉rMm݌M¿wq(GD?'O|< LLn5ſͶu^_ l@@p1I5Y,)D 7|$BeBr@,=DM~iˬ&xQ3ii8sTk˚|9 @Xi@`ٽ#`>YǦwӠ+<v#o);~%qrQh'5D@½~vXJ.UVVy/}v[0fY fyCUڥmwӄyF(e!ۑsȼ[h.Vm6?_Q:,-#M[{*Եk:]G-7=}m@\Rx0N5&;RX쾕lA`ocz/ HFǏMX=MyI%d `]w=7 θK+'@5ݭ'# 04A!h8w(oip5֛b-*^ۅ-\ }3VA[-v}̶ǃc:_k ]8A͋R>"pf + ϻ[yS?^ [_|t KHptf%༃DM-ler @f>Cb]@v$8u)4Y%ztޣh_ǭ14mCazGrK|'~IK<^<[ r8ljRJF?nΧ@>?[o7KCs{.S@V0 ,@=W ze Ӏ8%Ijf2$&ʙ|l4|3|<mwZSvuuK|{%veo/ 4;0&Ǿ>M&ɧQ+(@竛biBU)Owyv,pu}w @j",>)Cq~ O˙1_ZM},B@fSƧ+ͧI ׽dV9a5ǂ }4/̇-]V.*[ n?C÷ K0sv%~diN۹%'\D CR)輂/1wYN#maPPu~-S{0x#̲6UuٔJw3.%OiQvWE֛ji" Ov=dA@ i~{ u9-,yeOѥbȏ_3CIw.͂UzQ%ڢ4;d3jc1ALy4/Yҳ0r`(}9 v3D76Z7MWOgj50 Ӯd^8#3-R$D}#.a|<y һ(B2D1peϛcÌ_=?X+h`Kj]7xuߍV׶ъ>z?_Ý}v_bկP9Ԍ}n%Zn:ʬDUghwY.bR FkJ@%Q0)^ R>1+!߻oTYMa nl^.O|ɬMUJf^I V.Co5 :s,!Ӏ! ~Y _WV ,7( w$4s2n6q_c4 p]13%"B(9 #CㄫP$tZn8=SPh8*xcJx:_Zt8JfORyRI}V/Q6$M-v_?=ݙԍ}MΞw{4) ~[ 5&$d @7<-rjOs2v~5 3N?cR[.ۙgiʙ $ߚҤ!:jLN*b:/P9v̧hC"ꁶ:!Or  g aެ`]sa) n4;%vk0;N5i) n|Q*&m%lD+Fu:͗]MMs G݆S ~yf AS]b%:Ah"T`ٕZN zAj~]}VŒJ(B{f 1N0hlm-Uf)]cEs nC~ 'Z.UXpV G'ʰkkƸK arfWuL:wBg( H,#)=\%uQsq X[xuPʛ>nV4jw~~OֱV@fob5y4_~ z]߾|/Qǩ2X~&cOgNC/ ~ eA쌞hф R7fp@8,і`2 \u}CJB<>+8gБH@Si/t ogjE\)sWD#!2R7`if욗n~M;͗;ۧۛm"Osb[:jv~ޤ]-:^z}c*Cy;Z"OE[3 gB )A7DDZ?p,GhJgB6H+!$8v '?_RC^X +RH_v_?vjb2i!+(*_f(rά"W/Rx0CS?g ~ab7 E @'"vwnEc9+3}ܠOAIAfOlBWo6xtot<{>@Mx/vv6~}ʇ.CCGE]cvm7h7(^&Ú1or~{=,< kh֫]'Qj6׼vN^Ԫd qvo F%bhhj-\)L@GajRJ@bAh}-V kvKM;Zcv Zk$nQQvz0( *=8jlUxt{Җ0:]'Mh2fC>߼P AtǏǑ{+a3 ϸ=o9 He- Ƌ6hQrJ~ƈ O&5[?>d9&[4]_]+_qN=77Bh+\)C/ ˗Ք}WWJ+Sދn85۾b#;FNʨme{pO Юh (CuEɪxٛܦ VM,w\ˁCԀh|߫ M *ڈh'Z * N?[ >,[o9ã )K Af,\Kw\F-- X=OӃ\At vpY!©4U%zeP=2L߃UF@EXJZ^R bkQ}rN4f۴V*[3_Ã$ŢD׋QL4LA+68zQhW(l_pQLtZ.?ݚ/5_k?= u_33 ~IEIH|,( ?%ˁLhH:)b槙]__ǥvZ>4#UW{51; 5l@sxR+sƓP,E$idPIiw5K*=wfهzWZ: AhgOIPxg3YzLBo'|'  ,ZUZ7#-JD;M!f*\.xU?vnD QQ(~~{AWjy;~>h(_{ <\TB'orFeu׏M/Z mg@B s#oz|c)DͦfώkyI+ޅ~6QϱUt ]SOo\K h K\nOVl݆|BDJXHIr! ݨXkDؤ /3cJA8:o_+A$4kijoƊptf3uE/G!FYg!X7,6rb?lmq b ?\=GN&W]xXV%+3!+QJpP%ۅ^R m`12c@&ﭯ>tbQ{澥.|f-SҝE){:k>vas5= nZ6 ʿJʺW!"]"|M h"[ X Le@Tb娒b đD'bq)9vB#HD}8 `0{@Q;?k4{Ez@1@1 d&`H;0}eѮG'M?e_GƝp:bY#;ܱOLw΂cAj?~pC9 ua{HNvi>R+ q = CAa](jjvla:ojZ[G')?7a3zLWLF2H`IB?G}I~sŀJRBPP*wZsdXb\@j;ej3xba$5ujglt=&F 0;i$p 2njM3.gҜu@kU\oh"MDDlb%X>{41{%XFc,Ē *ꝷf3^{kyֺoLeX1jF=76cK#/Vgpx4 3m =;llp8&SHA^id$;=,N#Lŏ%&ΕT%))4Y 1_ Ǻd RfsC[b]ԥ3O |(pn DBdftj`[^&O%F S([[%V9?1~d^zS[&S!jNb`pHuu[mSf̻xn|!n oX]l `);X3XL03+!LT_߮unlV[^eE W>wa.i&𕏨IeM!*1C-i ٵ0sica![L'WB,jsӘɵsudWteg/"QJ=̟G L ?4q1QaIDH.+xϿ¦&@T'H63*'e{8'.3 %De1#pr^kYi6z9ˢVRX8 3"{,Djr`%YjތA+S9q\"ԴSx!5 cZ1lmD TV^Q:G6(&O^#ı$]%@ؔ4SIˀNW[p`G+ a 9J̜b@^I"WWx«Juj)FKNWT3GiV 1JC'Hxџ  WJsTʌ@Dl\貍7ߖZ% "B}%a X3\&UI8&>@96(SV /x9푰*@}ڔcƆU&|$ڑ$N2Ri&#oRjv1mQF#ݳ.'_JR J~B"' TRC7M2Ė)J!䅌(Spia$/0is(>EdV3ҽQch#%u_U'\PnI6IbKFjK)!#DĚڢ27nU4)fy8'Ŕt&.:{vQH&7DB"+u^:(&^Ĉ J(c'N@ZNFΫ$>Vܟ0N=͚p]=9'O煠ls-kv`u@I>Ad=m֣ Gfii_bLN>ϜϚIPts!4ɵ=;vMkx-< g ŠWgЪ3!LiԞ'PL*&Uon_IQ^ u,ί9y%`21 $dy)F 1!4ēqSdRWMMWV'ӨKA{X{]}bCYXY̛Lf$ҥ~a(&JܙUn1_]UF u6'\lBItt|!_TQ0ctD١}Ba p^b r"ÆCL9z#p@`H'>ERF 29P[{Ӻ%"ր?rRp3tG-b?=I) Mo>2kRxr%[¥XbLQW?ry @y?!l⭏0!0MlRٽ34?E1`Rv D #Ƨk.i7\-^`Bn!Li3 L$|"0SEKRFCTH:h.k!2+HUNt c I62bo#lŕO}gKmc?ܱ˗{'ym=q Z}/sоLuw)vlc vڈ~WwNA\Vj,|8~,'@{\ l`'Nw vьUG%HW 6=">2xi io_PY|3Ji{ Evot~P̈Z 1ފ{oKM!l* ǀ;ˌ.~~PZlA-i&;.++ fPFc#ϑ^2HIkitC* `Rm*`jj"r˦ ~wy8?v5 Nا?Dχp/Ur28gXM Ufк2D, "Yy3־lS P~@E2m huI=r1ZUR^5nj9›K6SJ!&]sd8`ǕYiUD]O}и\7jSWz蘖@[Gg1Gd2vMv lO"w;_9WQ aw}kh÷*3/%#,>^뻴k?IؓwdNZٕ])spfgIooVKR~KjGڜFO<Ӊב;aRdaw=zVAӼ14K~01 &LΫ|mp jֻN}U | Σ\)@U Q (sd"pjےT+zݪ &);rh(~߾5I؁._=W|'9dAK Zfq@b <_KmcY~𻓴N[* /jSl)歹"@ʤ9#-~0*H,5j oTA:U9G$#ûArs| .a3Ko0d34u-6YUIwdOIV|{@n ]dZl0̱"7l*mXFHCԖ݃`~$ N&zP 'F?aC7^r2q5u$l\~iڢI$1<;p1f5тŁ't^I^wYquP--pi8=;?xyK~NB 6Jd7cH~Or4fϠߗ5G0)G-f/G۔{vi)Ԟ]>1ʛU`78"椯CH =[/2>#Qb~'Nik䫷.8cYݬ93#FI1{RW'nibMR;NbC"eիqHFOA@Mp<&]|{/s˅}9n8`5˃eaj{Q;HhSV"D٦.#oQ=i(p.$G'Xw@f^38o7syxK>ٗ'`#RՏ&@9p! /}$-/SN@lhT229{k[5;m8Pw>X+y4/OB!qN0jV-24RTg CY 'M9 S(?~*;dD^C0ljm PP^fNIMoΞ^tm]hsN(rkRS,v[y$};5a 38JT}??<> ]skwLv;+^zB% '/>#ֶ*ˀ2O'`5S~~,1gb-< \[tN@8-K6_N9L3t$6ߐ(浮HchinJmz&"קvh"sj_D긓fwefDVommfpNvG{VQߢɿp]ϓ]5b<|<,di bEe6W'']6rxK6{T#]wnk#腏-z] ҳٓ ۟sm?lo[u#l0ajmw񽽻Z}KUV{rn&15 e@Tip~yQC7GF%=7ۈ3 PkPI4y)`G7Z}+ڔ1CApHi h;!U} ꩚]0bxu@Tz'Y r)Bc%A<yۛqz-uGmn֏NDp'KŕOY|:D'`yNu\X'_uNHlo~+^s?sj+HJG"rcVl2/w,3X"rŰHXj7,o3, t+7пm,޼`Nȶ?AcY9)"G c ,l옟A@J~m|ŭ6u`ȱ@`%+; !k_<2-SK>T`^ܗx*eI> j |HC'^qC7 KGX w۝Ե^p&5ytoIu#j4f-É$HR~5fp۹CϨ]OTs9R[ Duo5cn'4b/A:0UϧyGd~rt_lsڽg |PM8bN EO}B-ZeYRE/{;"8`_[<ݏ/pu4H`tC$ba\cEPfs0@#FNvɏ vm)GA6yab)xI_9ܡ@~oůvv9фn}H̀Rֵ8?5.-[z]rdvl^mt:6gDy{

݀s|@@6p_[ Zr6I6r"/,n~~ijd<#oq1ips hCfջdӓf0ˡʔ-1fԪL8w!K=hـz(&@@; AM|:9jKb9f0zjtڵi.' 4orθoEFI"$LO0~BARhIK,>^D*4&M,;8BÀ~~9w,/"ZH*@n^΋_7>@;8C;e1}]:lq`)y 9K2Ŏ  .ø nc,3W1˅gj g8k+oݞ$ 9JM$)E }C#$IAOwNBOnסv7,gv| ^r V]6"|/`%5!߿w?KYz;Q= 7ˣHz/uI/> c ,wʃ݊He1>W3 6T}^UA}@g!5~h{ȟ[x'=uy4k0% 0x=2??2ƣV^OW{gPϿQD*"s&@> v|d}z@s =$jD sw IMDA}H_]Oԛ$)!IҸ8hAr.Nl};l盛ߣ=S=YMMԤ&ĸwdAQz̧k`Y8t:ұj.@-1sN%͐;U(O}=k1kRm ǻg}8Pvm@W|[yK0G N>ap7 4Ӫ Ğj_6sШUXSEBJ %t"K}=;JMN:k/~R`Czn1A #>vu ݍ }9,yõNU=?oW&P25~A߮eIc$2$TF Op%\3h&>5ᷢ lncQ,,i,ooc(OAQ"ȭ~;pnWvqsn"{{TDž;K!>}?9؛L֫oGs!v &IV4ԓM %^\$SQyNm 38qO91RVfjO}c+=~_"'\jq{mO OA~E֡ "ݙ#:_fqi!fk)ۃ ~)}TIH2^LgMP| ϼ 6U ?O/u5&8GӋd>Ӥ)Gh6iy60#/x]OQ|n'z J< m+Lߟ̣ݓՔϾݜPD~IOU@0s\YP&H R  4LkvgQI|gр=;LoC6)6L`}._{˅;s왟D> 2q׷1]cP~WJ@H&S6 lHcDR`(Kw+8WE~oL[< *R]j^.q"S,~7v^\5I( ߵedr:[ے0`!ۈU~~p_,fΊ< I~:$ @Cw8 ,*?{T8AȭQwMLE_sc=/zsV Ia uV{ K)^xsM304X`U5C"M>Lfd~IwK8 &6oP1`{&l,/6p a.zo "0V4U S@ `ۇ Ģ=F@gDp4ֱ|#mؚhkfV |q 쫶XM0ue!Ӫt|*|mrj20߫6n~9g>B 6N6nqs8 ߶빕kkGDc,NJNqNJlGaiTm7N=f&MEYD=os?x|HiJbucv`SO]@} ^e |Н8>OUN='C;:[t9X&Ta kuAii=\v ۻ9Hj1J}&c՛~$(D-qSX8 [np6l]׏\@j4Wۈ5!`qٓ@gpG/@Q}Q0? r(AWiG"p~yO<`q6V1vIG8]p |׎YL!UH#-ҩK"c>6_q WJDܥ15A@wn.@N(@|ل9D{!: RVx- [ e0zq8a8'ّ)jsDb/:_F@-G[1Ttr?%}Hj@gGГ$-ò!H*/߲xn ҧ¾o|Lg],@ ͗<ԺW -ϐ<'Jd.-oY+'Ye1i!KfiJ\9;]|QSl42v<|t2?DӅ ˀ>j#⧷Mؽ4@yj,)Kִ]*äL$3T `)8 =r?Y7Zץ\۬ۦ½O3vL>UCLn$876/\Բ%(o}~r{@o{޴Wx/F<=ώui7rQtB*?oFߞdNOb dcIE=$ ? L8It ]XL UynZ7't]_g&^ Sp-g-*$N/L]lї}A@lLKjÀ[KDF7~4E[lbpOQޏOe& ^JˀYhu"y_6~bdhuon"$}=_{`3mq''m.LO]bY1-O>\_t@ibjED.Ppr7Z ߍX)+ UM}p +T8畅sY |@sȫ2 z@A>DןmR5ZLRKJY= 7]Fڙ10k-Kc Rv`vtȆvw@ j [_X\OIqҢ6lb@ ¦QQ wKx Tlp^ǺQ_Z\0'q[;^7kU*GJ@[yA=/]U&lt8;#vrP[IZ=1!|Ɍ@ {ZT]܎ŭ {E)3>rǢՀt)3~LCP,%.g~ˡLŝej}>3du#l7qFKՁT܅ts:5OhYtN$;Mʏgva~1,ƝGu) WE1p4u@=x< \76' 1ν/r{|\%Dr?sFZ4?GUہd(pn]N@| klC p0pܾz0q x5;Y[Tu:HY[HYDH+*|84",qk Kj-jBFb+f+ibuH:8á\{8:@,$gsNT̙&i4bXN->agEj,F&$̈6^ߥw ?4Hk!%p]|%&9Po`YF{f$Qv49w1J>oeej/>PУ&j}*BmBڵ6EfUm8eәq|;8/vҢ̏ 1$O@Q2M QpEGZ} >sZH2jn@`:Ai'`ѺU3L7LiHwR ~gSӁ޶:hɗ.$sWswQH&EiS C>=S,.[c]KPS'4Dsw'u1^u&(j$ؿt ϛ:]A 1؝ 쯕mSoq٨7>I,WMכCl{R5Ws@o&[>s/VdQph=lLmV3o .O n)! -1Bhe椼¼]3Go!HM}8h`Z!ךP mAuz2ʪ?>pu6BU l1BȼkzxsƦu+^5 4蝄.#Kܚ:ohqq&OvIo|>oq8iOIAs+ x8`x;ٕÚzdrI(*-@l{>A`hMMhh񫛁Ij̅$]D~25iЫ[5V4,J;ߤw}n88O{짐Mw(3'3Ύ* tg{Oʷ[ JEm v8i.x.z="깉e'`m5ǧwBBspYCZ Y",&8КwPN9 iBTK O<(_zUcbG n R2&$ƙ 3MhHd@\@$|TmT B![}ύ*%ÇӀ_T$YK}Н\M?eκ1աt6-lq:DXe=S=h} _T"HLlkJYsK'u}paN 8UeGwz9_I,mG -Ke=n ;Ug;^У+A?`-hIʌ&iK`;O`~xҎhn#-VZ*c4V9kdȣ >KFрЎS}k ?ln}TQ 팕8J|^/M5Wwd[XcR i-/s ܁N#@64{['V ٩DFMb](1P|a8_ܑ s &nkx#oqztY\9GZ[H C!fhَ,>_{)Tfe^ j1hc?'qf<"oꠋs۵Eo%ҟAt_+Ղ)ss#1kȸeڌ mc4>ք8 IDATEFTX$6Y:rn}<@\W>iF*M6?'HRRKW^6d ?H[`Sц=VI2F*[?Rj#d^Eҧ"2 f Y@tRuCs$)K2؂a[P6JlIJgJc~"c{j8 @m(݃>9^V6wDIɒ&2MTe v^GI4O2!ڑ~U(pn޲@?a3E+Z jX :p I0d(I PNE^4+ eAp&\$ †'2md!1z,E1/IoEhye m$һƕgdU^FZ<ɸ)_w$&smF*ըbضeˇKۄ8] 1QH B>#q0a$ɲ -$ Pi=6>4'Bk 0<8XAq5HBHte:14cld.n#c6aP16rPc0 'c7ps*bj*AA}yfW @(zJcn> z !!3\/H$R YM_(eA6t 2@tӌO ړZ :Rc+[|6'l脶R04G}jD9Β I2D4r?em-i2m.r@|&y֍w2O .@3 `"qh jp$'6 CVO]UjjѿI悔{5tbJ&@2)ɁS2C%!}Y AjKjϲupmE[e1!HNeϴ)gDz.[FlL;d ͼDuB34[z mktFf L,":GtK°jH1l:hV4~8%nlR/Kc#js@yB œQ&ǃng 7l ^J˨ifT!s-=3RZR-d4`0Ι9hUsmVZr14ԾTW(ǭ e/}hwu!Q"h5ۺ@$h!m*Qm)3wqQ,judW(HFI"0һ Vڤr4$_:vt,iOHU'ئvdrZ$Fqg0Nx2 2Q2$-LUt0o8'_`քi3QO=$ߢY6>?OK :E&ZF}@YLe2#qIod)nW62&#ϲ';rl,&),A}B0pʥ4 4FrLs Z0_\' z׌T;,@R&)K_[6V-%rmNWOvπk&Cn}ΉpdZsW kAi- ey"edM@T/m3Š"~͙Dۘz#XE9-#qBdwIKllxmH۠9>y 'RE؊ߌ']1SYZZJ,6{+^o H Gq1k\dڵ{y;cmP k .P q e 4$oRezBG>X/ܛ QnE2|{D';պ0`xduj;f(2{ TJNQTZ`o\=I0/M3vɟIW e\Th3e)`V'0>L%/ZYZ_x3Nچeh Z/Z[74oL0bd|tMZEj%J.:64C:O'[PbO+MCF hTS;)9r G@Ajlz9e8)ЅԄK%cJ^h'> $ʺK=}A-G͵j6ω4|5[nL۴if+V̀S9CZtA5Z6di< f*}26¸ƖK>3k6Rf$hB%(K Ed]̇l~ BT6Cס %}# !KAv#U:_k6B+@rB[S1}ӿ8Xct탈j A ՗9EYsW)֢EˋoB7ka@c.%fxX[q5YI*oiϿ^Q_QLF)yk뢒#[-4|uy;LK7z hhtVH40Քە۩mLUgǥ 6yuO_?޵1z}+?2>9oІpk vd I*#Ԋ7;.koA'z2)l]ʪ*꾦V1d&'/On镮+Vm溲TXΗ]qo%wJJ8um_m;`х@<` f'"vQWZ&y>Wf<2fW$*-Яz|c4h9Jjߌ9s lui1 -^LU6Իh5OT:h )uڄl=GSZzn3+z6[N<>o{_^5chjmSN.kMmV&ji=Mw_٦Ɩ{)6&z1w%ؘu6}?̘Lg_Vq-[lhѢ4܁!3C-݃>$϶C,=چ1m۶|gny{1YIENDB`(0`    CLLKIHGFEDCB@?=<;987 5 3 1 0 . - + ) '&$"    D-+)'%#!~ |zwurpmkheb`] Y V S P MIFB?;740,(%!  N-+)+2,!!*(xurqu!|0q fb`daV S WVJPJ?;@?40:<*   O-+)|">.uth`V aλO?pHʾW2kY  O-+)Ա/p]uv5`V ONƴtKEI!wO0D&  N-+,X˥նux&km`MNF402 ^A  O-+Fغluslj`ëN N g=747 ¹K5  O-+u[:ʤ}'ǣJl7δ`V h/NV+4V11"!  N-+Ϩ0T~!nP9̮@`ѽWNƴPW/>t  O-+z%,l|2Hs1ß{3c`rof)MK {\?K|d2O,{A*  N-+KN%$e*}{ycvv hYhcw1oZWP Mc*j9B?;740,(%!  N-+%$ƛn}{C׼tвMŤc}aFP LbB?;740,(p Q!~ -  N-+%$IӴҳjy"plv(da] Z o.P MbB?;749g /v s h 0? O-+Ѭb_(F0}'-nlnda~>~wP MbB?<74f |X Ko | N-+*zXƠv.nlndxtr3T P MbB?<8PNyA(!,Rr . N-+%$"3ϭLv.nlnd̲AZ W T P MaB?<Dhx )$!"y yy N-+ЫϪO ϭyv.nlndYcq<8v -(%!5~ N-+4A@>+ *.xvu~-nliu)c`j |?m,V _c&`%]%Z$R<g -)%!&wx N-+)'%$" |zxvsqnlhfc`] Z V T P MJFC?<b-)%!i k! N-+)'%$" |zxvsqnlhfc`] Z V T P MJFC?<9[t-)%!D N-+)'%$" |{xvsqnlhfc`] Z W T P MJFC?<A|[G)%!Cf ^ O-+)'%$" }{xvsqnlhfc`] Z W T P MJFC?<< r,%"U @ O-+)'%$! |{xvsqnlhfc`]Z W T P MJFC?<84T u -45{I O-+*'%$" |{xvsqnlhfc`]Z W T P MJFC?<84SzSoQo {  O-+*'%$" |{xvsqnlhfc`]Z W T P MJFC?<841-) :iK  O-+*'%$" |{xvsqnlhfc`]Z W T P MJFC?<841-)'3gb ] e  O-+*'%$" |zxvsqnlhfc`]Z V T P MJFU =`g 1-)%,  O-+*'%$" |{xvsqnlhfc`]Z V T P Ne r : >Ds r * O.+*'%$" }{xvsqnlhfc`]Z W T P Om\ o y c  x r k  O-+)'%$" }{xusqnlifc`]Z W Y tX P?<88G} k u_ [ u%  O.+*(%$" }{xvsqnlifc`]Z W V p u FC?<841=n ~ b ~|  O-+*'%$" }{xvsqnlifc`]Z e JFC?<841-3mz # b   N-+)(%$" }{xvtqnlifca]Z OJFC?<841-)RX}  O.+*'%$" }{xvtqnlifca]Z W MJFC?<841-)9q.  O-+*'%$" }{xvtqnlifca^[ u MIFC?<841-))5  O.+*'%$" }{xvtqnlifca^[ u MIFC?<841-))5  O-+*'%$" }{xvtqnlifca^[ X MIFC?<841-)9p.  O-+*'%$" }{xvtqnlifca^ [ OJFC?=841-)RY}  N-+*'%$" }{xvtqnlifca^ [ f JFC?=951-3mt O  N.+*'%$" }{xvsqnlifca^[ W W q v GC?=951=n } P  N-+*'%$"!}{xvtqnlifca^[ W Y tY Q?=99I| U  N.+*'%$"!}{xvsqnlifca^[ W T Q Pn\ p y d %"  N-+*'%$" }{xvsqnlifca^ [ W T Q Oe s : >&"  N-+*'%$"!}{xvsqnlifca^[ W T Q NJGU >`g 1.*&"  D.+*'%$"!}{xvtqnlifca^[ W T Q NJGC@<951.*&"   CMLJJIHGFDCB@?>=;:87 5 4 2 1 / - + * ( &$#!    llllllllllllllllllllllllllllllllllllllllllllllll( @ Z Z x(*'%"~zwsplgc_Z U Q LGA<71+&   -*8o,_-?vTR*gI|fS<  .*{d×>CF[|K~ĶK"l?*  .*ӯغėsϱlSF˶Lƶ= 1iL:$  .+Z˩}mhFm-YDExb9  .?*J}'VDPvpD  .,L%D'{1,|*i7dx3_s6P Lf1D << 3-3#  .,̣%er=3˫>Ÿs(Uw6f(LA<71+b Rs /  .,ԲM6ڿlϰ|%laMdNȯb!LA<7Mm f   .,ٻh;`e|'l^P]bQ LA=Pz /  ] .,~TE{"|'l^Pgvr8nmNR 3& /o  .+86,~ *wtv llg`o*aX[VQ@ r ,& l C -+(%"~ {wtplhd_[ V Q LGB=],& * .*(%"~ {wtplhd_[ V Q LGB=i S& \ { .*'%"~ {wtplhd_[ V Q LGB=9G i ++e n  .+(%"~ {wtplhd_[ V Q LGB=7As v ] _  .+(%"~ {wtplhd_[ V Q LGB=72,B]~ ] > .+(%"~ {wtplhd_[ V Q LJt b B/&\| z L .+(%" {wtplhd_[ V Q u } \r2.rB .+(%" {wtplhd_[ V q H=7= } z M .+(%" |xtplid_[ j i GB=72. \S= .+(%" |xtplid`[ MGB=72,?/ .+(%" |xtqlid`[ LGB=72,, C .+(%" |xtqlhd`\ LGB=72,, C .+(%" {xtpmhd`\ MGB=72,?/ .+(%" {xtqmhd`\ jj GB=82. \ .+(%" {xtplhd`\ V q H=8> G .+(%" {xtqmhd`\ V R v } '! .+(%" {xtplhd`\ V R MJt b C0'! y(+(%" {xtplhd`\ V R MHB=82-'! Z Z(  +KHDA=94 / * %  MB.qhO[}VvVlfT MyȟҲhī\>`M MiWIW_rvo:j=`;iK5 MkCwgd]|;eP?;l f S Mu]5RW{q5tW%h B;: M-*~!vogbXQD { )U M)#}unf]S J?`Y$Q1 M)$}unf]S J?8Vz V M)$}unf]S k } x Sn f M)$}vnf]}p A7p y V M)$}vnf^J?41`  M)$}vnf^J?41a  M)$}vnf^}p A8p 7 M)$}vnf^T k ~ x F +KHEA=95 0 + &  AAAAAAAAAAAAAAAAFaustWorks-0.4/Resources/FaustWorks.png0000755000175000017500000001025312130743520016720 0ustar miramiraPNG  IHDR szzsRGBbKGD pHYs B(xtIME 0#GV+IDATX   Z SC&  -A#5 [uA=3> N d?'36^$.P   >9,1 K4 * *;H6 2 Dl i$$ 3 QP0+") ;  )0)-)!8<03$ ^ $) +$ :'#^3 O!d='?(VlP" 7 P.jP/I1:A!*8Ln=4 ~T (?7(7 A#C(\92cA_& 3 Ux 2& % ?/ 4 !Fhk; wZ9m+eu,ggM"ٰUd6 =#B'lpgCeLnQ.]66%1&(K.)*+j]qdG>2A7dK      #$gecnIENDB`FaustWorks-0.4/Resources/FaustWorks.rc0000755000175000017500000000010112130743520016527 0ustar miramiraDI_ICON1 ICON DISCARDABLE "FaustWorks.ico" FaustWorks-0.4/Resources/add.png0000755000175000017500000001236312130743520015344 0ustar miramiraPNG  IHDR szzbKGD pHYs  ~ zTXtRaw profile type 8bimx|K末KrdIA'SG7pTbQERH=?!dSU*"CU~H`o .~H! A$ؽfż>{$ZGUfVHt5:9DGo#h :zI]w uK>=-Ro1 UJBB\wJc7;ˇ;E/FFJ>ɏ0MQ ](Eֽ >5M"$߯h]H c'x(h~: zn3Afw[ʟoԽtw.]$~YUCKBR>#L ϰlT}D|B@1w^a~wp(WXѠ]nf^O'Lrw|(e$~胧gHKu pn7ÙP>-%@L'BCW5`~[0<%xK1&&!MPbp~K `lC?(`[_Ou\;sY%OI>:!P72|az&Pv ?HG/ s³8Z;4HC]Y {|cCLx ho-·-o<,i(jw/ j9oU@ߔ=]| =č0Q ߃;ӻgا}ǦkIo{ȍb߲nM8֯F{Cn F$oG+Z6IơT)SNyCO*&y*P^KcRqF ]I}}׍iZ&|][;0]s_[/Pou|n 07em[D#/.,4\xHa>lZg.L%OVgNiK:ɰ䤅3:{W^|ѧ5JgKbKsB^}g1Vm(%JF,9p֜K[w聾(;icԖ^cTsY|,xePẌZ̖N 5v>gbEBjD*ĭnP.f^J,4&.-Xg0 Mܣeȱ2t =Jׅ$0"UUb#*"XIll.sJCGXjRq5=\nsXDNvۤ ּf-@ 陈s/fQlL[C̔to&u u 9֐vYq&Қsz":9(0""zY b#9۹}&FD D? b!tJ vpAg IDATXkUW}̝{ La08TRF ilդ)!ᇍ&ڄЈ5MMLaAV1T $ma2@yMLqg}{9gs{?d'{YzX]jv=Im*fR]yo/ZbPa'^zc1gߖ}aC젽m.ay%'O:/뚗oͿ{]͵U;7fժNSSgL(B q8}qro1c.\㗞?887׭{1>`^* "ZꨮrHr굚{Zï=yv;|_aOm\ݱb%]"p@k "b-5$dd,Zr*%v_cJz.^`plb$DUADʭEQT! XBN ]xvm ]+W8 JBl:M6%C\#X+*`Z,mÄΝ{o&롚dl.[K"% -~!uq#q^xqZ)BԀ: bX&?rk;",HĶs(cPЂ||!  9l&C.#^6M}<|z뮽nP̤6-kket,DC%Fٮ (V>AkINŀDB> M&T2]53$Z>Q,rp }[c` /bFOA70`E#-4dHOv=(8n1*T0BQb5qΊ^."`P(yuT?־+*%V]M!7RX(|*Xݷ%6ү(/GU)5;0NNL!0e1;A}*L/4? QB* O0DEZ kƅX_wK}3e >l''1?QvPU `Pg@y)0Uɩ \&RI^k-A`Q5Z*Qe*=A&~̺+P]_w3oS}ҩT EP:p{+ZUDKų$杪cw0Mj7*Dёэl`E(`hQGmx|b`v?sǏnXRԒDSy띗@,#^8`/QHΝ>hiWsg~Ň>10c"7*m(Q(}rOo2|ky'p!Vc\[CTĂZ(r#y{E-DZ ~CC7oYuF6%WO_| PUbSo&=9zt՚~=SNWYO ~/ _x*6/m׫ڨQhȥX,?J)%fMfSOAӴ`!L$dhC45h|ce@CR3GjDu)Ob1GScі0L/0[ݔJ4-iƦW=kI-)Y (h%8@=/-W Wђ# @b1[zΙ_ 'k%zTXtSoftwarexsLOJU///P03D'u9k&zTXtTimestampx32002024S022621%˺b}IENDB`FaustWorks-0.4/Resources/addFaust.png0000755000175000017500000000515512130743520016350 0ustar miramiraPNG  IHDRBBTbKGD pHYsHHFk> vpAgBB ; IDATx]lo@ JSJD -U)BTj&C$D 5RҾT 52J*/Ui*HSDl @ml޹#69ܽsΜם5|)HسgfY Z K/$3ѡf?[c{{{;N\$b}s!G)o NYV\Y:nݺrz> 1|T\kt5Wr3! &Hh2ɽd>غi ؋Ѽ{W%jQ{WS>L&Ö-[X~}reDB.!d pswN]f ׯ_cǎFtuuϫ}IU~)p*E}2{74tR<ۓCCCr9jkk եO>8X3 \ηgbjDNmkkk׮޽{imm+VL5|pj.DaFV8\S#> QZ >"歳(0rNLi־>6lMHRslc,"cLi(g2>=:m{nvܩs^} Ma*eqŹqF._\tէ@%@-6RWRX}vtt 0է1G8EmAqHQu΋x@Bq"BEPquЅ>)qޝfB #;LAUV&Oxb& ʤ*VHfo?zwmhʹ"++^h/7ΠeFږ|ST}cNՏiy7k|{3StGQ;`Ԉ w9a9fGQTC\ LQ"5RXA(SOg8quM2YB@HƛO$(i GEO>_g$UH"0zdpBJ|[`Lcg7eM7#s;I<gVs;#FD!("(w<@m yg;UtD{pz)⮻, cܿ0g(&f#B-ɤV& 7zaӼ?!=*"Z-!52Q ij>[$Jrg%A x4F$&U0ꃥQtU_';z1EsJ( PiH71 +"(A< F;Uuc$HvGxsY7u:oa,Q1<& B"HdQ6 LJQeh3K8-dJpN@X#{ej G۰o4Ujp.݇,$Ђp6'D G[`~Q)Çuƍݽ_xP\FL$jD!6BQE7vZZjq&СC+ B$!? ZcBر]4 qSۏka<#M*,B?q[r+Tqcݺu[ jooB?Pϝ;WWWW7moNZx衇xGK#cQ%#*.p Hm۶%svtth VRd F:%> Mn7^q2~1o}Д#4n}n^)yTg>OcG/J T9|;3k e{|q…VjjLGE -ƅr)-l FF0>!dndaQϵcmPYɯCZ!B6 kyY^,X. NXd}kp %tEXtcreate-date2008-12-05T15:19:23+01:00&2%tEXtmodify-date2008-12-05T15:19:24+01:00$/IENDB`FaustWorks-0.4/Resources/addFromFile.png0000755000175000017500000001273412130743520016772 0ustar miramiraPNG  IHDR szzbKGDC pHYs  ~ zTXtRaw profile type 8bimx|K末KrdIA'SG7pTbQERH=?!dSU*"CU~H`o .~H! A$ؽfż>{$ZGUfVHt5:9DGo#h :zI]w uK>=-Ro1 UJBB\wJc7;ˇ;E/FFJ>ɏ0MQ ](Eֽ >5M"$߯h]H c'x(h~: zn3Afw[ʟoԽtw.]$~YUCKBR>#L ϰlT}D|B@1w^a~wp(WXѠ]nf^O'Lrw|(e$~胧gHKu pn7ÙP>-%@L'BCW5`~[0<%xK1&&!MPbp~K `lC?(`[_Ou\;sY%OI>:!P72|az&Pv ?HG/ s³8Z;4HC]Y {|cCLx ho-·-o<,i(jw/ j9oU@ߔ=]| =č0Q ߃;ӻgا}ǦkIo{ȍb߲nM8֯F{Cn F$oG+Z6IơT)SNyCO*&y*P^KcRqF ]I}}׍iZ&|][;0]s_[/Pou|n 07em[D#/.,4\xHa>lZg.L%OVgNiK:ɰ䤅3:{W^|ѧ5JgKbKsB^}g1Vm(%JF,9p֜K[w聾(;icԖ^cTsY|,xePẌZ̖N 5v>gbEBjD*ĭnP.f^J,4&.-Xg0 Mܣeȱ2t =Jׅ$0"UUb#*"XIll.sJCGXjRq5=\nsXDNvۤ ּf-@ 陈s/fQlL[C̔to&u u 9֐vYq&Қsz":9(0""zY b#9۹}&FD D? b!tJ vpAg IDATXk\UޝǾnٶtB UR" *$|AI%BD'B, AT"vG3{yN]/$sϜs_w#v?Й:<U9t6oh4in|! G+9u/gK@4q^FFF8OH飕C4Mkn K_ F`F໾3 ͕guR,|siW׼߶վ6_7 D 8t(OuEKַ-Mؔ+33C^cws=Tfglh `LUR[ɩ}!ྡΧ$649/lodlIgsŪ ?$ c(&6\%Y֯ÇF?0 ;^߲餤Լ؂*HqWse>x>tT !"bEQnl76tKK뷯d$k/[H20;ۯ1j RE f\uDa~6o?пjϏV{o߸zuH-,aZ'.}+ql0ST(V̙]Rʥ|Vt=cGW%Q iii[%0 "(DQHSqI|c߉ё 02ɯMRkew]C1P϶m7ޞq Ø0VO p݀JťRv9rx$s&zbcO`͖; wܜ{r蒜hD)+)F}5F$gq,ˆ8x^ۗ;%.. RH"+mV@0WIYشi}ݎ7#QI[MFJI =B?h9%р4Zk󚫳uWW[BXV-`m -]t ~|a(‡6_Yd˶l*7u?˲e[m#&h>*mXԙ$Ʀ4K|֜<.j(*u%zTXtSoftwarexsLOJU///P03D'u9k&zTXtTimestampx32002024S022621%˺b}IENDB`FaustWorks-0.4/Resources/addFromFileFaust.png0000755000175000017500000000713212130743520017771 0ustar miramiraPNG  IHDRBBTbKGD pHYsHHFk> vpAgBB ; IDATxm\y9άwmlWԤ"%&F8ڴPKD[J&\R*TPlU"TD 6/(E1Pجug9sgv6g5{ϝ9=܇سw^=?!fz^ye7XvyJ,$ɲБ;c0\|?OU[kW84 =Wx|Z?xٜ=Z"V+bvU;߼X3;k}\e,'Y<ƎӵmH{ﲉ`ZwMm}wvM'΋X@=p:>Ok[c͛7[op͗spy`?k.}3BpO `;< v-Com6GR'֭[t'oOTMqwܱcZwMmΝ;?Q,8k ?s}w^}GKXbpYuoZc+hPTםs:tw}=<~jpj2ZRX&&&8pwytIP*v|o 6({ͳw\qH_Au   XM(7Pಟ+SݺSRF$.j173CWaj< `;8*Lbi273G|j@$6A[2QXӨtp΃s=zYzh :m!AL' R@̒amfkv|2t ^/5%g~r)ibqJeB!%I hPL{P+K" 8:LvqE:Ƙ܁'_ #3lx! bl`+я -@0 +!?<C͋~ZSx:ufKp*sϪoc>C@ Z]P(*-"i+ AK1bUd@T1y4RT'fp_S7faZk400jRbXbGeh,@ț4E0+U>.TJB^!tLXضtц 7ŊPblR#"oJCJ@WA! 00NH|O۲K"q6h _}u% c,61\pIJa,k@>FDьLOx>/Cfjjy/幦w h3>6UX$(+cl pYqL& r8bRx1NzP8u;aK/4 p.ƴwc rT*1 s/;ߪ7qyjA"|[ǎ_S==,@5f^nEbmlx**qa+$}ѓ.|,4kǡ80YRՓe-Z$ %@8Sf|ݺȆƂdB@U!"=$8Pa^ճ|W~ZqWSO),={r /G]r\.yU_Q.Ӫٴa`_2v䔏iSNK, Ȃ|J~U ǎM==g ψУYyHcBܾ(^G٠ԛͶ#&%t1Ȩ]_[?|Ȅtdhm:Y`٦Մ01#$le87|W<mtIOUrlejRE7~)ZvN_ktEl _7kt%tEXtcreate-date2008-12-05T15:21:42+01:00S%tEXtmodify-date2008-12-05T15:21:42+01:00gIENDB`FaustWorks-0.4/Resources/application.qrc0000755000175000017500000000100512130743520017107 0ustar miramira zoomIn.png zoomOut.png fontBigger.png fontSmaller.png add.png addFromFile.png remove.png copy.png paste.png resize.png new.png save.png saveAll.png open.png hAlign.png vAlign.png FaustWorks-0.4/Resources/copy.png0000755000175000017500000000247212130743520015566 0ustar miramiraPNG  IHDR szzgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATXõ]L[ewoI q&NpхDP+.&J'Тl9@lC +(іJ{*<9o!,/zc@}}P2Ff dn:~E"+*0@mWڪ4|S5@f:eCբcw*wڻeyBgg'zzz8PIiniog%3 @(cmm | =@A677vVUG;%$3O$(+6Z0'<=MIɩJ=0|qɘPzHk朙WdSjF< fd(;dH=sӹ@ eU-:c}iv]=&rJ*pW=~g.@DqL+++X__'Yt POe24XdNi)9D@|[O~uqq,~Nm7d,m72%#'hf[O5xGJ.7RR:)"E\---n`җ `}iiC ͲТRNxT;5`Zy `0$g@SS[gJO"7@GGG#mmm|A'@ss3JGT?U???h4:ô]L0xGRv:bJJo>ޙ#gSuVnłHmm377WVFLAnC9VpIENDB`FaustWorks-0.4/Resources/faust.qrc0000755000175000017500000000100112130743520015722 0ustar miramira addFaust.png addFromFileFaust.png removeFaust.png FaustCommands.xml seq1.png seq2.png par1.png par2.png split1.png split2.png merge1.png merge2.png rec1.png rec2.png FaustWorks.png FaustWorks-0.4/Resources/faustworks.png0000755000175000017500000001025312130743520017020 0ustar miramiraPNG  IHDR szzsRGBbKGD pHYs B(xtIME 0#GV+IDATX   Z SC&  -A#5 [uA=3> N d?'36^$.P   >9,1 K4 * *;H6 2 Dl i$$ 3 QP0+") ;  )0)-)!8<03$ ^ $) +$ :'#^3 O!d='?(VlP" 7 P.jP/I1:A!*8Ln=4 ~T (?7(7 A#C(\92cA_& 3 Ux 2& % ?/ 4 !Fhk; wZ9m+eu,ggM"ٰUd6 =#B'lpgCeLnQ.]66%1&(K.)*+j]qdG>2A7dK      #$gecnIENDB`FaustWorks-0.4/Resources/faustworks.svg0000755000175000017500000003713512130743520017043 0ustar miramira image/svg+xml FaustWorks-0.4/Resources/faustworks.xpm0000644000175000017500000002315212130743520017037 0ustar miramira/* XPM */ static char * FaustWorks_xpm[] = { "32 32 475 2", " c None", ". c #0D11AE", "+ c #0D10B1", "@ c #0D10B2", "# c #0C0FB1", "$ c #0C0FB0", "% c #0C0EB0", "& c #0B0EB0", "* c #0B0DB0", "= c #0B0DAF", "- c #0B0CAE", "; c #0B0BAC", "> c #0E14A7", ", c #2567EA", "' c #2C8DFE", ") c #2A89FE", "! c #2686FF", "~ c #2483FE", "{ c #2180FE", "] c #1E7CFF", "^ c #1C79FE", "/ c #1A76FE", "( c #1772FE", "_ c #156DFE", ": c #1369FE", "< c #1165FE", "[ c #0F60FE", "} c #0D5CFE", "| c #0C58FF", "1 c #0A53FF", "2 c #094EFF", "3 c #0849FF", "4 c #0644FF", "5 c #063EFF", "6 c #0439FF", "7 c #0333FF", "8 c #032DFF", "9 c #0227FF", "0 c #0221FF", "a c #011CFF", "b c #0115FF", "c c #000EFF", "d c #0208EB", "e c #0B0BA8", "f c #0E13AA", "g c #2977F6", "h c #2B8CFE", "i c #084EFF", "j c #094EF9", "k c #0C76C4", "l c #0C6BCB", "m c #0D87A7", "n c #0648E8", "o c #0433F9", "p c #0008FE", "q c #0B0BB0", "r c #1E7CFE", "s c #0C71D3", "t c #13A68C", "u c #10989B", "v c #0E7FB4", "w c #0C74BC", "x c #11A384", "y c #109C8A", "z c #1368FE", "A c #1194AA", "B c #119C9D", "C c #0D75C9", "D c #0647FC", "E c #0438FA", "F c #0E86A1", "G c #0E8B99", "H c #0748D8", "I c #0114FF", "J c #2877F5", "K c #0E6FE0", "L c #12A397", "M c #0C73D0", "N c #0E899B", "O c #0B6CB4", "P c #0221FA", "Q c #1084C5", "R c #118BB5", "S c #084FFE", "T c #0438FF", "U c #053BEB", "V c #0D81A0", "W c #032FED", "X c #1291B2", "Y c #1085BD", "Z c #022AFC", "` c #0D7FA1", " . c #074AD1", ".. c #1183C4", "+. c #1197A6", "@. c #032DF9", "#. c #0F9090", "$. c #0539E1", "%. c #2383FE", "&. c #128EB5", "*. c #129CA0", "=. c #0952FA", "-. c #053EFF", ";. c #0645E0", ">. c #119B84", ",. c #0430EB", "'. c #1771FE", "). c #0D60F3", "!. c #118CB4", "~. c #0432FA", "{. c #0D7EA6", "]. c #0C70B0", "^. c #0A61BB", "/. c #0A5FB8", "(. c #0642CF", "_. c #0D5BFF", ":. c #0C57FF", "<. c #108AB7", "[. c #119B9E", "}. c #0E7EBF", "|. c #0856E9", "1. c #0439FE", "2. c #074EE1", "3. c #0F899E", "4. c #0D82A1", "5. c #0E819F", "6. c #0C75A7", "7. c #0D77A1", "8. c #0855BE", "9. c #2686FE", "0. c #0A52FF", "a. c #0C6ADB", "b. c #12A095", "c. c #10959E", "d. c #10969A", "e. c #0E8DA1", "f. c #109694", "g. c #109295", "h. c #085EC7", "i. c #12A27E", "j. c #0431EA", "k. c #0532E2", "l. c #119B7E", "m. c #063FCD", "n. c #1975FF", "o. c #0B68D4", "p. c #085BDD", "q. c #0B72BE", "r. c #0540F1", "s. c #0226FF", "t. c #0859C7", "u. c #0E829B", "v. c #0E8298", "w. c #0643CE", "x. c #0007FE", "y. c #0643FF", "z. c #074FD5", "A. c #095BC4", "B. c #0C76A7", "C. c #0852C5", "D. c #0431DF", "E. c #2889FE", "F. c #0848FF", "G. c #0647EA", "H. c #0E82A5", "I. c #0D7EA5", "J. c #0D80A1", "K. c #0E819C", "L. c #0C72A6", "M. c #0B68AC", "N. c #1C78FE", "O. c #0541F6", "P. c #085DD1", "Q. c #0E81A6", "R. c #0855CF", "S. c #0221F9", "T. c #084ACC", "U. c #0D779E", "V. c #0530D9", "W. c #1164FE", "X. c #0962D0", "Y. c #109595", "Z. c #0747E2", "`. c #011BFF", " + c #0850C2", ".+ c #108E86", "++ c #2B8BFE", "@+ c #084DFF", "#+ c #0B6DC4", "$+ c #0E85A5", "%+ c #032CFF", "&+ c #0328E6", "*+ c #0D749D", "=+ c #0E2B9D", "-+ c #51A0FE", ";+ c #5CA4FE", ">+ c #4998FE", ",+ c #4996FE", "'+ c #3B87FE", ")+ c #2271FE", "!+ c #2773FE", "~+ c #1463FE", "{+ c #4E87FF", "]+ c #4A82FF", "^+ c #2364FF", "/+ c #467AFF", "(+ c #4676FF", "_+ c #4472FF", ":+ c #154AFF", "<+ c #0B71C0", "[+ c #0D80AB", "}+ c #0013FF", "|+ c #0325EA", "1+ c #0C6FA1", "2+ c #0D309A", "3+ c #AFD3FF", "4+ c #5AA3FE", "5+ c #4797FE", "6+ c #388DFE", "7+ c #D2E5FF", "8+ c #3D8CFE", "9+ c #9FC4FF", "0+ c #498BFF", "a+ c #669BFE", "b+ c #95B9FF", "c+ c #4883FF", "d+ c #5086FF", "e+ c #2565FF", "f+ c #4378FF", "g+ c #B2C6FF", "h+ c #4270FF", "i+ c #1449FF", "j+ c #085ED4", "k+ c #109594", "l+ c #0641E8", "m+ c #0747CA", "n+ c #0F898A", "o+ c #BAD9FF", "p+ c #91C2FE", "q+ c #5AA2FE", "r+ c #88BBFE", "s+ c #3C8EFE", "t+ c #8DBBFE", "u+ c #81ABFE", "v+ c #91B4FF", "w+ c #467FFF", "x+ c #99B4FF", "y+ c #0642F3", "z+ c #085FCE", "A+ c #0647DD", "B+ c #011DFD", "C+ c #053DD8", "D+ c #0D7F97", "E+ c #0534D6", "F+ c #A6CEFF", "G+ c #C8DFFF", "H+ c #96C2FF", "I+ c #CAE0FF", "J+ c #1C77FF", "K+ c #4E8EFF", "L+ c #6098FE", "M+ c #2269FF", "N+ c #A0BDFF", "O+ c #3A74FF", "P+ c #0437FF", "Q+ c #0648E7", "R+ c #0E87A0", "S+ c #0E869D", "T+ c #0D7EA2", "U+ c #0E7F9D", "V+ c #0D7B9D", "W+ c #0B6DA7", "X+ c #5BA3FE", "Y+ c #6FACFF", "Z+ c #1D7CFE", "`+ c #5E9FFE", " @ c #5F9FFF", ".@ c #90BBFF", "+@ c #71A6FE", "@@ c #A3C4FF", "#@ c #2873FE", "$@ c #72A1FE", "%@ c #6496FF", "&@ c #A4BFFF", "*@ c #2867FF", "=@ c #0332FF", "-@ c #0852D2", ";@ c #0642DE", ">@ c #095DBE", ",@ c #0222F1", "'@ c #000DFF", ")@ c #2D8CFE", "!@ c #66ABFE", "~@ c #2887FE", "{@ c #4294FE", "]@ c #4393FF", "^@ c #589BFE", "/@ c #1E78FF", "(@ c #2278FE", "_@ c #629DFE", ":@ c #4287FF", "<@ c #1C68FE", "[@ c #6597FF", "}@ c #4980FF", "|@ c #165AFF", "1@ c #366AFF", "2@ c #285DFF", "3@ c #073FFF", "4@ c #446AFF", "5@ c #1742FF", "6@ c #173DFF", "7@ c #435EFF", "8@ c #3049FF", "9@ c #011AFF", "0@ c #E6F1FF", "a@ c #4E9CFE", "b@ c #B9D7FF", "c@ c #C3DCFF", "d@ c #3A8DFE", "e@ c #EEF5FF", "f@ c #277EFF", "g@ c #DEEBFF", "h@ c #A9C9FF", "i@ c #D4E4FF", "j@ c #88B2FF", "k@ c #3378FE", "l@ c #FBFCFF", "m@ c #AAC4FF", "n@ c #F1F5FF", "o@ c #1D5CFF", "p@ c #9DB7FF", "q@ c #89A6FF", "r@ c #ABBEFF", "s@ c #99ADFF", "t@ c #103DFF", "u@ c #E9EDFF", "v@ c #91A1FF", "w@ c #ACB6FF", "x@ c #B1D4FF", "y@ c #84BAFE", "z@ c #CFE4FF", "A@ c #CBE1FF", "B@ c #77B0FE", "C@ c #B8D5FF", "D@ c #69A5FF", "E@ c #D2E4FF", "F@ c #4488FF", "G@ c #EFF5FF", "H@ c #F8FAFF", "I@ c #6594FF", "J@ c #E9EFFF", "K@ c #1757FF", "L@ c #EEF2FF", "M@ c #ADBFFF", "N@ c #0739FF", "O@ c #123EFF", "P@ c #EFF2FF", "Q@ c #97A6FF", "R@ c #495FFF", "S@ c #81BAFE", "T@ c #D5E8FF", "U@ c #ADD0FF", "V@ c #A1C9FF", "W@ c #D4E6FF", "X@ c #85B6FE", "Y@ c #66A3FF", "Z@ c #D6E6FF", "`@ c #488AFF", " # c #ECF3FF", ".# c #FAFCFF", "+# c #9BB9FF", "@# c #D1DEFF", "## c #1053FF", "$# c #D7E1FF", "%# c #DEE5FF", "&# c #234FFF", "*# c #6F84FF", "=# c #F2F4FF", "-# c #2F43FF", ";# c #4C9DFE", "># c #FFFFFF", ",# c #78B2FE", "'# c #6AAAFF", ")# c #4E96FE", "!# c #1F78FE", "~# c #C8DEFF", "{# c #BFD7FF", "]# c #DAE7FF", "^# c #71A3FE", "/# c #F6F9FF", "(# c #0C56FF", "_# c #C0D2FF", ":# c #749AFF", "<# c #84A2FF", "[# c #5D81FF", "}# c #E3E9FF", "|# c #4164FF", "1# c #C8D1FF", "2# c #B0BBFF", "3# c #E8EBFF", "4# c #162DFF", "5# c #2989FE", "6# c #348EFE", "7# c #2784FE", "8# c #2381FF", "9# c #2C85FE", "0# c #1E79FE", "a# c #1874FE", "b# c #1972FE", "c# c #2F7DFE", "d# c #2272FF", "e# c #1261FE", "f# c #1C65FE", "g# c #1257FF", "h# c #1455FF", "i# c #124FFF", "j# c #0F49FF", "k# c #053DFF", "l# c #1242FF", "m# c #0C39FF", "n# c #1138FF", "o# c #2443FF", "p# c #0D2AFF", "q# c #0006FD", "r# c #0D13A1", "s# c #1C46D4", "t# c #2369EC", "u# c #2168EB", "v# c #1F65EB", "w# c #1D63EB", "x# c #1B60E9", "y# c #195EE9", "z# c #175CE8", "A# c #1559E8", "B# c #1456E8", "C# c #1253E6", "D# c #1150E5", "E# c #104DE5", "F# c #0E4AE4", "G# c #0D46E5", "H# c #0C43E4", "I# c #0B3FE2", "J# c #093BE2", "K# c #0937E2", "L# c #0834E1", "M# c #0730E1", "N# c #072BDF", "O# c #0628DF", "P# c #0524DE", "Q# c #041FDE", "R# c #041BDD", "S# c #0417DC", "T# c #0312DC", "U# c #030DDB", "V# c #0508C4", "W# c #0A0AA1", "X# c #0C119D", "Y# c #0C12A4", "Z# c #0B12A4", "`# c #0B11A2", " $ c #0B11A1", ".$ c #0B10A1", "+$ c #0A10A0", "@$ c #0A10A1", "#$ c #0A0FA1", "$$ c #0A0FA0", "%$ c #0A0F9F", "&$ c #090E9F", "*$ c #090E9E", "=$ c #090D9E", "-$ c #090D9D", ";$ c #090B9D", ">$ c #090B9C", ",$ c #090A9D", "'$ c #0A0A98", " . + @ @ @ # # # $ $ $ % % % % & & * * = = = = = = - - - - ; ", "> , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e ", "f g h ) ! ~ { ] ^ / ( _ : < [ } | 1 i j k l m n o 9 0 a b c p q ", "f g h ) ! ~ { r ^ / ( _ : < [ } | 1 s t u v w x y 9 0 a b c p q ", "f g h ) ! ~ { r ^ / ( _ z < [ } | A B C D 5 6 E F G H a I c p q ", "f J h ) ! ~ { r ^ / ( _ z < [ } K L M 3 4 5 6 7 8 N O P I c p q ", "f J h ) ! ~ { r ^ / ( _ z < [ } Q R S 3 4 5 T 7 8 U V W I c p q ", "f J h ) ! ~ { r ^ / ( _ z < [ } X Y i 3 4 5 T 7 8 Z ` .I c p q ", "f J h ) ! ~ { r ^ / ( _ z < [ } ..+.i 3 4 5 T 7 8 @.#.$.I c p q ", "f J h ) ! %.{ r ^ / ( _ z < [ } &.*.=.3 4 -.T 7 8 ;.>.,.I c p q ", "f J h ) ! %.{ r ^ / '._ z < [ } ).!.s 3 4 -.T 7 ~.{.].^./.(.p q ", "f J h ) ! %.{ r ^ / '._ z < [ _.:.<.[.}.|.-.1.2.3.4.5.6.7.8.p q ", "f J h ) 9.%.{ r ^ / '._ z < [ _.:.0.a.b.c.d.e.f.g.h.i.j.k.l.m.q ", "f J h ) 9.%.{ r ^ n.'._ z < [ _.:.0.i 3 o.p.q.r.8 s.t.u.v.w.x.q ", "f J h ) 9.%.{ r ^ n.'._ z < [ _.:.0.i 3 y.-.T 7 8 z.A.B.C.D.x.q ", "f J h E.9.%.{ r ^ n.'._ z < [ _.:.0.i F.y.-.T G.H.I.J.K.L.M.x.q ", "f J h E.9.%.{ r N.n.'._ z < [ _.:.0.i F.y.-.O.P.Q.R.0 S.T.U.V.q ", "f J h E.9.%.{ r N.n.'._ z W.[ _.:.0.i F.y.-.X.Y.Z.s.0 `.I +.+- ", "f J ++E.9.%.{ r N.n.'._ z W.[ _.:.0.@+F.y.-.#+$+%+s.0 `.I &+*+=+", "f J ++-+;+>+{ ,+N.n.'+_ )+!+~+{+]+^+/+(+_+:+<+[+%+s.0 `.}+|+1+2+", "f J ++3+4+5+6+7+8+n.9+_ 0+a+b+c+d+e+f+g+h+i+j+k+l+s.0 `.}+m+n+- ", "f J ++o+p+q+r+s+t+n.9+_ 0+a+u+v+w+0.@+x+y.-.y+z+H.A+0 B+C+D+E+q ", "f J ++F+9.~ G+H+I+J+9+_ K+L+[ M+N+O+@+x+y.-.P+Q+R+S+T+U+V+W+x.q ", "f J ++F+9.X+Y+Z+`+ @.@+@@@#@$@%@&@*@@+x+y.-.P+=@%+-@;@>@,@'@x.q ", "f J )@!@~@{@]@Z+^@/@(@_@:@W.<@[@}@|@@+1@2@3@4@5@6@7@8@9@}+'@x.q ", "f J ++0@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@9@}+'@x.q ", "f J ++x@y@z@A@B@C@D@E@_ F@G@k@H@I@J@K@p@L@M@N@O@P@Q@R@9@}+'@x.q ", "f J ++S@T@U@V@W@X@Y@Z@_ `@ #k@.#+#@###p@$#%#&#=@6@*#=#-#}+'@x.q ", "f J ++;#>#,#'#>#)#!#~#{#]#^#k@/#(#_#:#p@<#[#}#|#1#2#3#4#}+'@x.q ", "f J ++5#6#7#8#9#0#a#b#c#d#W.e#f#(#g#h#i#j#k#l#m#n#o#p#9@}+'@q#q ", "r#s#t#u#v#w#x#y#z#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#", " X#Y#Y#Z#`#`# $ $.$+$+$@$#$#$#$$$$$$$%$&$*$=$-$-$;$>$>$,$,$'$ "}; FaustWorks-0.4/Resources/fontBigger.png0000755000175000017500000000054612130743520016702 0ustar miramiraPNG  IHDR!yEH`PLTEqqqvvv***443zyv|||ZZZjjj>>=nnn^^^00/LLLgf`U pHYsHHFk> vpAg!źMIDAT(ϵ E$2(Mk\>vHtV!]'&<,4׼Έ fteXD7[ Tي e;&&NnRװl!,!r]7IzCD0ZUgf?<aOYIENDB`FaustWorks-0.4/Resources/fontSmaller.png0000755000175000017500000000054312130743520017077 0ustar miramiraPNG  IHDR!yEH`PLTEqqqvvv***443zyv|||ZZZjjj>>=nnn^^^00/LLLgf`ш pHYsHHFk> vpAg!źMIDAT(ϵ *]XkYqa}L`+[>? #zLƅVVWkB`MB|=yT*mN5);{~W9U!B{IG(=e B\.Raw3q(Xk1̲#zŖ ᦵe,IENDB`FaustWorks-0.4/Resources/i18n.qrc0000644000175000017500000000015712130743520015367 0ustar miramira translations/i18n_ru.qm FaustWorks-0.4/Resources/merge1.png0000755000175000017500000000361512130743520015774 0ustar miramiraPNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATx[lW̮wY%M"C^hTZ*T4@HRR%R6Ds"N۶3622۲cǎ/۷o([>nkkky3J_oh4")MaM&$TG>|[eaYJu˲p]l6iN:  y`@q8s̟zzzۨ`+"α{O]\-z{{ShP(eYTWWSUUeYa(XmضeYB!(H˲ʕ+[6WsAd>7 !)04MGKwfsx%ӆQ@6䝝mfݣ"yhRQ dH `Z`(gY+{x8wLUY Eڻsܜ < "ݍ`UC-Ky drՊ9񗙓yc7xi,,s…J"u1"2N)oŋ!MdIZ +;TSHdՊ?{οKG+B@ pi~VءhiiPJ77"2Z.<[)iظ`ſd5οˣm8,oڏp ^d߮.qse.T8@y3@M)y' ~W]N^E}Č(WJ)O)uI)pikwOW3劂ƜIZ"ZEQ.[udzDH5in: i Bb&eaYiBL$ 200$X\ĸi~M)a|{c] -GSRY_4M&1˲K4+VٟTjS,~ l:N.Rxl#}`d2i*.k}Wo?P(~%f ))ħu})dC&o>ix8PU'_tis__}G@4;bYox6b8B|WJ 2O>Uz_&'m%ӝL;i[Hĵx,;^u])e_JYooo8wq<!{v.)8 <\}Нn^XX=L$N4::W} Ëp|!x|f%mzXFFF\G^@U]uww_ V]]] xJRbLZZZpݑ' 5<!V1RJQ,\0_;+tZ:qD.:DBb1Q__/#dY:;;Km366橫rzzZ$ V2Ma:uK=NP Bu@kiv|^^+zUJ@qNbaN.r4N'J.F14ݲQ9 ֟ @3K) LW[Mt{q2c\.\B `-K+JB,DI>}Y,}XL| @ժPm@TP*T @ժPm@TP*Tʕ2uIENDB`FaustWorks-0.4/Resources/new.png0000755000175000017500000000152412130743520015402 0ustar miramiraPNG  IHDR szzgAMAOX2tEXtSoftwareAdobe ImageReadyqe<IDATX՗Na5{q\\0&bXX ѝRHECey{QJ!Iޜ3MN"SsՐn==d 12<S(CfIkR׾TUNK޷’=Oޣqnl4kZS YoK|mu5e<7ɺx&oFh?B~Ql% wIENDB`FaustWorks-0.4/Resources/open.png0000755000175000017500000000206412130743520015552 0ustar miramiraPNG  IHDRw=bKGDIDATxݕoUUmy^Z,jMihDF>908r&*Fc!,CЦmoo{k{rp(8M%+g眕ouւ>exQWXE ᖲF?GΜbcvF~]'۷ R(δliyi>@ +/ v (k'?能J'y(<ޮ zJ=u;FQԪZK<$׏;Jk0 QJqx ˗/("6w6cۺgs~֚A NpNb-la)E&!ʄ~@To3<܎r`qa=|~L&KRA) klD-Cj6H+(O!a`eeut~~llTƱR(h'Iaie=@! ?] jȥ1F¶֙&1hm0C[/f"@R)ݹˏEڄ1nڐ):BwzM;gBsADZg?"% i.񽅟rclt\.홋P JetΡT},9W`EkC5iR,qsb0={:.iZ#I 8qx:s{X0ڀRIu{/7r'.XK1(q\qwe[[5Ju'0Tn$FP$GUXk[4%tN@cFT ?3;;aEY*iv "_Bk1qXֵ*Y2IRnrjVq7[0 8'{zz|uASSx1*l$;M|,BP{ Vf.怇="zC-TN^u ouM{?zNt[]0ypwI"zMD-^/𣸋.$XTPSxQl&xQ$1QzSDp" 2'oջ9+l-JU SSSG).D֪ذ Q[d2@ 0UJ3 ѓӢOUڈy 63/n+H]C=#[(WFjU*~Q'aH8̿6044Ri^8;5-n]Vd znDoƾ}kp `3nKfRk, 6Wp,#[r*O|"9T VWW58g [{nLv/] ?A ϢSyO&K:i{;:x%d,'u)ve^w ښ`G;MfC___b0cFd2xbQJaVU5*VP@:v 022R3lnõ^`Z^ ر#;44k D[ZZsεD333޽;ӓnbD"!>}gMvwiG&lWӎ (~)Z`N4#0E"qD(XӞ=zTD0VzE4•BlsC0< <;-;5Ij2ʋ0`[@`I $9.[@cW@$AX,Z1-s[Ƨ-#Y%""S/Supp׻~R]"z: l8JDQPRyMb ED+M'nCfg否)y|q*68bj/)f#/Wڈp/޼Ise(]RLFC9_o\;4tg 9?֡z#o{@ 44@eP5 _6 `tMUEU5"ȸo^N!}MMM}peSUUd:ƒh"8bfCZo_Hg2ky'Ouf-wPU2\2ɖ_uì0(reYeHS%NP,V7/@(昍*x"[/PC[3Uefa[Fh4y7NؖuW;IENDB`FaustWorks-0.4/Resources/par2.png0000755000175000017500000000373712130743520015465 0ustar miramiraPNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<\IDATx}hU?ss=/1&i/lkU% RMNfu̱ cŖ1ցQd]7^ XGEY݌M1ƛܛ{srk^1=Khp<*gPjPjƊPjyI."&zeW۠>i`Fxbg;٬# [.Yv(| +لJp.w"89 u; q)L-W.`" ? Bpw{#š9gZVl +XDj,QCQHEd[ ^"m)G'"?QlNr',VBpwddX.g#"bO/R3ZU/,s1 pkFY5wMrFƾ8Ns$r[5Q^} Pc3D{u UOa uu~v&3I /Q[z{nT"9 qUE7iTh1WPjPj 8]me۶=&zLpPVQQQ2H$F¡2mtNR#22r}FU~  8̘%GG Yߒm gr51q; .0B\3AHθ3>>n1 QB^s/?PLL)e9=!Rc۷oxs\`۶mWܹSHuuukdd=i;;;ׇ᱖k׮$ 6B!# mvc6UUUyRiIRXE,0 $~H$B6%F' Bg\tH$B$Vz̺ʏcGTu-)$F >4; <"3k~2 l`B'xondzd ?Pաt{mڴiI0dúC|%SYY\`;hC1}l 7?ʛ^^*7>l5B3srISSӠ'BUՓ_{{% Ν;B XА'cb[lro*<3;JO#BOZ$CCCqLӤ0d2DQ\,ٳtvvBQai>plw(|fr& '4`9`Y^bŀR (5V (RcŀR (5> i*>չIENDB`FaustWorks-0.4/Resources/paste.png0000755000175000017500000000315512130743520015727 0ustar miramiraPNG  IHDR szz4IDATx^[lTsًic$BJ!"-b/Kh+U`UڴV U')ċRy9iӄcj;z޳ghrl'}~sJ)$xxkH)w(' ChRcdY@9&`]DDnΉ+WP]S@Pe(A)fi^/Nl;G|[CL;D2Ķ!!p>Sl;D*@P4`Hi$N8!҇g em(AXW%DBs\=AX\$}-ZܱcGYUU~ХKܮ֪DU,s1O(Ja Aرlr?+ M"fxGuuPKի(ZA-ڶ8XŒL{;76|/g2f>v&.A,٩:l!Y-BPDz8`Yx555 rȑbmt0f#6,2cy.Er<,A65fm8Xt SˍӲ}: /s$$IR躬3Νѣ>|^,Ok/&7|k.-dk{N^VsogwMܝvrugk?x<8%8#%A:߽Mծ(bBYlArfOfrad^g2ƅ퇡ʹ755 FqolH;L^Éy[Iy%c fܝ2 L'ط+%3{=ku*2J+Zpc(,R{}$eLM|`ƸP#Sxv}hL aXx!B-iC#jc! s߃ʣ2G(akK!%0*\@X*#plYD\ϓ=RPjYVL v_=gӺ2y_hίp%x LO3DŗY\N`S(%mR}[tjWo7SpSx3i %Ղ)3u3}r7oDT_p =?~Bv;su]pW@2 ~*ӽi9thӶ}%XXX'O>Iʭ*;nLRYt= АӓNΞ.)055U/"SN%/g~쮸 KvO&@@aZ`;ߊ$^saw3n`pt___̙3ťЏxc!DxOis*_IENDB`FaustWorks-0.4/Resources/rec1.png0000755000175000017500000000344312130743520015445 0ustar miramiraPNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATx[lWgzg]Rb#(KL(6RPHAPbԇTE E< H+ !Hp;*#6&d;;sx؍eVI9|9gfgJTT[@k@T~/ɅM>% 4M#<1@lm==Rʢt)%w?~.`[&x5/`%?6lYS<\1$Xtۨy t8\W"] z( }z  *5>)װc>E~)kv j7`YEq8bvy?=xY <` !uUޑR~UJzQn+oVAxkBkRwROUl.3v jc׀j 6vB pE[βmۙ +1盉 !E4CDáw۶adr aq_ RJ!'X[NvXg6 9r䟋㽽swy>k===:pwzbb)5vwwτB!&:=3`hhhpxxCCCضM}}=Bd2a$e: hiI$! N w^M4mMaz}Y]]ʵ+sss\r -h-.EQPUro }}}4[ zj[\e1==VóެN3c=`СuMdzzz:=3ó6?(awyɾ똡Py3TUG/p1q#4DDžeZ oihmmMnBN !4yFGG 'zC92L882Lo #K0̚vT۷o~4`N!+B9pTF3g6dA_ŕ8Q+6XuKbߺ$K!ĿJ).oV888!d'm5@u'oܸ= ( ş`m5 R^fΞ=S:p+!7`M'( ~)a!D7p5+)rI=/Fi{^"H[ rK6QUOJ)=9.J#yysG|,%Op vo?jxfU}xFڵkL<giih4̠( ht:M,H$B,#ގeYܼyN/tz<b0@=P㻝Jmϕ%J{6iR^#f/k@TT[@k@Tϼ)XͭIENDB`FaustWorks-0.4/Resources/rec2.png0000755000175000017500000000364712130743520015454 0ustar miramiraPNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<$IDATx[[lYzc;ƩEIYB6["U ZVE]H ,@`+b!}+"m&5M$cxƇ&!n]92)9Ͽ9sM1?ChVcۀV h5 hVcۀV h5$^p.޸qײ,%NӮT*ޞ흹uVXu5KQ3ʲ%S\ GpKӴۭG}sddD"JH$]בJ*:::JiBDQD"D @6E6E0D\ӧ_u HӮ@ @ PY9-Bd2X,pg@(o5k׮]\Nsv7Ξ=.bnV[ pFry)yqKGB桓[ ^~ͼqϸ?/Kx(|dšC>䡓[LMMy^3؎x#*dcfO-VXl6ࡓ[ܼy_/̻(a|-ʛ_*)_S(0>>C3 ?ԩSTmZB˜ű!S&)W,crr9"i 鏌W2ɀa40````B2DQuhV "gMvCQ\-/طzh\dk8y;Ǐ}1(rb]@ww녷1ރO=S30 䡓Uȑ#w{f_ݯC۠UKX{\ũWA1ػw s=؎xֽͽ4||ŋ!hR׫̀k׮}Q{҅;>.l6˗/GmՀ]\ t6Zo) RUCCCukJf+W~60ǷU`nn}rrbB>,caaD]בdxrdPTa&&&&;yf3g>;88xBU\4MLOOggg;ttth%Iwgvv3==Hdqbb\. }ׯ_=>>^w, ;66VszY1Or""G` \ "s~C$1ڄ FDd2ƪvi$1C(xd嶶b1CD]`{ XJ{1f+ У(J`'yAj3tvHSU{ !k!˲v8$̲~\%A`(cVoG1Xh7@$kDTvىc6+l_nYRjqЉH2|:/9/,?'[2o3\lbQVP4l0TYz.=VhU\pi5 `]Df 7]^Y.wwv3Ƙ٨? _cj~\[ c,ߨkcl]Qz¶jljL Hc̴,FDk<"p(pID= *cT*l0R%]7JDlDHTUňuݾ6CcTVJfA投t:PdYkgcQ5kζ(JmH$ic4e H(mU 0 @ib3+9DE1ST\ X!#\ 2^6ZmZ-$XkpIENDB`FaustWorks-0.4/Resources/remove.png0000755000175000017500000001225312130743520016107 0ustar miramiraPNG  IHDR szzbKGD pHYs  ~ zTXtRaw profile type 8bimx|I밮xK@q9i $e[9'ǍE`sai?!(kсʆ?秞̊4.n!^<}`)ՋOfCfIX3jZ1Tc %$LYFfJݍQG`X[0'*v-&lɩٗP )pcvb,C8 =݂C&-ژkz ĊE7(q%[`< <=}8OCx{3ɻ[tν9ri~ޑ ԋ7P.nN{CEzHZʇO'p[^39 p%t uVCXt{E:ܪ3I.?z.SBV=3oz3 w u`OL|%tUu u` !$a*("UX\UyvVIa5$6vޝ<zӡmz9W9s[2x Ģ(2/(L ,r +E7V;EpEocL!霏]ញ |fLj>"CU~H`o .~H! A$ؽfż>{$ZGUfVHt5:9DGo#h :zI]w uK/>=-Ro1 UJ^BB\wJc7;ˇ;E/FFJ>ɏ0MQ ](Eֽ >5M"$߯h]H c'x(h~: zn3Afw[ʟoԽtw.]$~YUCKB\|F$$a/(.٨":*bxB1/5;;P AE-ͼN>Pb;I !OCϐP`/yro3=}y3[KNe6 }XjfB~SӹSI|B߄}2^m`C5g_ ;~ ?m k" ug/s =3%÷K ڞ÷vdŮ/߽3žeݚp4_yƒpIwxpSx);茮n/zw.'G ulemK>CwG$x]Fչk`y~Ӟ;gOMg.GӧǭB=5|o``5ba]wGߺ5+7`jUXknitx=cjtAXBAK.:;{zzܒ?f X| %yy[wF={gcߜ=T<{].m]uNMO?Ko3t7mH/0}*Q]rYc;1H "RX2'"jUעk`{s b%WOg7Kșs"⼔!%EĎ .`\cVlDdرcBBBFBB  o|6l8p ĉ'IJs!z,DpYmĈČLB cl̮H ~dcʮضYUBDF9VŊ2EdTd4 t\PUPPДHF'-T2wr ^x [aII.!b/®ZUsPql6-ɢ]MIQ(ZuźZYa/^w>=]B#b5Z1#V `=*Đ`1ꪇ f4 z`d<(QyR…UL%D4 }X6PMU8n-zdF'BDLþ6B7jd_/gHq 1{=iبhlو6Tf#[vRU =d6ټWci8ϰax-,!;ZmQ4+VxSVۄ&z92RGK Y%3[S\S)u] Zк85ZZoTd֘t5#|I 歱dռDҗ1(2s,m|t﵆( K[z}4Zfb>3a>nXXQk%FXśva624p>6!ZZGr biu sQ2$KH4Z2sq2cK^Jk8ø \FA;kFfo!CHֺ T"'ڂkYF:pQ)tPaSg5yM9-4 n*WbLl)KbF>{jjyJk杌 疕溼}&x"#&<! /Y vpAg IDATXo\W̌=4;'!iPEVQZ <!JREUhSi|4XvgΝy׉cl$`KWGgYg_8;?{lt*3po/.-m;?=O=O77ē{vӳBٹynݞa.|@w_ϜO|'8=x** mZhos[lS\x ~}{ZooE玎?{ϟJG-}"'XcДEZͧX\\.gD3jfF?{CǸ>}|kRXjAT"jDk!;vd{O0'克M+?#䕗_yL\& 6e1)p"U C:::ww[_ 8udyȑDqs.q8DPTꕩR~zоO}؋{YcAT 9ȁ(2`BhxԪuj*^ë֩k:ڷ{Fƾ3~?{f(rb 5ALb".$ B~h!c-44HVtvuӿ{K 'ٔ@gwѾ~ +D"X "#q∂( }FQ@0m,BY 'UAH[GG@k6?IPʼn"(h3"7!Ўh֬ y0.Y,7`Dii͒ni=%M{ fo=wljkkbTA- *npKͦO RXT:7ӲPq1&:7q~"j"qB`z{"!T]mX,!ϫז$PVoGڻv\HaA3-Nŋ%&S`5XT%Š54<6W+_^Y-P*9PAEGQ*5gI[aTYh6- T/_FP)QUATqHbJ(ĕ"NAN'MJpQ\SW.1'lx[{hv6\xn(<ԘVl8 c_`ڇoݻu[fPou$q;3WKjPkPkQ,j@Db"&>x𪯳a/ k+m{]#=clm%NX I6Gp. |t,ř.\FoD&{h:&cb0JX8@@as޺f%zTXtSoftwarexsLOJU///P03D'u9k&zTXtTimestampx32002024S02221%3IENDB`FaustWorks-0.4/Resources/removeFaust.png0000755000175000017500000000661112130743520017113 0ustar miramiraPNG  IHDRBBTbKGD pHYsHHFk> vpAgBB ; IDATx}pT?Ky#utXiA2(|-3WO80u  ">Qk^"B H! /B6n{7Ɇ@ l~g3gszv Df 0Lho)np~~wwk음%V^-DO` bڵj}AD_`5^o?mGӈ+WǨ.]k &1"-[vgEwi;vw}|YXX(UUV*ǎ6m"ʢ+Vkɴo->3gmG(  9={D< Xj4N:Ř1cv 1tމsΜ9ߩ"//eTW/H(YxO,W^-~mYZZnY{g!sV \&ƍ@ v>WU47>/;$T ygc777Dp8\.fE-5L6MƴiDSS\n,Y!C,,&-_ˉ̞-WVZ%/^,GD"UvNye3fM=o︶bLyAoǹn]> af! A;e͓i& &L4lg3 =#uq/' !A }|rrG]K#ƍUpfL**wg,..GVVVǑRbT[t:+ 3Ki.)%ے Ə e8\6˗ 1cvV`Ш>SaD(dXKdfy>ienzL##˾x!N=cBյͽkV+e{ߋ۽mF{0⭿PxyS Ǝ,֬xu5u/D\}VjSi)/|!bJR\dem֎C( @HIt ^B7uU'JLhԐB|?AQ0;.٥˅gh> r6HIME 9>ťK_ϑg9)%90PNT@h6(._op4q}]^/jA'^NJaڵ=FAgI8VD(_> yEGkk ϔx mnĈ>|x`!$-Z:lfQJ|>ʌŪ4;}hpJ)d,) /x(FĂ ),ŋ1 00|8RAב$0IiYfCLx^'tv&9^Q0nd1}0{ \.Du,@t+lh--\YkW68!Gu}d!;~<pAAQb юޣ&Ix0) @MMξ%!F(HEA4A"֎B S Ǝeǔ)jD(l$m܈-%t6t@Ch jD @ϟ1~ (? ՊpF`b8D) I9b/AMUEhRӨ!sklقEnGZ HUELHRQVFQѣ X2^בPUd 32i['T&_J8v;0p8D\p * gNUԶ6N׋dhm>t˅t8p]NӼy=1vv-t-YG֯_'t{RvyyrUXIQ6jh[,Ha"].%%a5iCjQtO"D(DC޽qHOhzit,b1|YFJ Vh !3ƴ4r**0:f)S9}:pB<|"&bb;p{<9}EQVAFGN@U).&tLIᩫWOF|!}>9z0dii#lλ͆5"2kVL]FyٌZK&D}àAq/i?{Т1cvrQa87w.ۍhm!=JӉLM;1ͳQ"-]*Jh-avF$GB"NVV` DsxM_|'d6àA$D}BcK Wk$@:TE1H^N'rH~UUauj'L࿾> Č&:VEE\ٿ @FF XT;GO #BAsK U.Юy\h\z{**f*OgΙ3}r,ho't0{dV8 ;x5l'5=EJZ}>2PGW[KӧBu5ƅGVt{N4"%G۹ KBH Gvvb7L@k4\ohy~+H'g.I0*%%\۾k4"S]F$W-AّN^/#M"Q1y2BQkj5 4 EQ8zKT#f3DkFe?/Q${O8!*}ɄjEs8< Vf|%vMfT~sh˙'[6lH =$8%tEXtcreate-date2008-12-05T15:23:37+01:00f%tEXtmodify-date2008-12-05T15:23:38+01:009` IENDB`FaustWorks-0.4/Resources/resize.png0000755000175000017500000000605312130743520016114 0ustar miramiraPNG  IHDR?vgAMA a oFFs) pHYsttk$ vpAg66N _IDATHMi|Z+!1%愲i41PC HQ5=iU7%*hBL%nvIiU rvS"$ks>\ֿ9Q'0`}@tu))1_A xp2BF([򖴒wa>,2OBI!RnfiN2Uf9hyLɐ ӆksm.+Ғ<v{ \ QQ_dVa "B Csl:@Ze'uLPfaVQw"r .ޕt6m͸lc3r+oT|Aik걚I=h}0C* 7clSM"!kj@%d<<}.|KP꣎j+^y VA*6+8- 1$[c7=P e.2G+NXZg]kUF۵)عSunUXTfKS}+ Ws+A :N=J kJQkvݢklb1ZfouUAh I~4M!q]1ܸdLTcz& B/ǗXZSLGJW u)D@{i/*( 3Lm7wZy+U;?j&sVV[+]ThL!TKLO_Wx||؎#Bpum(%&᪝j*RMY~EGb\:<t4&kU@dUmx8Of.~+ N>nXj ,B0Gm4o*RY掜9/]']d /h)C4`ʑ4PAtHI{a =c:.BexpË  Waџ%bIaG,kG ❒ >#L F%Z2ࡑ[T|xV"%WrLP0-@ '*,rSdnsߗN29<5CPSCy9)G娄 ˦ j&@1 e9lfIpHe's>mKrzn:}eSKgN  gcV-R8. wD9釺iajK,sμɑ| /6V`b5l5A&M3dOchPM'׆JQjS%\P!9Kxٙo?݉X$>cV C!1+-a6DCquS5ZL{)HmTNc) )a NQU"S7YFO6d>KHNv>pԵK=ئZM}X@+vHr)7@$JY!S\"Fz zw>f sXǛDScLyİD;sbye9!uyFET[fM 2 WsW Nމzܙ;MY)+HL@[c5<;4-W/xj>Ss_*.Ԛ(LU j9uLWk법l>o)[}iOJ-)Xb.7jDߢ&")Qhѭ4Jm;>]vN5ػ」;v<:̗7XSڠkg|p?0x.ory #ӟd}k@E@xp,#˲m00aP|#%"+Օs΃* ,I Iw:琷Ղv+m(r8 㯼IkFؽ{k놮ZVmQg5 ,# /#&|#!Я'aa%% 4M:ólc V_)Fara-р: TIO4/!g iXvj#wPE x:Tx3x$wh6h߱R^DM_ 8ňKvRPZ0}@Ű&WU.2p}Ʉ-Jsf+7QW?תd~')Ü wl 55Y1{X0+WVU!ѐS,-޸Wj'WڣU<_o|w__sl}5ځ?MKFIENDB`FaustWorks-0.4/Resources/saveAll.png0000755000175000017500000000231012130743520016172 0ustar miramiraPNG  IHDR szzbKGD pHYsHHFk> vpAg IDATXýke?cf6k4[D+6`ܼŃ"(GDPx 6$TcL)Z4+tC3zxggg'm4 ;;}}gF8v133#;ㆅ+,^KN=0>l{Y&ƨf`:1nJP&^XKf$'=]bqF-7yx Mx7 -7yx Mx7<x ""b@3Be0/ci |>_hݡ`0h|%Yt:S###NNtttT@KK˝[nmqFi8aͮ:s xeR'''oP:444xJ8pEƘkHVU4.яbd99 ܊ZȒOu}]^CTj-KY`@zF5xbG`>uŐ$ɞ),Y V^^`IIIE"p:PlOjL0,ZM&J hxz7Sð z=wǎ>'/4A A`20  )wC~}@hu7ˎ*X4׌Kcs+ #"+3@mM` ÚGf2 @.^s=Hsa_O{ڪNj*eYр,g% lllT7-Tq4;=R 8#CcC544h[ c,z'Zj_Xa$_s2kSg@g1?[I`E˜<9 WFg@tj@eڇ9!Dz#4n(zLh,c'C8}*Sq:x >NMeMMMQG !B"]1 `0(,k?ǟ!cT~ mm/lzkت}6JфgΜ2nݺܳgO3;229rI2t_r%ёݻwozll޽{`0h7a=wѱmELk-xɓ@Y ӧQ8p@UGc[Qu\X y4;U5J."]륥`4V}/;3H|˲T1@UπI| ŋK @[im[kKX"qj.g$`HO@&pJDR'OLD"*kwK.,əC۶(+=~\|s8*DoLcW#//{ݻ(.ª)o<@ggg,}I\X0-c@t|No;|yر~i DzBG+>Pg:T,,D0==]ʏ6kr}.ۍEQX "!屏mxE¥Kq 7g1ܲy---ʫY 5_U5 .qOFƿwylDchJEP`٘!\8N0[-$=\~-";v̭ ?3dN˗x- Š{bb`%F L楜iv8/_ܻ"HԸHZBLӤY omk{cWdՕ nT5zܹwxMtww) :QzՑJ 1,,b,[&Ujy|||| h/U|bYvG"7"dDR\βmmpUz{{㫪|fLM̈́6y{` q=ds9B:=SMb1)r၁C܅ vG">ko;nÇߛ޸qcKWWWlgϞ츯LBMalq ^ ض\XV4d2Z:"_Xx\רU "*f=\<9UvQ FjPŀѯZ|5rN pN pN pN pN pN pN pN pN p˚B [IENDB`FaustWorks-0.4/Resources/split1.png0000755000175000017500000000354112130743520016026 0ustar miramiraPNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATx[lW\x&Mm"*EE< 5} RKQ%!UR[[)-A MRvԮj;Iq;׻띝îq_O9s.?gmD)Ž))))))) 0TDDY*'ODLB80 ʁ0YHlZ!=XX!cp`¥<=`޽?88<]pСꕊƍMdw+kv4Jnxݳg@ P`ﭦmurEP3`r=*)fA\,L%EAMXkz dv;~xsE_"y8c"GCu])%H$~dk4xr?_UU\҆ۢїM,""膁azB73/>@ kLvKq<ٽh۷B&"hS^r\.p-mcw2OU >.fGxs<}p=qjAu sNQ@RBOOd2꺮'K҂ LQ#f4 "|MD.J/(),&R/-N4?GSrCgmmmG _TJ]ZLR凰:<=`jj*Ӑ rV* ׸p8䗞]p\hSfioNQ4=N:UM~ GDΊ/DH|}ѬӚ{܏.O^~U.o̼ųWg}<tuuXU R8~ l:4MD˲Lu]l0 4M#ˡ""ˡ:c6255Y`xE#mYɸ"=ܵk8jmm eZpvǎCCCCCCՍÉDbĉuL&~~||<ۻ%H\mll?șcǎZ###cGuh4 "!0e*eYLT꺥T0 s*|7Q8 73 & Vr6ZTj2c鉻с5k"ik`pE(˲˲3333@cqc7`;g^9Z2o~S2o~S2o~S2o~S2o~S2o~S2o~S2o~S2o~_$5TԭIENDB`FaustWorks-0.4/Resources/split2.png0000755000175000017500000000350412130743520016026 0ustar miramiraPNG  IHDR@@iqsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATxmh[Ϲ˲,#$ֵI>l,]ꎱAal!0XG׬et 0j!IhJ4v8s-= [%Įk~B`?_{sDk̓rZT pZT pZT pZT pZT pZT pZT pZ<)gGzV^.Q!]^"nK!C<0R4SZ/ԇ>e6R_h$d k1'NDfggexxhmm7nx\ٓN&oB!ٞPXLܹ3v+W`0}>޿7,_q }J[*"@Ziԗ~x<Y2iii:::rݻwc?#G$x;Yu^Xfv뛲#GK˶mn rɠRޭ/U[fSHŦ./2 0eyWDȵ ..XYjiYL~igGbhth*'co0p:ng2b۶M cnqԫ:[Eq%q 70C/ln"y(\<i/N@Q. 08nceLs@)""3"r|酌P(P'Ϗw^*z^*ϏwT}HR /e9:[kψvM~<*"?.LPoR˳ze~1`NPkTR˳ԛJN5#; Xy띝ED̿V,6FUɾ8dG^ ;pX\AQOLLL4/6Zn0~ɷrYVkz\ d+F9&ζgΜ KG-0E4e_j Je 9,,,`6e!"R)RXE:&`&J)rdHaLMMAȀ7FG'BGƕj?z} K5d*%wx|:u4 J@ ۣG~}jj*1X]]<{Wk EH$2wܹ]`]k$F?t֥GpEѥRjL  CuLɻwSx|j!$HĀf*UE\UUU>˲.6۽*T*IRyk o4 XP|/.V|gAb/6N pN pN pN pN pN pN pN pN p6b IIENDB`FaustWorks-0.4/Resources/vAlign.png0000755000175000017500000000142512130743520016031 0ustar miramiraPNG  IHDROc#"bKGD X pHYs B(x vpAg\ƭrIDATHǽJ@'ҤH<R )/ՓѣzTzhHZLf7YWmAe~~Վ94Fy|>oo  =B!于8SN4M4K%4M4a>jZyuu]q2m۶mGT\:f}+8yeYd|qQǔhE1$I$Sd2$(ry-c 1!b1!I) B!8f f3!1F)~NzEls\N&E"f4M 4-@*~ <c)3@8O@p}}q8ښ+J "7G`⃃˳fT}]5~(_G@x<!Ւ  uٕLfz)/F`Q Bs;?y|cB(}~^uwwK%1ĬׅtE#G@";> 0 e n`LgE}1_yyP( Wjy? $,8"zTXtSoftwarex+//.NN,H/J6XS\IENDB`FaustWorks-0.4/Resources/zoomIn.png0000755000175000017500000000211312130743520016057 0ustar miramiraPNG  IHDRw=gAMA abKGD pHYs  ~tIME 'IDATxڵKg߷:nU+C/Z zp(e#Q=^R07B=VОDҚ JRHXZugfg^ܩmb?xxx{|ud*ˍX;Ӡ8V*++3'胷o>RJ,u]r,..8r]]ӵ_57u||Bajjj(--Eضi|ϟDჃk lǏljD"TUUǩ& ô`|Ƚ{~<===P(uibbp8L4p8L0$D"B-S ֖r]gllr(xMR ۶q۶޽köm`~~qPJa&mS(E)uxm<[YZZ4M eQ(|u]\mibeaYr-@Jd2dY c/E@>Ų, `ggM"iڷ=hM>!Wlmm-7MoRʭ>~(e_|>333:@UẮ&Xܔ>??g{{i^~yKubBgRʞEcc#z/_,Og=?$/@2DeCO#m@^6$n>'t0/˖˧7MMM)] 8KH1+3NۉD¾kU1 !/Ԏ^7IENDB`FaustWorks-0.4/Resources/zoomOut.png0000755000175000017500000000206212130743520016263 0ustar miramiraPNG  IHDRw=gAMA abKGD pHYs  ~tIME ԸIDATxڵKcWF4( n'nKuYd.fj0.J+hWҎA4~L!׍y8 s8>!Ng ˜i8mJ)#`ѣG`||[) OU$ ($ D"".766ZZZ~<`YxH$B,H$B("BDQ0?fwwW}i$@WWWu݁ jkkb$ @)%RJ"$N6LE@Pd2455C!grE:F4> h!y'eM!Rm*T[kk+P><< |.BPJ<v@)m8m۟eOa{ss3m#`zzگu98R 0m˲A)uT-aea&ezY60uݷRE2NTBO4MJ/i:*eY 588X˲mϢ +zy`ISJ7粻o^9~yJWWWye߹*\ !wvv>| [[[],׬8@ ~o]'⭔r^R,..0_\_' |ڍ!:zR-@|Q6$>lс˖|ȧ7 \MMM)M (>$fd2i?4&Pr XcIENDB`FaustWorks-0.4/CPPHighlighter.cpp0000755000175000017500000001057712130743520015446 0ustar miramira/* * CPPHighlighter.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include "CPPHighlighter.h" //! [0] CPPHighlighter::CPPHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { HighlightingRule rule; keywordFormat.setForeground(Qt::darkBlue); keywordFormat.setFontWeight(QFont::Bold); QStringList keywordPatterns; keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b" << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b" << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b" << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b" << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b" << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b" << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b" << "\\bvoid\\b" << "\\bvolatile\\b"; foreach (QString pattern, keywordPatterns) { rule.pattern = QRegExp(pattern); rule.format = keywordFormat; highlightingRules.append(rule); //! [0] //! [1] } //! [1] //! [2] classFormat.setFontWeight(QFont::Bold); classFormat.setForeground(Qt::darkMagenta); rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); rule.format = classFormat; highlightingRules.append(rule); //! [2] //! [3] singleLineCommentFormat.setForeground(Qt::darkGreen); rule.pattern = QRegExp("//[^\n]*"); rule.format = singleLineCommentFormat; highlightingRules.append(rule); multiLineCommentFormat.setForeground(Qt::darkGreen); //! [3] //! [4] quotationFormat.setForeground(Qt::darkRed); rule.pattern = QRegExp("\".*\""); rule.format = quotationFormat; highlightingRules.append(rule); //! [4] //! [5] functionFormat.setFontItalic(true); functionFormat.setForeground(Qt::blue); rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); rule.format = functionFormat; highlightingRules.append(rule); //! [5] //------ preprocessor define //! [2] classFormat.setFontWeight(QFont::Bold); classFormat.setForeground( QColor(186, 118, 63) ); rule.pattern = QRegExp("^\\s*#.*"); rule.format = classFormat; highlightingRules.append(rule); //! [2] //! [6] commentStartExpression = QRegExp("/\\*"); commentEndExpression = QRegExp("\\*/"); } //! [6] //! [7] void CPPHighlighter::highlightBlock(const QString &text) { foreach (HighlightingRule rule, highlightingRules) { QRegExp expression(rule.pattern); int index = text.indexOf(expression); while (index >= 0) { int length = expression.matchedLength(); setFormat(index, length, rule.format); index = text.indexOf(expression, index + length); } } //! [7] //! [8] setCurrentBlockState(0); //! [8] //! [9] int startIndex = 0; if (previousBlockState() != 1) startIndex = text.indexOf(commentStartExpression); //! [9] //! [10] while (startIndex >= 0) { //! [10] //! [11] int endIndex = text.indexOf(commentEndExpression, startIndex); int commentLength; if (endIndex == -1) { setCurrentBlockState(1); commentLength = text.length() - startIndex; } else { commentLength = endIndex - startIndex + commentEndExpression.matchedLength(); } setFormat(startIndex, commentLength, multiLineCommentFormat); startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); } } //! [11] FaustWorks-0.4/CPPHighlighter.h0000755000175000017500000000313512130743520015103 0ustar miramira/* * CPPHighlighter.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef CPP_HIGHLIGHTER_H #define CPP_HIGHLIGHTER_H #include #include #include QT_BEGIN_NAMESPACE class QTextDocument; QT_END_NAMESPACE //! [0] class CPPHighlighter : public QSyntaxHighlighter { Q_OBJECT public: CPPHighlighter(QTextDocument *parent = 0); protected: void highlightBlock(const QString &text); private: struct HighlightingRule { QRegExp pattern; QTextCharFormat format; }; QVector highlightingRules; QRegExp commentStartExpression; QRegExp commentEndExpression; QTextCharFormat keywordFormat; QTextCharFormat classFormat; QTextCharFormat singleLineCommentFormat; QTextCharFormat multiLineCommentFormat; QTextCharFormat quotationFormat; QTextCharFormat functionFormat; }; //! [0] #endif //CPP_HIGHLIGHTER_H FaustWorks-0.4/FaustHighlighter.cpp0000755000175000017500000001375012130743520016102 0ustar miramira/* * FaustHighlighter.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "FaustHighlighter.h" //#include only on unix #include using namespace std; #define WHITE Qt::white #define TRANSPARENT Qt::transparent #define VIOLET QColor(72,66,139) #define LIGHT_YELLOW QColor(250,250,210) #define LIGHT_GREEN QColor(240,255,240) #define FLORAL_GREEN QColor(255,250,240) #define DARK_OLIVE_GREEN QColor(85,107,47) #define DODGER_BLUE_4 QColor(16,78,139) #define INDIAN_RED_1 QColor(255,106,106) #define INDIAN_RED_2 QColor(190,84,83) #define DARK_SEA_GREEN_1 QColor(193,255,193) #define DARK_SEA_BLUE_1 QColor(193,193,255) #define LAVENDER_BLUSH QColor(255,240,245) #define GREEN_4 QColor(0,139,0) #define ORANGE_1 QColor(240,110,36) #define ORANGE_2 QColor(209,110,36) #define DEEP_BLUE QColor(31,68,110) #define DEEP_TURQUOISE QColor(31,109,110) #define DEEP_PURPLE QColor( 70 , 0 , 83 ) /* #define SQUARE_BRACKETS_FONT DEEP_PURPLE #define SQUARE_BRACKETS_BACK TRANSPARENT #define SQUARE_BRACKETS_WEIGHT QFont::Black #define CURLY_BRACKETS_FONT DEEP_PURPLE #define CURLY_BRACKETS_BACK TRANSPARENT #define CURLY_BRACKETS_WEIGHT QFont::Black #define NOTE_NAMES_FONT DEEP_BLUE #define NOTE_NAMES_BACK TRANSPARENT #define NOTE_NAMES_WEIGHT QFont::Bold #define ACCIDENTALS_FONT DEEP_BLUE #define ACCIDENTALS_BACK TRANSPARENT #define ACCIDENTALS_WEIGHT QFont::Bold #define DURATIONS_FONT INDIAN_RED_2 #define DURATIONS_BACK TRANSPARENT #define DURATIONS_WEIGHT QFont::Bold #define TAGS_FONT ORANGE_2 #define TAGS_BACK TRANSPARENT #define TAGS_WEIGHT QFont::Bold #define FULL_TAGS_FONT Qt::black #define FULL_TAGS_BACK TRANSPARENT #define FULL_TAGS_WEIGHT QFont::Bold */ #define COMMENTS_FONT GREEN_4 #define COMMENTS_BACK TRANSPARENT #define COMMENTS_WEIGHT QFont::Normal #define MDOC_FONT Qt::blue #define MDOC_BACK TRANSPARENT #define MDOC_WEIGHT QFont::Normal #define QUOTED_STRING_FONT Qt::red #define QUOTED_STRING_BACK TRANSPARENT #define QUOTED_STRING_WEIGHT QFont::Normal #define NUMBER_FONT Qt::blue #define NUMBER_BACK TRANSPARENT #define NUMBER_WEIGHT QFont::Normal #define FAUST_COMBINATOR_FONT Qt::red #define FAUST_COMBINATOR_BACK TRANSPARENT #define FAUST_COMBINATOR_WEIGHT QFont::Bold #define OPERATORS1_FONT ORANGE_2 #define OPERATORS1_BACK TRANSPARENT #define OPERATORS1_WEIGHT QFont::Bold #define OPERATORS2_FONT DEEP_BLUE #define OPERATORS2_BACK TRANSPARENT #define OPERATORS2_WEIGHT QFont::Bold #define VARIABLES_FONT Qt::black #define VARIABLES_BACK TRANSPARENT #define VARIABLES_WEIGHT QFont::Normal #define OPERATORS1 "\\b(component|library|environment|mem|prefix|int|float|rdtable|rwtable|select2|select3|ffunction|fconstant|fvariable|button|checkbox|vslider|hslider|nentry|vbargraph|hbargraph|attach|acos|asin|atan|atan2|cos|sin|tan|exp|log|log10|pow|sqrt|abs|min|max|fmod|remainder|floor|ceil|rint)\\b" #define OPERATORS2 "\\b(process|with|case|seq|par|sum|prod|import|vgroup|hgroup|tgroup|declare)\\b" #define FAUST_COMBINATORS "(<:|:>|,|~|:)" //------------------------------------------------------------------------- FaustHighlighter::FaustHighlighter(QTextDocument *parent) :MusicNotationHighlighter(parent) { /* // SPECIAL CHARS QStringList squareBracketPattern; squareBracketPattern << "\\[" << "\\]" ; appendLineRule(squareBracketPattern, buildTextCharFormat( SQUARE_BRACKETS_FONT,SQUARE_BRACKETS_BACK,SQUARE_BRACKETS_WEIGHT ),false); QStringList curlyBracketPattern; curlyBracketPattern << "\\{" << "\\}" ; appendLineRule(curlyBracketPattern, buildTextCharFormat( CURLY_BRACKETS_FONT,CURLY_BRACKETS_BACK,CURLY_BRACKETS_WEIGHT ),false); */ //Variables { QStringList pattern; pattern << "\\b([a-z]|[A-Z])(\\w*)\\b" ; appendLineRule(pattern, buildTextCharFormat( VARIABLES_FONT, VARIABLES_BACK , VARIABLES_WEIGHT ),false); } //Numbers appendLineRule(QStringList() << "\\b((\\d*\\.?\\d+)|(\\d+\\.?\\d*))\\b", buildTextCharFormat( NUMBER_FONT, NUMBER_BACK , NUMBER_WEIGHT ),false); appendLineRule(QStringList() << FAUST_COMBINATORS, buildTextCharFormat( FAUST_COMBINATOR_FONT, FAUST_COMBINATOR_BACK , FAUST_COMBINATOR_WEIGHT ),false); // TAGS //the tag itself { QStringList pattern; pattern << OPERATORS1 ; appendLineRule(pattern, buildTextCharFormat( OPERATORS1_FONT,OPERATORS1_BACK,OPERATORS1_WEIGHT ),false); } { QStringList pattern; pattern << OPERATORS2 ; appendLineRule(pattern, buildTextCharFormat( OPERATORS2_FONT,OPERATORS2_BACK,OPERATORS2_WEIGHT ),false); } { QStringList pattern; pattern << "(\".*\")"; appendLineRule(pattern, buildTextCharFormat( QUOTED_STRING_FONT,QUOTED_STRING_BACK,QUOTED_STRING_WEIGHT ),true); } QStringList commentsPatterns; commentsPatterns <<"//.*"; appendLineRule(commentsPatterns, buildTextCharFormat( COMMENTS_FONT,COMMENTS_BACK,COMMENTS_WEIGHT ),false); QString startCommentsPatterns("/\\*"); QString endCommentsPatterns("\\*/"); appendMultilineRule(startCommentsPatterns,endCommentsPatterns, buildTextCharFormat( COMMENTS_FONT,COMMENTS_BACK,COMMENTS_WEIGHT ),true); QString startMDocPatterns(""); QString endMDocPatterns(""); appendMultilineRule(startMDocPatterns,endMDocPatterns, buildTextCharFormat( MDOC_FONT,MDOC_BACK,MDOC_WEIGHT ),true); } FaustWorks-0.4/FaustHighlighter.h0000755000175000017500000000215312130743520015542 0ustar miramira/* * FaustHighlighter.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef FaustHighlighter_H_ #define FaustHighlighter_H_ #include #include #include #include #include "MusicNotationHighlighter.h" class FaustHighlighter:public MusicNotationHighlighter { public: FaustHighlighter(QTextDocument *parent = 0); }; #endif /*FaustHighlighter_H_*/ FaustWorks-0.4/FaustMainWindow.cpp0000755000175000017500000006350212130743520015720 0ustar miramira/* * FaustMainWindow.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "FaustMainWindow.h" #include #include #include #include #include #include #include #include #include #include #include "QFaustItemFactory.h" #include "QFaustItem.h" #include "MainWindowObjects.h" #include "QFaustPreferences.h" #include "QItemResizer.h" #include "QPaletteItem.h" #include "FaustHighlighter.h" #include "CPPHighlighter.h" #define RSC_DIR QString(":/") #if defined WIN32 #define DEFAULT_FAUST_PATH "faust.exe" #define DIR_SEP "\\" #define FONT_FAMILY "Monospace" #elif defined __APPLE__ #define DEFAULT_FAUST_PATH "faust" #define DIR_SEP "/" #define FONT_FAMILY "Courier" #elif defined linux #define DEFAULT_FAUST_PATH "faust" #define DIR_SEP "/" #define FONT_FAMILY "Monospace" #endif #define CURRENT_TARGET_ARCHITECTURE_SETTING "CurrentTargetArchitecture" #define CURRENT_BUILD_OPTION_SETTING "CurrentBuildOption" #define COMPANY_NAME "GRAME" #define APP_NAME "FaustWorks" #define PALETTE_ID 1 #define TAB_SPACE 4 /** * The different ways to combine two faust expressions. Basically the block diagram algebra * in two flavors : normal arguments and reversed arguments */ enum { COMBINATION_SEQ1=1, COMBINATION_SEQ2, COMBINATION_PAR1, COMBINATION_PAR2, COMBINATION_SPLIT1, COMBINATION_SPLIT2, COMBINATION_MERGE1, COMBINATION_MERGE2, COMBINATION_REC1, COMBINATION_REC2 }; //----------------------------------------------------------------------- FaustMainWindow::FaustMainWindow() : GraphicsSceneMainWindow( new LanguageGraphicsView() , new QFaustItemFactory() ) { setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); mCPPTextEdit = new QTextEdit("" , this); mCPPTextEdit->setAcceptRichText( false ); mCPPTextEdit->setReadOnly( true ); mCPPTextEdit->setLineWrapMode(QTextEdit::NoWrap); mCPPTextEdit->setFontFamily( FONT_FAMILY ); mCPPTextEditDock = new QDockWidget(tr("C++ code") , this); mCPPTextEditDock->setWidget( mCPPTextEdit ); mCPPTextEditDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable ); mCPPTextEditDock->setObjectName("CPPTextEditDock"); addDockWidget( Qt::RightDockWidgetArea , mCPPTextEditDock ); // Error Window as a dock if (!gErrorWindow) { gErrorWindow = new QTextEdit("", this); //gErrorWindow->setWindowFlags(Qt::WindowStaysOnTopHint|Qt::Tool ); gErrorWindow->setFontPointSize(9); gErrorWindow->setTextInteractionFlags(Qt::NoTextInteraction); gErrorWindow->ensureCursorVisible(); gErrorWindow->hide(); //gErrorWindow->setWindowTitle("Invalid Faust Code"); mErrorDock = new QDockWidget(tr("Error Messages") , this); mErrorDock->setWidget( gErrorWindow ); mErrorDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable ); mErrorDock->setObjectName("ErrorDockObject"); addDockWidget( Qt::RightDockWidgetArea , mErrorDock ); } //------------- init(); new FaustHighlighter( mLanguageTextEdit->document() ); // note : we need it, but we don't have to store the highlighter mLanguageTextEdit->selectAll(); mLanguageTextEdit->setFontFamily( FONT_FAMILY ); new CPPHighlighter( mCPPTextEdit->document() ); // Create a QPaletteItem for FaustItems (id=FAUST_ITEM_PALETTE), radius 100, no parent (=independant). QPaletteItem * paletteItem = new QPaletteItem( FAUST_ITEM_PALETTE , 150 , 0 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "seq2.png" ) , COMBINATION_SEQ2 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "rec2.png" ) , COMBINATION_REC2 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "par1.png" ) , COMBINATION_PAR1 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "merge1.png" ) , COMBINATION_MERGE1 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "split1.png" ) , COMBINATION_SPLIT1 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "seq1.png" ) , COMBINATION_SEQ1 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "rec1.png" ) , COMBINATION_REC1 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "par2.png" ) , COMBINATION_PAR2 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "merge2.png" ) , COMBINATION_MERGE2 ); paletteItem->addInteraction( buildPixmapItem(RSC_DIR + "split2.png" ) , COMBINATION_SPLIT2 ); mGraphicsScene->addItem( paletteItem ); QPaletteManager::instance()->setActivationDelay(200); connect( QPaletteManager::instance() , SIGNAL(interactionActivated(QGraphicsItem*,QGraphicsItem*,int,int,int)) , this , SLOT( combineItems(QGraphicsItem*,QGraphicsItem*,int,int,int) ) ); paletteItem->setBrush( QBrush( QColor(FAUST_ITEM_BASE_RGB , 50) ) ); paletteItem->setPen( QPen( QColor(FAUST_ITEM_BASE_RGB , 250) ) ); //Palette's positioning policy paletteItem->setPositioningPolicy(QPaletteItem::CENTER_POLICY); } //#define NO_OPTIONS "No options" #define NO_OPTIONS "Scalar" //----------------------------------------------------------------------- void FaustMainWindow::reinitSettings() { GraphicsSceneMainWindow::reinitSettings(); reinitPreferencesSettings(); QSettings settings("grame.fr", "FaustWorks"); settings.setValue( CURRENT_TARGET_ARCHITECTURE_SETTING , "" ); settings.setValue( CURRENT_BUILD_OPTION_SETTING , NO_OPTIONS ); } //------------------------------------------------------------------------- void FaustMainWindow::reinitPreferencesSettings() { QSettings settings("grame.fr", "FaustWorks"); // ----- Faust Path settings.setValue( FAUST_PATH_SETTING , DEFAULT_FAUST_PATH ); // ----- Target configurations settings.remove( TARGETS_SETTING ); settings.beginGroup(TARGETS_SETTING); // ----- Fill the configuration with existing script files in the scripts folder #if defined linux settings.setValue( "jack-gtk", QString("faust2jack") + " $DSP $OPTIONS" ); settings.setValue( "alsa-gtk", QString("faust2alsa") + " $DSP $OPTIONS" ); settings.setValue( "jack-qt", QString("faust2jaqt") + " $DSP $OPTIONS" ); settings.setValue( "alsa-qt", QString("faust2alqt") + " $DSP $OPTIONS" ); settings.setValue( "csound", QString("faust2csound") + " $DSP $OPTIONS" ); settings.setValue( "puredata", QString("faust2puredata") + " $DSP $OPTIONS" ); settings.setValue( "supercollider", QString("faust2supercollider") + " $DSP $OPTIONS" ); settings.setValue( "ladspa", QString("faust2ladspa") + " $DSP $OPTIONS" ); settings.setValue( "dssi", QString("faust2dssi") + " $DSP $OPTIONS" ); #elif defined __APPLE__ settings.setValue( "coreaudio-qt", QString("faust2caqt") + " $DSP $OPTIONS" ); settings.setValue( "maxmsp", QString("faust2msp") + " $DSP $OPTIONS" ); settings.setValue( "vst", QString("faust2vst") + " $DSP $OPTIONS" ); settings.setValue( "csound", QString("faust2csound") + " $DSP $OPTIONS" ); settings.setValue( "puredata", QString("faust2puredata") + " $DSP $OPTIONS" ); settings.setValue( "supercollider", QString("faust2supercollider") + " $DSP $OPTIONS" ); #elif defined WIN32 #endif settings.endGroup(); // ----- Build options settings.remove( OPTIONS_SETTING ); settings.beginGroup( OPTIONS_SETTING ); settings.setValue( "Scalar" , "" ); settings.setValue( "Vectorial" , "-vec -vs 64" ); settings.setValue( "Parallel (OpenMP)", "-omp -vs 512" ); settings.setValue( "Parallel (WS)", "-sch -vs 512" ); settings.endGroup(); } //------------------------------------------------------------------------- // Protected slots /// //------------------------------------------------------------------------- //------------------------------------------------------------------------- void FaustMainWindow::preferences() { QFaustPreferences * dialog = new QFaustPreferences(this); if ( dialog->exec() == QDialog::Accepted ) { GraphicsSceneMainWindow::readPreferencesSettings(); readPreferencesSettings(); } } //------------------------------------------------------------------------- void FaustMainWindow::updateCode() { int vFaustEditScrollValue = mLanguageTextEdit->verticalScrollBar()->value(); int hFaustEditScrollValue = mLanguageTextEdit->horizontalScrollBar()->value(); GraphicsSceneMainWindow::updateCode(); mLanguageTextEdit->verticalScrollBar()->setValue( vFaustEditScrollValue ); mLanguageTextEdit->horizontalScrollBar()->setValue( hFaustEditScrollValue ); // if ( ( mFirstSelectedItem ) && ( mCPPTextEdit->isEnabled() ) ) if ( mCPPTextEdit->isEnabled() ) { QString newCode = ((QFaustItem*)mFirstSelectedItem)->cppCode(); if ( mCPPTextEdit->toPlainText() != newCode ) { int vSliderValue = mCPPTextEdit->verticalScrollBar()->value(); int hSliderValue = mCPPTextEdit->horizontalScrollBar()->value(); mCPPTextEdit->setText( newCode ); mCPPTextEdit->horizontalScrollBar()->setValue( hSliderValue ); mCPPTextEdit->verticalScrollBar()->setValue( vSliderValue ); } } } //------------------------------------------------------------------------- void FaustMainWindow::targetArchitectureChanged(int index) { QSettings settings("grame.fr", "FaustWorks"); settings.setValue( CURRENT_TARGET_ARCHITECTURE_SETTING , mTargetsComboBox->currentText() ); setBuildCommand( mTargetsComboBox->itemData( index ).toString() ); } //------------------------------------------------------------------------- void FaustMainWindow::buildOptionsChanged(int index) { QSettings settings("grame.fr", "FaustWorks"); settings.setValue( CURRENT_BUILD_OPTION_SETTING , mOptionsComboBox->currentText() ); setBuildOptions( mOptionsComboBox->itemData( index ).toString() ); updateCode(); } //------------------------------------------------------------------------- void FaustMainWindow::droppedFileTypeChanged(int droppedFileTypeIndex) { QFaustItem::setDroppedFileType( mDropTypeComboBox->itemData(droppedFileTypeIndex).toInt() ); } //------------------------------------------------------------------------- void FaustMainWindow::itemLaunchScriptError(const QString& command) { QMessageBox::warning( 0 , tr("Binary build error") , tr("Couldn't launch command %1!").arg(command)); } //------------------------------------------------------------------------- void FaustMainWindow::itemBuildError(int errorType , const QString& msg) { QString statusMsg = ""; switch ( errorType ) { case QFaustItem::SCRIPT_ERROR : { statusMsg = tr("Script error : ") + msg; break; } case QFaustItem::SCRIPT_CRASHED : { statusMsg = tr("Script crashed"); if ( msg.length() ) statusMsg += (" : " + msg); break; } case QFaustItem::SCRIPT_NO_FILE : { statusMsg = tr("Script : no output file specified"); break; } case QFaustItem::SCRIPT_FILE_NOT_FOUND : { statusMsg = tr("Script : output file(s) %1 not found.").arg(msg); break; } } //statusBar()->showMessage( statusMsg ); // qDebug() << "FaustMainWindow::itemBuildError : " << statusMsg; QMessageBox::warning( 0 , tr("Binary build error") , statusMsg ); } //------------------------------------------------------------------------- /** * Combine an item A with a dropped item B according to a combination type */ void FaustMainWindow::combineItems(QGraphicsItem* dropped,QGraphicsItem* target,int,int,int combinationType) { QFaustItem * fixedItem = (QFaustItem *)target; QFaustItem * droppedItem = (QFaustItem *)dropped; //Auto-save the item, or save it to untitled_1/2/3... if //there wheren't saved. if ( fixedItem->file().length() ) fixedItem->save( fixedItem->file() ); else fixedItem->save( availableDefaultName( fixedItem->name() ) ); if ( droppedItem->file().length() ) droppedItem->save( droppedItem->file() ); else droppedItem->save( availableDefaultName( droppedItem->name() ) ); // the various ways to combine Faust programs QString code; switch ( combinationType ) { case COMBINATION_SEQ1 : code = buildCombinationCode( droppedItem->file() , fixedItem->file(), ":"); break; case COMBINATION_SEQ2 : code = buildCombinationCode( fixedItem->file() , droppedItem->file(), ":"); break; case COMBINATION_PAR1 : code = buildCombinationCode( droppedItem->file() , fixedItem->file(), ","); break; case COMBINATION_PAR2 : code = buildCombinationCode( fixedItem->file() , droppedItem->file(), ","); break; case COMBINATION_SPLIT1 : code = buildCombinationCode( droppedItem->file() , fixedItem->file(), "<:"); break; case COMBINATION_SPLIT2 : code = buildCombinationCode( fixedItem->file() , droppedItem->file(), "<:"); break; case COMBINATION_MERGE1 : code = buildCombinationCode( droppedItem->file() , fixedItem->file(), ":>"); break; case COMBINATION_MERGE2 : code = buildCombinationCode( fixedItem->file() , droppedItem->file(), ":>"); break; case COMBINATION_REC1 : code = buildCombinationCode( droppedItem->file() , fixedItem->file(), "~"); break; case COMBINATION_REC2 : code = buildCombinationCode( fixedItem->file() , droppedItem->file(), "~"); break; default: qFatal("ERROR unrecognized combination code %d\n", combinationType); } //Set the code of the target item with the code computed by GuidoAR fixedItem->setCode( code ); fixedItem->unlinkFile(); //It's a fusion of 2 items, so we remove the dropped item (only if it was in the main scene: history&storage items are not affected). if ( droppedItem->scene() == mGraphicsScene ) { droppedItem->deleteLater(); itemRemoved( droppedItem ); } unselectAll(); fixedItem->setSelected( true ); //Don't forget to call QGraphicsSceneMainWindow::addToHistory, because we changed the item's code GraphicsSceneMainWindow::addToHistory(fixedItem); } //------------------------------------------------------------------------ // Protected members // //------------------------------------------------------------------------ //----------------------------------------------------------------------- void FaustMainWindow::init() { mIsWorkspaceModeOn = true; GraphicsSceneMainWindow::init(); } // Update values / widgets / anything that depends on the Settings. //------------------------------------------------------------------------- void FaustMainWindow::readSettings() { //Reads the type of settings that are set in the preference //Note: faust executable path & build commands are set here readPreferencesSettings(); //Call GraphicsSceneMainWindow function //Note : the workspace-scene is loaded here, so the //faust executable path & build commands must have been set before. GraphicsSceneMainWindow::readSettings(); QSettings settings("grame.fr", "FaustWorks"); //Update changed values //Update text edits. mCPPTextEdit->setFontPointSize( settings.value( FONT_SIZE_SETTING ).toDouble() ); reloadTextEdits(); } QString makeAbsolutePath(const QString& path) { if (path[0]!='.') return path; return QDir::cleanPath(QCoreApplication::applicationDirPath() + "/" + path); } //------------------------------------------------------------------------- void FaustMainWindow::readPreferencesSettings() { QSettings settings("grame.fr", "FaustWorks"); QString faustAbsolutePath = makeAbsolutePath(settings.value(FAUST_PATH_SETTING).toString()); qDebug() << "faustAbsolutePath : " << faustAbsolutePath; //Update Faust Path QFaustItem::setFaustPath( faustAbsolutePath ); QProcess p; p.start( faustAbsolutePath + " -v " ); p.close(); if ( p.error() == QProcess::FailedToStart ) { QMessageBox::warning( 0 , tr("Faust not found") , tr("Couldn't launch %1.\n" "The file may not exist, or you may not have the rights to execute it.\n" "You must define a valid faust executable in the Application Preferences.").arg(faustAbsolutePath) ); } //Update combobox updateBuildComboBox( mTargetsComboBox , SLOT( targetArchitectureChanged(int) ) , TARGETS_SETTING , CURRENT_TARGET_ARCHITECTURE_SETTING ); updateBuildComboBox( mOptionsComboBox , SLOT( buildOptionsChanged(int) ) , OPTIONS_SETTING , CURRENT_BUILD_OPTION_SETTING ); setBuildCommand( mTargetsComboBox->itemData( mTargetsComboBox->currentIndex() ).toString() ); setBuildOptions( mOptionsComboBox->itemData( mOptionsComboBox->currentIndex() ).toString() ); } //----------------------------------------------------------------------- void FaustMainWindow::updateBuildComboBox( QComboBox * comboBox , const char * indexChangedSlot , const QString& settingsKey , const QString& settingsIndexKey ) { disconnect( comboBox , SIGNAL(currentIndexChanged(int)) , this , indexChangedSlot ); comboBox->clear(); QSettings settings("grame.fr", "FaustWorks"); settings.beginGroup(settingsKey); QStringList keys = settings.allKeys(); for ( int i = 0 ; i < keys.size() ; i++ ) { comboBox->addItem( keys[i] , settings.value( keys[i] ) ); } settings.endGroup(); connect( comboBox , SIGNAL(currentIndexChanged(int)) , this , indexChangedSlot ); QString t = settings.value( settingsIndexKey ).toString(); int selectedIndex = comboBox->findText( t ); if ( selectedIndex == -1 ) selectedIndex = 0; if ( comboBox->currentIndex() != selectedIndex ) comboBox->setCurrentIndex( selectedIndex ); } //----------------------------------------------------------------------- void FaustMainWindow::createActions() { GraphicsSceneMainWindow::createActions(); mPreferencesAct = new QAction(tr("Preferences"), this); mPreferencesAct->setStatusTip(tr("Setup the applications parameters")); connect(mPreferencesAct, SIGNAL(triggered()), this, SLOT(preferences())); mAddAct->setIcon(QIcon(RSC_DIR + QString("addFaust.png"))); mAddFromFileAct->setIcon(QIcon(RSC_DIR + QString("addFromFileFaust.png"))); mRemoveAct->setIcon(QIcon(RSC_DIR + QString("removeFaust.png"))); } //----------------------------------------------------------------------- void FaustMainWindow::createMenus() { GraphicsSceneMainWindow::createMenus(); QAction * sep; sep = new QAction(this); sep->setSeparator(true); mFileMenu->insertAction(mExitAct , sep ); mFileMenu->insertAction( mExitAct , mPreferencesAct); sep = new QAction(this); sep->setSeparator(true); mFileMenu->insertAction(mExitAct , sep ); } //----------------------------------------------------------------------- void FaustMainWindow::createToolBars() { GraphicsSceneMainWindow::createToolBars(); mBuildToolBar = addToolBar(tr("&Build")); mBuildToolBar->setObjectName("BuildToolBar"); /* // supprim par yo le 16 septembre 2010 car inutile.... mDropTypeComboBox = new QComboBox( this ); mDropTypeComboBox->setToolTip("Dropped-out file"); mDropTypeComboBox->setStatusTip("Choose the type of file exported when dropping an item out of the application."); mDropTypeComboBox->addItem("Binary" , QVariant( QFaustItem::DROP_BINARY ) ); mDropTypeComboBox->addItem("DSP" , QVariant( QFaustItem::DROP_DSP ) ); mDropTypeComboBox->addItem("CPP" , QVariant( QFaustItem::DROP_CPP ) ); mDropTypeComboBox->addItem("SVG" , QVariant( QFaustItem::DROP_SVG ) ); connect( mDropTypeComboBox , SIGNAL(currentIndexChanged(int)) , this , SLOT(droppedFileTypeChanged(int)) ); mBuildToolBar->addWidget( mDropTypeComboBox ); */ mTargetsComboBox = new QComboBox( this ); mTargetsComboBox->setToolTip(tr("Target architecture")); mTargetsComboBox->setStatusTip(tr("Choose the exported plug-in architecture")); connect( mTargetsComboBox , SIGNAL(currentIndexChanged(int)) , this , SLOT(targetArchitectureChanged(int)) ); mBuildToolBar->addWidget( mTargetsComboBox ); mOptionsComboBox = new QComboBox( this ); mOptionsComboBox->setToolTip(tr("Build options")); mOptionsComboBox->setStatusTip(tr("Build options used for $OPTIONS by binary build scripts")); connect( mOptionsComboBox , SIGNAL(currentIndexChanged(int)) , this , SLOT(buildOptionsChanged(int)) ); mBuildToolBar->addWidget( mOptionsComboBox ); } //------------------------------------------------------------------------- void FaustMainWindow::setupNAddItem(QLanguageItem* decorator) { GraphicsSceneMainWindow::setupNAddItem(decorator); QFaustItem * faustItem = (QFaustItem *)decorator; connect( faustItem , SIGNAL( buildError(int , const QString&) ) , this , SLOT( itemBuildError(int , const QString&)) ); connect( faustItem , SIGNAL( launchScriptError(const QString&) ) , this , SLOT( itemLaunchScriptError(const QString&)) ); } //------------------------------------------------------------------------- bool FaustMainWindow::addLanguageItem(const QString &gmnSource, bool sourceIsAFile , QLanguageItem** createdItem) { bool result = GraphicsSceneMainWindow::addLanguageItem( gmnSource , sourceIsAFile , createdItem ); return result; } //------------------------------------------------------------------------- QItemResizer * FaustMainWindow::plugResizer( QLanguageItem * itemContainer ) { QItemResizer * itemResizer = GraphicsSceneMainWindow::plugResizer( itemContainer ); itemResizer->setKeepAspectRatio( true ); itemResizer->setBrush( QBrush( QColor(FAUST_ITEM_BASE_RGB , 50) ) ); itemResizer->setPen( QPen( QColor(FAUST_ITEM_BASE_RGB , 250) ) ); return itemResizer; } //------------------------------------------------------------------------- void FaustMainWindow::updateWindowState() { int vFaustEditScrollValue = mLanguageTextEdit->verticalScrollBar()->value(); int hFaustEditScrollValue = mLanguageTextEdit->horizontalScrollBar()->value(); GraphicsSceneMainWindow::updateWindowState(); mLanguageTextEdit->verticalScrollBar()->setValue( vFaustEditScrollValue ); mLanguageTextEdit->horizontalScrollBar()->setValue( hFaustEditScrollValue ); mCPPTextEdit->setEnabled( mLanguageTextEdit->isEnabled() ); if ( !mCPPTextEdit->isEnabled() ) mCPPTextEdit->setText( "" ); } //----------------------------------------------------------------------- void FaustMainWindow::changeFontSize( float newFontPointSize ) { mCPPTextEdit->setFontPointSize( newFontPointSize ); mCPPTextEdit->setTabStopWidth( QFontMetrics(mCPPTextEdit->currentFont()).width ( "a" ) * TAB_SPACE ); // Set mLanguageTextEdit->setFontPointSize here so that we can also call mLanguageTextEdit->setTabStopWidth, // that hasn't to be called by GraphicsSceneMainWindow. mLanguageTextEdit->setFontPointSize( newFontPointSize ); mLanguageTextEdit->setTabStopWidth( QFontMetrics(mLanguageTextEdit->currentFont()).width ( "a" ) * TAB_SPACE ); GraphicsSceneMainWindow::changeFontSize(newFontPointSize); } //------------------------------------------------------------------------- void FaustMainWindow::setBuildCommand( const QString& buildCommand ) { QFaustItem::setBuildCommand( buildCommand ); QList items = selectedFaustItems(); for ( int i = 0 ; i < items.size() ; i++ ) { items[i]->checkBinary(); } } //------------------------------------------------------------------------- void FaustMainWindow::setBuildOptions( const QString& buildOptions ) { QFaustItem::setBuildOptions( buildOptions ); QList items = selectedFaustItems(); for ( int i = 0 ; i < items.size() ; i++ ) { items[i]->checkBinary(); } } //------------------------------------------------------------------------- void FaustMainWindow::reloadTextEdits() { GraphicsSceneMainWindow::reloadTextEdits(); int vValue = mCPPTextEdit->verticalScrollBar()->value(); int hValue = mCPPTextEdit->horizontalScrollBar()->value(); mCPPTextEdit->setText( mCPPTextEdit->toPlainText() ); mCPPTextEdit->verticalScrollBar()->setValue( vValue ); mCPPTextEdit->horizontalScrollBar()->setValue( hValue ); } //------------------------------------------------------------------------- void FaustMainWindow::closeEvent(QCloseEvent *event) { if (gErrorWindow) gErrorWindow->close(); GraphicsSceneMainWindow::closeEvent(event); } //------------------------------------------------------------------------- QString FaustMainWindow::availableDefaultName(const QString& baseName) { int num = 0; QString generatedName; while ( (num==0) || QFile::exists( generatedName ) ) { num++; generatedName = getFileDialogPath() + "/" + baseName + "_" + QVariant(num).toString() + "." + mSettings.mLanguageFileExtension ; } return generatedName; } //------------------------------------------------------------------------- QString FaustMainWindow::buildCombinationCode( const QString& file1 , const QString& file2 , const QString& faustOperator ) { return "process = component( \"" + QFileInfo(file1).absoluteFilePath() + "\" ) " + faustOperator + " component( \"" + QFileInfo(file2).absoluteFilePath() + "\" );"; } //------------------------------------------------------------------------- QList FaustMainWindow::selectedFaustItems() { QList selectedItems = mGraphicsScene->selectedItems(); QList result; for ( int i = 0 ; i < selectedItems.size() ; i++ ) { QFaustItem* languageItem = dynamic_cast( selectedItems[i] ); if ( languageItem ) result.append( languageItem ); } return result; } FaustWorks-0.4/FaustMainWindow.h0000755000175000017500000000611312130743520015360 0ustar miramira/* * FaustMainWindow.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef FAUST_MAINWINDOW_H #define FAUST_MAINWINDOW_H #define FAUST_PATH_SETTING "faustPath" #define TARGETS_SETTING QString("targetsSetting") #define OPTIONS_SETTING QString("optionsSetting") #include #include #include #include #include "GraphicsSceneMainWindow.h" class QFaustItem; class FaustMainWindow : public GraphicsSceneMainWindow { Q_OBJECT public: FaustMainWindow(); void reinitPreferencesSettings(); protected slots: void preferences(); void updateCode(); void targetArchitectureChanged(int index); void buildOptionsChanged(int index); void droppedFileTypeChanged(int droppedFileTypeIndex); void itemLaunchScriptError(const QString& command); void itemBuildError(int errorType , const QString& msg); void combineItems(QGraphicsItem* dropped,QGraphicsItem* target,int,int,int interactionId); protected: void init(); void reinitSettings(); void readSettings(); void readPreferencesSettings(); void updateBuildComboBox( QComboBox * comboBox , const char * indexChangedSlot , const QString& settingsKey , const QString& settingsIndexKey ); void createActions(); void createMenus(); void createToolBars(); void setupNAddItem(QLanguageItem* decorator); bool addLanguageItem(const QString &gmnSource, bool sourceIsAFile , QLanguageItem** createdItem); QItemResizer * plugResizer( QLanguageItem * itemContainer ); void updateWindowState(); void changeFontSize( float newFontPointSize ); void setBuildCommand( const QString& buildCommand ); void setBuildOptions( const QString& buildCommand ); virtual void reloadTextEdits(); void closeEvent(QCloseEvent *event); QString availableDefaultName(const QString& baseName); static QString buildCombinationCode( const QString& file1 , const QString& file2 , const QString& faustOperator ); QList selectedFaustItems(); QAction * mPreferencesAct; QTextEdit* mCPPTextEdit; QDockWidget* mCPPTextEditDock; QDockWidget* mErrorDock; QComboBox * mTargetsComboBox; QComboBox * mOptionsComboBox; QComboBox * mDropTypeComboBox; QToolBar * mBuildToolBar; }; /* #include class QHashStringString : public QHash { public : QHashStringString() : QHash() {} }; Q_DECLARE_METATYPE(QHashStringString) */ #endif FaustWorks-0.4/FaustWorks.pro0000644000175000017500000000361312130743520014761 0ustar miramira###################################################################### # Automatically generated by qmake (2.01a) ven. nov. 27 15:18:38 2009 ###################################################################### TEMPLATE = app TARGET = DEPENDPATH += . Forms Resources INCLUDEPATH += . QT += xml svg RC_FILE = Resources/FaustWorks.rc ICON = Resources/FaustWorks.icns # Input HEADERS += CPPHighlighter.h \ FaustHighlighter.h \ FaustMainWindow.h \ GraphicsSceneMainWindow.h \ MainWindowObjects.h \ MusicNotationHighlighter.h \ QFaustItem.h \ QFaustItemFactory.h \ QFaustPreferences.h \ QItemResizer.h \ QLanguageCommandPalette.h \ QLanguageCommandPaletteLayout.h \ QLanguageCommandReader.h \ QLanguageItem.h \ QLanguageItemFactory.h \ QPaletteItem.h \ QResolutionDialog.h \ QSwitcher.h \ Resources/resource.h FORMS += Forms/FaustPreferences.ui Forms/ResolutionDialog.ui SOURCES += CPPHighlighter.cpp \ FaustHighlighter.cpp \ FaustMainWindow.cpp \ GraphicsSceneMainWindow.cpp \ main.cpp \ MainWindowObjects.cpp \ MusicNotationHighlighter.cpp \ QFaustItem.cpp \ QFaustItemFactory.cpp \ QFaustPreferences.cpp \ QItemResizer.cpp \ QLanguageCommandPalette.cpp \ QLanguageCommandPaletteLayout.cpp \ QLanguageCommandReader.cpp \ QLanguageItem.cpp \ QPaletteItem.cpp \ QResolutionDialog.cpp RESOURCES += Resources/application.qrc Resources/faust.qrc Resources/i18n.qrc OTHER_FILES += Resources/FaustWorks.rc TRANSLATIONS += Resources/translations/i18n_ru.ts i18n_qm.commands = lrelease FaustWorks.pro QMAKE_EXTRA_TARGETS += i18n_qm PRE_TARGETDEPS += i18n_qm FaustWorks-0.4/GraphicsSceneMainWindow.cpp0000755000175000017500000025642712130743520017366 0ustar miramira/* * GraphicsSceneMainWindow.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "GraphicsSceneMainWindow.h" #include "QLanguageItem.h" #include "QLanguageItemFactory.h" #include "QItemResizer.h" #include "MainWindowObjects.h" #include "QLanguageCommandPalette.h" #include "QResolutionDialog.h" #include #include #include #include #include #include #include #include #include #define LANGUAGE_NAME_SHORT GraphicsSceneMainWindow::applicationSettings().mLanguageNameShort #define LANGUAGE_NAME_LONG GraphicsSceneMainWindow::applicationSettings().mLanguageNameLong #define LANGUAGE_FILE_EXTENSION GraphicsSceneMainWindow::applicationSettings().mLanguageFileExtension #define SCENE_FILE_EXTENSION GraphicsSceneMainWindow::applicationSettings().mSceneFileExtension #define DEFAULT_LANGUAGE_CODE GraphicsSceneMainWindow::applicationSettings().mDefaultLanguageCode #define LANGUAGE_COMMANDS_FILE GraphicsSceneMainWindow::applicationSettings().mLanguageCommandsFile #define COMMAND_PALETTE_DOCK_NAME LANGUAGE_NAME_SHORT + " Helper" #define GMN_EDIT_DOCK_NAME LANGUAGE_NAME_SHORT + " Code" #define GSC_FILE_EXTENSION SCENE_FILE_EXTENSION #define GMN_FILE_EXTENSION LANGUAGE_FILE_EXTENSION #define GSC_FILE_FILTER QString( LANGUAGE_NAME_SHORT + QString(" Scene (*."+ GSC_FILE_EXTENSION + ")") ) #define GMN_FILE_FILTER QString( LANGUAGE_NAME_LONG + QString(" (*." + GMN_FILE_EXTENSION + ")") ) #define DEFAULT_WINDOW_WIDTH 1000 #define DEFAULT_WINDOW_HEIGHT 700 #define DEFAULT_WINDOW_X 200 #define DEFAULT_WINDOW_Y 200 #define DEFAULT_WINDOW_POS QPoint( DEFAULT_WINDOW_X , DEFAULT_WINDOW_Y ) #define SLIDER_PRECISION_FACTOR 100.0f #define SLIDER_TOOL_BAR_MARGIN 50 #define CACHE_MEMORY_SIZE 100000 #define MAX_COORDINATE_EDIT 99999 #define PASTE_ITEM_DISTANCE 5 #define START_SCENE_RECT_SIZE_X 400 #define START_SCENE_RECT_SIZE_Y 400 #define START_SCENE_RECT QRectF( \ -START_SCENE_RECT_SIZE_X/2,-START_SCENE_RECT_SIZE_Y/2, \ START_SCENE_RECT_SIZE_X,START_SCENE_RECT_SIZE_Y \ ) #define MIN_PAGE_SIZE 20 //#define ITEM_SIZE_BOUNDS QSize( 400,300 ) //#define TEXT_EDIT_TEMPO 2500 #define TEXT_EDIT_TEMPO 1000 #define TEXT_EDIT_TEMPO_FACTOR 0.1f #define COMBINATOR_PIXMAP_MARGIN 10 #define COMBINATOR_HIGHLIGHT_PEN_COLOR Qt::red #define COMBINATOR_HIGHLIGHT_BRUSH_COLOR QColor(255,0,0,50) #define COMBINATOR_HIGHLIGHT_PEN QPen( COMBINATOR_HIGHLIGHT_PEN_COLOR ) #define COMBINATOR_HIGHLIGHT_BRUSH QBrush( COMBINATOR_HIGHLIGHT_BRUSH_COLOR ) //DOM Document defines #define DOM_DOC "GraphicsScene" #define DOM_ROOT "SceneRoot" #define DOM_SCENE "Scene" #define DOM_VIEW_X "viewX" #define DOM_VIEW_Y "viewY" #define DOM_VIEW_ZOOM "viewZoom" #define DOM_SCENE_X "sceneX" #define DOM_SCENE_Y "sceneY" #define DOM_SCENE_WIDTH "sceneWidth" #define DOM_SCENE_HEIGHT "sceneHeight" #define DOM_SPLITTER_SIZE_0 "Splitter0" #define DOM_SPLITTER_SIZE_1 "Splitter1" #define INIT_DONE_SETTING "InitDone" #define WINDOW_SIZE_SETTING "WindowSize" #define WINDOW_POS_SETTING "WindowPos" #define WINDOW_STATE_SETTING "WindowState" #define WINDOW_ZOOM_SETTING "WindowZoom" #define FILE_DIALOG_PATH_SETTING "FileDialogPathSetting" #define STORAGE_VISIBLE_SETTING "StorageVisibleSetting" #define HISTORY_VISIBLE_SETTING "HistoryVisibleSetting" #define CURRENT_SCENE_SETTING "CurrentSceneSetting" enum FileFilters { PNG_FILTER = 0, PDF_FILTER = 1, PS_FILTER = 2, GSC_FILTER = 3, GMN_FILTER = 4 }; GraphicsSceneMainWindowSettings GraphicsSceneMainWindow::mSettings = GraphicsSceneMainWindowSettings(); //------------------------------------------------------------------------- GraphicsSceneMainWindow::GraphicsSceneMainWindow( LanguageGraphicsView * graphicsView , QLanguageItemFactory * factory ) : mGraphicsView( graphicsView ) , mFactory( factory ) { connect( qApp, SIGNAL( focusChanged ( QWidget *, QWidget * ) ) , this, SLOT( focusChanged(QWidget*,QWidget*) ) ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::init() { // Create History & Storage GraphicsView/GraphicsScene createHistoryAndStorage(); // Main GraphicsScene/GraphicsView init ((LanguageGraphicsView *)mGraphicsView)->setMainWindow( this ); mGraphicsScene = 0; mBackgroundItem = 0; reinitScene( START_SCENE_RECT ); // mGraphicsView->setBackgroundRole(QPalette::Dark); // mGraphicsView->setResizeAnchor(QGraphicsView::NoAnchor); // mGraphicsView->setAlignment( 0 ); // Guido code edit widget setupTextEdit(); // Layout the History widget, the main GraphicsView widget and the Storage widget QWidget *window = new QWidget(); QHBoxLayout *layout = new QHBoxLayout(window); if ( mSettings.mHasHistory ) layout->addWidget(mHistoryGraphicsView); mSplitter = new QSplitter(this); mSplitter->addWidget(mGraphicsView); layout->addWidget( mSplitter ); if ( mSettings.mHasStorage ) mSplitter->addWidget( mStorageGraphicsView ); // Main Scene is the central Widget setCentralWidget( window ); // Create actions, menus, toolbars createActions(); createToolBars(); createMenus(); createStatusBar(); // App init setDockOptions ( AnimatedDocks ); QPixmapCache::setCacheLimit ( CACHE_MEMORY_SIZE ); setAcceptDrops(true); mSceneHasChanged = false; // mCurrentZOrderItem = 0; updateWindowState(); mStdMainWindowState = saveState(); checkSettings(); } //------------------------------------------------------------------------- GraphicsSceneMainWindow::~GraphicsSceneMainWindow() { delete mFactory; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::reinitSettings() { QSettings settings("grame.fr", "FaustWorks"); settings.setValue( INIT_DONE_SETTING , true ); settings.setValue( FONT_SIZE_SETTING , DEFAULT_FONT_SIZE ); settings.setValue( WINDOW_POS_SETTING , DEFAULT_WINDOW_POS ); settings.setValue( WINDOW_SIZE_SETTING, QSize(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT) ); settings.setValue( FILE_DIALOG_PATH_SETTING , QDir::homePath() ); // settings.setValue( WORKSPACE_MODE_SETTING , false ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::writeSettings() { QSettings settings("grame.fr", "FaustWorks"); settings.setValue( WINDOW_POS_SETTING , pos() ); settings.setValue( WINDOW_SIZE_SETTING, size() ); settings.setValue( WINDOW_STATE_SETTING, saveState() ); settings.setValue( WINDOW_ZOOM_SETTING , mGraphicsView->transform().m11() ); settings.setValue( FILE_DIALOG_PATH_SETTING , mLastOpenFilePath ); // settings.setValue( WORKSPACE_MODE_SETTING , mIsWorkspaceModeOn ); if ( mSettings.mHasStorage ) { settings.setValue( STORAGE_VISIBLE_SETTING , mStorageGraphicsView->isVisible() ); } if ( mSettings.mHasHistory ) { settings.setValue( HISTORY_VISIBLE_SETTING , mHistoryGraphicsView->isVisible() ); } } //------------------------------------------------------------------------- const GraphicsSceneMainWindowSettings& GraphicsSceneMainWindow::applicationSettings() { return GraphicsSceneMainWindow::mSettings; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::initApplicationSettings( const GraphicsSceneMainWindowSettings& settings ) { GraphicsSceneMainWindow::mSettings = settings; } //-----------------------------------------------------------------------// // Private slots // //-----------------------------------------------------------------------// //------------------------------------------------------------------------- QPointF GraphicsSceneMainWindow::viewCenterInSceneCoordinate() { QPoint viewPortCenter( mGraphicsView->width() / 2 , mGraphicsView->height() / 2 ); QPointF sceneCenterPoint = mGraphicsView->mapToScene( viewPortCenter ); return sceneCenterPoint; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::addItem() { QLanguageItem* createdItem = 0; addCode( DEFAULT_LANGUAGE_CODE , &createdItem ); setupItemFromMenu(createdItem); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::addItemFromFile() { //Select a file QString fileName = QFileDialog::getOpenFileName( this, tr("Add a %1 file").arg(LANGUAGE_NAME_LONG), getFileDialogPath(), tr( QString( GMN_FILE_FILTER + QString("\nAll (*.*)") ).toAscii().data() )); // Create the item with the file QLanguageItem* createdItem = 0; addFile( fileName , &createdItem ); // Add & setup the created item if ( createdItem ) setupItemFromMenu( createdItem ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::removeSelectedItems() { //StorageGraphicsView gets the removeAction if: // - it has focus // - AND it has selected items if ( ( mSettings.mHasStorage ) && ( mStorageGraphicsView->hasFocus() ) && ( mStorageGraphicsScene->selectedItems().size() > 0 ) ) { while ( mStorageGraphicsScene->selectedItems().size() > 0 ) { QGraphicsItem * item = mStorageGraphicsScene->selectedItems()[0]; mStorageGraphicsView->removeItem( item ); mSceneHasChanged = true; } updateRemoveActState(); } else { // Delete all the items that are in the mSelectedItems list. QList selectedItems = selectedLanguageItems(); while ( selectedItems.size() > 0 ) { if ( !removeItem( selectedItems[0] ) ) { break; } selectedItems.removeAt( 0 ); mSceneHasChanged = true; } updateWindowState(); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::copyItem() { QList selectedItems = selectedLanguageItems(); mCopiedItems.clear(); for ( int i = 0 ; i < selectedItems.size() ; i++ ) { mCopiedItems.append( selectedItems[i] ); } //Paste action is now available mPasteAct->setEnabled( true ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::pasteItem() { // Deselect all the currently selected item, // in order to select only the newly pasted items. unselectAll(); // Create and add to selection all the item in mCopiedItems. for ( int i = 0 ; i < mCopiedItems.size() ; i++ ) { QLanguageItem * item = addItemCopy( mCopiedItems[i] ); item->moveBy( PASTE_ITEM_DISTANCE , PASTE_ITEM_DISTANCE ); item->setSelected( true ); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::selectAll() { // Ignore the QGraphicsScene::selectionChanged() signal during the operation, // so that it can be done just once, at the end of the operation. disconnect(mGraphicsScene,SIGNAL(selectionChanged ()),this,SLOT(sceneSelectionChanged())); QList items = languageItems(); for ( int i = 0 ; i < items.size() ; i++ ) { items[i]->setSelected(true); } connect(mGraphicsScene,SIGNAL(selectionChanged ()),this,SLOT(sceneSelectionChanged())); sceneSelectionChanged(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::cleanHistory() { if ( mSettings.mHasHistory ) mHistoryGraphicsView->clear(); } //------------------------------------------------------------------------- QString getZoomLabel(float zoom) { return QString("Zoom: x%1").arg(zoom, 0, 'd', 2); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::zoomIn() { zoom( mSettings.mZoomFactor ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::zoomOut() { zoom( 1.0f / mSettings.mZoomFactor ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::zoomStandard() { zoom( 1.0f / mGraphicsView->transform().m11() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::zoom( float zoom ) { if ( mGraphicsView->transform().m11() * zoom < mSettings.mMinZoom ) { zoom = mSettings.mMinZoom / mGraphicsView->transform().m11(); } else if ( mGraphicsView->transform().m11() * zoom > mSettings.mMaxZoom ) { zoom = mSettings.mMaxZoom / mGraphicsView->transform().m11(); } mGraphicsView->scale( zoom , zoom ); mZoomOutAct->setEnabled( mGraphicsView->transform().m11() > ( mSettings.mMinZoom + 0.00001f ) ); mZoomInAct->setEnabled( mGraphicsView->transform().m11() < mSettings.mMaxZoom - 0.00001f ); updateZoomLabel(); } //------------------------------------------------------------------------- QString GraphicsSceneMainWindow::getFileDialogPath() { if ( mLastOpenFilePath == "" ) mLastOpenFilePath = windowFilePath(); if ( mLastOpenFilePath == "" ) mLastOpenFilePath = QDir::homePath(); return mLastOpenFilePath; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::setLastManagedFile(const QString& lastFile) { mLastOpenFilePath = QFileInfo( lastFile ).absolutePath(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::fontBigger() { changeFontSize( MIN( mLanguageTextEdit->fontPointSize() + 2 , MAX_FONT_SIZE ) ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::fontSmaller() { changeFontSize( MAX( mLanguageTextEdit->fontPointSize() - 2 , MIN_FONT_SIZE ) ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::reloadTextEdits() { int vValue = mLanguageTextEdit->verticalScrollBar()->value(); int hValue = mLanguageTextEdit->horizontalScrollBar()->value(); mLanguageTextEdit->setText( mLanguageTextEdit->toPlainText() ); mLanguageTextEdit->verticalScrollBar()->setValue( vValue ); mLanguageTextEdit->horizontalScrollBar()->setValue( hValue ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::changeFontSize( float newFontPointSize ) { mLanguageTextEdit->setFontPointSize( newFontPointSize ); QSettings("grame.fr", "FaustWorks").setValue( FONT_SIZE_SETTING , mLanguageTextEdit->fontPointSize() ); reloadTextEdits(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::sceneSelectionChanged() { statusBar()->showMessage(tr("%n item(s) selected", "", selectedLanguageItems().size()).arg(selectedLanguageItems().size())); updateWindowState(); } //------------------------------------------------------------------------- /** * Control the scene is large enough to contain all the language * items */ void GraphicsSceneMainWindow::sceneChanged( const QList &) { updateItemPositionControls(); // autoScrollOnSelectedItems(mGraphicsView); int totalMargin = PAGE_ITEM_IN_MARGIN + PAGE_ITEM_OUT_MARGIN; QRectF backgroundRect = mBackgroundItem->boundingRect(); QList items = mGraphicsScene->items(); for ( int i = 0; i < items.size() ; i++ ) { QLanguageItem * languageItem = dynamic_cast(items[i]); if ( languageItem) { QRectF decoratorBoundingRect = languageItem->mapToScene( languageItem->boundingRect() ).boundingRect(); if ( ( !mBackgroundItem->collidesWithItem( languageItem , Qt::ContainsItemBoundingRect ) ) || ( backgroundRect.width() < decoratorBoundingRect.width() + totalMargin ) || ( backgroundRect.height() < decoratorBoundingRect.height() + totalMargin ) ) { QRectF rect1 = decoratorBoundingRect; QRectF rect2 = decoratorBoundingRect; rect1.translate( totalMargin , totalMargin ); rect2.translate(-totalMargin ,-totalMargin ); QRectF totalRect = mBackgroundItem->sceneBoundingRect() | rect1 | rect2; mBackgroundItem->setRect( totalRect ); } } } mGraphicsScene->setSceneRect( mBackgroundItem->sceneBoundingRect() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::textEditActivity() { //mLanguageTextEditTimer->start( TEXT_EDIT_TEMPO + mLanguageTextEdit->toPlainText().length() * TEXT_EDIT_TEMPO_FACTOR ); mLanguageTextEditTimer->start( TEXT_EDIT_TEMPO); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateCode() { mLanguageTextEditTimer->stop(); if ( mLanguageTextEdit->isEnabled() ) { QString newGMNCode = mLanguageTextEdit->toPlainText(); if ( newGMNCode == mFirstSelectedItem->code() ) { return; } QApplication::setOverrideCursor(Qt::WaitCursor); mSceneHasChanged = true; if ( mFirstSelectedItem->setCode( newGMNCode ) ) { statusBar()->showMessage(tr("%1 Code OK").arg(LANGUAGE_NAME_SHORT)); addToHistory( mFirstSelectedItem ); } else { statusBar()->showMessage( mFirstSelectedItem->lastErrorMessage() ); } mLanguageTextEditDock->setWindowTitle( (mFirstSelectedItem->file().length() > 0 ) ? mFirstSelectedItem->getDescriptiveFileName() : GMN_EDIT_DOCK_NAME ); QApplication::restoreOverrideCursor(); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::resizeSliderChanged(int value) { float scale = pow(10,value / SLIDER_PRECISION_FACTOR ); scaleItems( scale ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::scaleItems(double scale) { scaleItems( 0,0, scale ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::scaleItems( double , double , double sizeScale ) { QList selectedItems = selectedLanguageItems(); for ( int i = 0 ; i < selectedItems.size() ; i++ ) { QRectF r = selectedItems[i]->rect(); r.setWidth( r.width() * sizeScale/selectedItems[i]->currentScale() ); r.setHeight( r.height() * sizeScale/selectedItems[i]->currentScale() ); selectedItems[i]->resized( r ); } updateScaleControls(sizeScale); mSceneHasChanged = true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::scaleChanged(float newScale) { updateScaleControls(newScale); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::moveItemX(double x) { QList selectedItems = selectedLanguageItems(); if ( selectedItems.size() == 1 ) { mFirstSelectedItem->setPos( x , mFirstSelectedItem->pos().y() ); } mSceneHasChanged = true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::moveItemY(double y) { QList selectedItems = selectedLanguageItems(); if ( selectedItems.size() == 1 ) { mFirstSelectedItem->setPos( mFirstSelectedItem->pos().x() , y ); } mSceneHasChanged = true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::resizeItems() { //Sets the scale of all selected items to the size of the first selected scaleItems( mFirstSelectedItem->currentScale() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::hAlignItems() { QList selectedItems = selectedLanguageItems(); //Sets the scale of all selected items to the size of the first selected float x = mFirstSelectedItem->pos().x(); for ( int i = 0 ; i < selectedItems.size() ; i++ ) { float y = selectedItems[i]->pos().y(); selectedItems[i]->setPos(x,y); } mSceneHasChanged = true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::vAlignItems() { QList selectedItems = selectedLanguageItems(); //Sets the scale of all selected items to the size of the first selected float y = mFirstSelectedItem->pos().y(); for ( int i = 0 ; i < selectedItems.size() ; i++ ) { float x = selectedItems[i]->pos().x(); selectedItems[i]->setPos(x,y); } mSceneHasChanged = true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::newScene() { //Save if necessary //saveOrCancelDialog == false <=> cancel if ( !saveOrCancelDialog() ) return; //Clear the scene reinitScene( START_SCENE_RECT ); mGraphicsView->centerOn( 0 , 0 ); mGraphicsView->setTransform( QTransform() ); //Update states setWindowFilePath(""); updateWindowState(); updateZoomLabel(); mSceneHasChanged = false; } // - If one item is selected (generally : because the user is editing its code) // saves this item. // - Else, saves the scene. //------------------------------------------------------------------------- void GraphicsSceneMainWindow::save() { QList selectedItems = selectedLanguageItems(); if ( selectedItems.size() == 1 ) { if ( selectedItems[0]->file().length() ) selectedItems[0]->save( selectedItems[0]->file() ); else saveItemAs( selectedItems[0] ); } else saveScene(); } //------------------------------------------------------------------------- QString getFileFilterExtension( const QString& filter ) { if ( filter == GSC_FILE_FILTER ) return GSC_FILE_EXTENSION; else if ( filter == PNG_FILE_FILTER ) return PNG_FILE_EXTENSION; else if ( filter == PDF_FILE_FILTER ) return PDF_FILE_EXTENSION; else if ( filter == PS_FILE_FILTER ) return PS_FILE_EXTENSION; else if ( filter == GMN_FILE_FILTER ) return GMN_FILE_EXTENSION; return ""; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::formatFileName(QString& fileName , QString& selectedFilter , const QString& filters) { QStringList filterList = filters.split("\n"); bool hasAFilter = false; QString fileNameFilter , fileNameExtension; for ( int i = 0 ; i < filterList.size() ; i++ ) { QString extension = getFileFilterExtension( filterList[i] ); if ( fileName.toUpper().endsWith( "." + extension.toUpper() ) ) { hasAFilter = true; fileNameFilter = filterList[i]; fileNameExtension = extension; break; } } // If the fileName already has an extension if ( hasAFilter ) { // If the extension is the same as the selectedFilter, ok. if ( fileNameFilter.toUpper() == selectedFilter.toUpper() ) return; else // If not, change the selectedFilter to match the fileName extension selectedFilter = fileNameFilter; } // If the fileName doesn't have an extension // - put the extension of the selectedFilter else { fileName += "." + getFileFilterExtension(selectedFilter); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::saveSceneAs() { QString savePath = windowFilePath(); if ( savePath == "" ) savePath = QDir::homePath() + "/untitled_scene"; QString filters = GSC_FILE_FILTER; QString selectedFilter(""); QString fileName = QFileDialog::getSaveFileName(this, tr("Save the %1 scene").arg(LANGUAGE_NAME_SHORT), savePath, tr(filters.toAscii().data()) , &selectedFilter); if ( fileName.isEmpty() ) return; formatFileName(fileName,selectedFilter,filters); saveSceneFile(fileName); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::saveAll() { QList items = languageItems(); for ( int i = 0 ; i < items.size() ; i++ ) { if ( !items[i]->file().isEmpty() ) { items[i]->saveItem(); } } saveScene(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::loadScene() { //Save if necessary //saveOrCancelDialog == false <=> cancel loadScene if ( !saveOrCancelDialog() ) return; //Open a file QString openPath = windowFilePath(); if ( openPath == "" ) openPath = QDir::homePath(); QString fileName = QFileDialog::getOpenFileName(this, tr("Open a %1 scene").arg(LANGUAGE_NAME_SHORT), openPath, tr( GSC_FILE_FILTER.toAscii().data() )); if ( !fileName.isEmpty() ) if ( !loadSceneFile(fileName) ) { QMessageBox::critical( 0 , tr("Load scene error") , tr("%1 : Invalid GuidoScene file").arg(fileName)); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::rescaleItem(float xScale , float yScale , float sizeScale) { scaleItems(xScale , yScale , sizeScale); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::resizePage( const QRectF& newRect ) { QRectF pageRect( newRect ); if ( pageRect.width() < MIN_PAGE_SIZE ) pageRect.setWidth( MIN_PAGE_SIZE ); if ( pageRect.height() < MIN_PAGE_SIZE ) pageRect.setHeight( MIN_PAGE_SIZE ); mBackgroundItem->setPageSize( pageRect.size() ); mBackgroundItem->moveBy( pageRect.topLeft().x() , pageRect.topLeft().y() ); mGraphicsScene->setSceneRect( mBackgroundItem->sceneBoundingRect() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::storeItem(QLanguageItem * container) { if ( mSettings.mHasStorage ) { QLanguageItem * other = mStorageGraphicsView->find( container ); if ( !other ) { mStorageGraphicsView->addItem( mFactory->buildLanguageItem( container ) ); } else { other->setSelected(true); } container->deleteLater(); itemRemoved( container ); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::itemRemoved() { QLanguageItem * container = dynamic_cast( sender() ); assert(container); itemRemoved( container ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::itemRemoved( QLanguageItem * languageItem ) { mGraphicsScene->removeItem( languageItem ); //Remove the item from all other references if ( mFirstSelectedItem == languageItem ) mFirstSelectedItem = 0; mCopiedItems.removeAll( languageItem ); mZOrderedItems.removeAll( languageItem ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::insertText( const QString& gmnCode , int insertIndex ) { if ( !mLanguageTextEdit->isEnabled() ) return; QTextCursor cursor = mLanguageTextEdit->textCursor(); QString selectedText = cursor.selectedText(); QString leftPart , rightPart; if ( insertIndex >= 0 ) { leftPart = gmnCode.left( insertIndex ); rightPart = gmnCode.right( gmnCode.length() - insertIndex ); } else { leftPart = gmnCode.left( gmnCode.length() + insertIndex ); rightPart = gmnCode.right( -insertIndex ); } cursor.insertText( leftPart + selectedText + rightPart ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::switchCommandPaletteVisible() { mCommandPaletteDock->setVisible( mSwitchCommandPaletteVisible->isChecked() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::switchTextEditVisible() { mLanguageTextEditDock->setVisible( mSwitchTextEditVisible->isChecked() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateWindowMenu() { if ( mSettings.mHasHistory ) mSwitchHistoryVisible->setChecked( mHistoryGraphicsView->isVisible() ); if ( mSettings.mHasStorage ) mSwitchStorageVisible->setChecked( mStorageGraphicsView->isVisible() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::switchStorageVisible() { if ( mSettings.mHasStorage ) mStorageGraphicsView->setVisible( !mStorageGraphicsView->isVisible() ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::switchHistoryVisible() { if ( mSettings.mHasHistory ) mHistoryGraphicsView->setVisible( !mHistoryGraphicsView->isVisible() ); } //------------------------------------------------------------------------- QString GraphicsSceneMainWindow::findFile(const QString& file) { // demander de specifier l'endroit du fichier. QString filter = tr("%1\nAll (*.*)").arg(file); QString fileName = QFileDialog::getOpenFileName ( this, tr("Find file"), file, filter ); return fileName; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::saveItemAs() { QLanguageItem * languageItem = (QLanguageItem *)(sender()); saveItemAs( languageItem ); } //------------------------------------------------------------------------- QLanguageItem* GraphicsSceneMainWindow::addItemCopy( QLanguageItem* item ) { QLanguageItem * languageItem = mFactory->buildLanguageItem( item ); setupNAddItem(languageItem); return languageItem; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::fileChanged(bool isFileRemoved) { QLanguageItem * languageItem = (QLanguageItem*)sender(); if ( isFileRemoved ) { unselectAll(); languageItem->setSelected( true ); QMessageBox msgBox( QMessageBox::Warning, tr("File not found"), tr("Can't find the %1 item's file %2").arg(mSettings.mLanguageNameShort).arg(languageItem->file())); QPushButton *findButton = msgBox.addButton(tr("Find file..."), QMessageBox::ActionRole); QPushButton *removeButton = msgBox.addButton(tr("Remove item"), QMessageBox::ActionRole); msgBox.addButton(QMessageBox::Ignore); msgBox.exec(); if (msgBox.clickedButton() == findButton) { QString file = findFile( languageItem->file() ); if ( QFile::exists( file ) ) languageItem->loadFile( file ); } else if ( msgBox.clickedButton() == removeButton ) { itemRemoved( languageItem ); languageItem->deleteLater(); } } else { languageItem->reloadItem(); updateWindowState(); #if 0 unselectAll(); languageItem->setSelected( true ); QMessageBox msgBox( QMessageBox::Warning, "File change", "The " + mSettings.mLanguageNameShort + " item's file " + languageItem->file() + " has changed." ); QPushButton *reloadButton = msgBox.addButton(tr("Reload"), QMessageBox::ActionRole); msgBox.addButton(QMessageBox::Ignore); msgBox.exec(); if (msgBox.clickedButton() == reloadButton) { languageItem->reloadItem(); updateWindowState(); } #endif } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::descriptiveNameChanged() { if ( mFirstSelectedItem ) mLanguageTextEditDock->setWindowTitle( (mFirstSelectedItem->file().length() > 0 ) ? mFirstSelectedItem->getDescriptiveFileName() : GMN_EDIT_DOCK_NAME ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::itemHasBeenReloaded() { if ( dynamic_cast(sender()) ) { addToHistory( (QLanguageItem*)sender() ); } updateWindowState(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::focusChanged( QWidget * old, QWidget * ) { if ( !old ) { QLanguageItem::checkAllFiles(); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::bringForward() { QLanguageItem* languageItem = dynamic_cast(sender()); if ( !languageItem ) languageItem = mFirstSelectedItem; if ( !languageItem ) return; int index = mZOrderedItems.indexOf( languageItem ); mZOrderedItems.move( index , MIN(mZOrderedItems.size() - 1 , index + 1) ); updateZOrders(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::sendBackward() { QLanguageItem* languageItem = dynamic_cast(sender()); if ( !languageItem ) languageItem = mFirstSelectedItem; if ( !languageItem ) return; int index = mZOrderedItems.indexOf( languageItem ); mZOrderedItems.move( index , MAX(0,index - 1) ); updateZOrders(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::bringToFront() { QLanguageItem* languageItem = dynamic_cast(sender()); if ( !languageItem ) languageItem = mFirstSelectedItem; if ( !languageItem ) return; int index = mZOrderedItems.indexOf( languageItem ); mZOrderedItems.move( index , mZOrderedItems.size() - 1 ); updateZOrders(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::sendToBack() { QLanguageItem* languageItem = dynamic_cast(sender()); if ( !languageItem ) languageItem = mFirstSelectedItem; if ( !languageItem ) return; int index = mZOrderedItems.indexOf( languageItem ); mZOrderedItems.move( index , 0 ); updateZOrders(); } //-----------------------------------------------------------------------// // Private functions // //-----------------------------------------------------------------------// //----------------------------------------------------------------------- void GraphicsSceneMainWindow::checkSettings() { QSettings settings("grame.fr", "FaustWorks"); if ( !settings.value( INIT_DONE_SETTING ).toBool() ) { reinitSettings(); } //Update dependencies. readSettings(); } /*! * \brief Reads last application's settings, using Qt's QSetting system. */ //------------------------------------------------------------------------- void GraphicsSceneMainWindow::readSettings() { readPreferencesSettings(); QSettings settings("grame.fr", "FaustWorks"); // Font size for QTextEdits changeFontSize( settings.value( FONT_SIZE_SETTING ).toDouble() ); // Window position & size QPoint pos = settings.value(WINDOW_POS_SETTING , DEFAULT_WINDOW_POS ).toPoint(); QSize size = settings.value(WINDOW_SIZE_SETTING , QSize(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT) ).toSize(); resize(size); move(pos); // Dockwidgets & toolbars status (see QMainWindow::restoreState) QByteArray state = settings.value( WINDOW_STATE_SETTING ).toByteArray(); restoreState( state ); // Side history/storage bars visibility (those are not DockWidgets and thus must be managed manually). if ( mSettings.mHasStorage ) { mStorageGraphicsView->setVisible( settings.value( STORAGE_VISIBLE_SETTING , true ).toBool() ); } if ( mSettings.mHasHistory ) { mHistoryGraphicsView->setVisible( settings.value( HISTORY_VISIBLE_SETTING , true ).toBool() ); } // Current graphicView zoom. zoom( (float)settings.value( WINDOW_ZOOM_SETTING , 1.0f ).toDouble() ); // Current scene ( <=> workspace ) QString currentScene = settings.value( CURRENT_SCENE_SETTING ).toString(); if ( mIsWorkspaceModeOn ) { if ( !loadSceneFile( currentScene ) ) { QString msg; if ( currentScene.size() != 0 ) msg = tr("Can't load the scene %1. ").arg(currentScene); msg += tr("Choose the path of your new 'workspace' scene."); QMessageBox::warning(this , tr("Workspace scene"), msg); saveSceneAs(); } } // Last openned file mLastOpenFilePath = settings.value( FILE_DIALOG_PATH_SETTING ).toString(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::readPreferencesSettings() { QSettings settings("grame.fr", "FaustWorks"); // Workspace mode on/off // mIsWorkspaceModeOn = settings.value( WORKSPACE_MODE_SETTING ).toBool(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::createActions() { mNewAct = new QAction(QIcon( RSC_DIR + QString("new.png") ), tr("&New scene") , this); mNewAct->setShortcut( QKeySequence::New ); mNewAct->setStatusTip(tr("Create a new scene")); if ( !mSettings.mDesactiveUIElements.contains( NEW_ACT ) ) connect(mNewAct , SIGNAL(triggered()) , this , SLOT(newScene()) ); mSaveAct = new QAction(QIcon(RSC_DIR + QString("save.png")), tr("&Save item or scene") , this); mSaveAct->setShortcut( QKeySequence::Save ); mSaveAct->setStatusTip(tr("Save the current item or the current scene")); if ( !mSettings.mDesactiveUIElements.contains( SAVE_ACT ) ) connect(mSaveAct , SIGNAL(triggered()) , this , SLOT(save()) ); mSaveAsAct = new QAction(QIcon(RSC_DIR + QString("save.png")), tr("&Save scene as...") , this); mSaveAsAct->setStatusTip(tr("Save the current scene to another file")); if ( !mSettings.mDesactiveUIElements.contains( SAVE_AS_ACT ) ) connect(mSaveAsAct , SIGNAL(triggered()) , this , SLOT(saveSceneAs()) ); mSaveAllAct = new QAction(QIcon(RSC_DIR + QString("saveAll.png")), tr("Save All") , this); mSaveAllAct->setStatusTip( "Save all items & scene" ); if ( !mSettings.mDesactiveUIElements.contains( SAVE_ALL_ACT ) ) connect(mSaveAllAct , SIGNAL(triggered()) , this , SLOT(saveAll()) ); mOpenAct = new QAction(QIcon(RSC_DIR + QString("open.png")), tr("&Open scene...") , this); mOpenAct->setShortcut( QKeySequence::Open ); mOpenAct->setStatusTip(tr("Open a scene")); if ( !mSettings.mDesactiveUIElements.contains( OPEN_ACT ) ) connect(mOpenAct , SIGNAL(triggered()) , this , SLOT(loadScene()) ); mExitAct = new QAction(tr("E&xit"), this); mExitAct->setShortcut(tr("Ctrl+Q")); mExitAct->setStatusTip(tr("Exit the application")); if ( !mSettings.mDesactiveUIElements.contains( EXIT_ACT ) ) connect(mExitAct, SIGNAL(triggered()), this, SLOT(close())); mAboutQtAct = new QAction(tr("About &Qt"), this); mAboutQtAct->setStatusTip(tr("Show the Qt library's About box")); if ( !mSettings.mDesactiveUIElements.contains( ABOUT_QT_ACT ) ) connect(mAboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); mZoomInAct = new QAction(QIcon(RSC_DIR + QString("zoomIn.png")), tr("Zoom &In") , this); mZoomInAct->setShortcut( QKeySequence::ZoomIn ); mZoomInAct->setStatusTip(tr("Zoom in")); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_IN_ACT ) ) connect(mZoomInAct , SIGNAL(triggered()) , this , SLOT(zoomIn()) ); mZoomOutAct = new QAction(QIcon(RSC_DIR + QString("zoomOut.png")), tr("Zoom O&ut") , this); mZoomOutAct->setShortcut( QKeySequence::ZoomOut); mZoomOutAct->setStatusTip(tr("Zoom out")); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_OUT_ACT ) ) connect(mZoomOutAct , SIGNAL(triggered()) , this , SLOT(zoomOut()) ); mZoomStandardAct = new QAction( tr("Zoom 100%") , this); mZoomStandardAct->setStatusTip(tr("Zoom 100%")); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_STANDARD_ACT ) ) connect(mZoomStandardAct , SIGNAL(triggered()) , this , SLOT(zoomStandard()) ); mFontBiggerAct = new QAction(QIcon(RSC_DIR + QString("fontBigger.png")), tr("Font bigger") , this); mFontBiggerAct->setShortcut( tr("Ctrl+Shift+Plus") ); mFontBiggerAct->setStatusTip(tr("Font bigger")); if ( !mSettings.mDesactiveUIElements.contains( FONT_BIGGER_ACT ) ) connect(mFontBiggerAct , SIGNAL(triggered()) , this , SLOT(fontBigger()) ); mFontSmallerAct = new QAction(QIcon(RSC_DIR + QString("fontSmaller.png")), tr("Font smaller") , this); mFontSmallerAct->setShortcut( tr("Ctrl+Shift+Minus") ); mFontSmallerAct->setStatusTip(tr("Font smaller")); if ( !mSettings.mDesactiveUIElements.contains( FONT_SMALLER_ACT ) ) connect(mFontSmallerAct , SIGNAL(triggered()) , this , SLOT(fontSmaller()) ); mAddAct = new QAction(QIcon(RSC_DIR + QString("add.png")), tr("Add &item") , this); mAddAct->setShortcut( tr("Ctrl+I") ); mAddAct->setStatusTip("Add a new " + LANGUAGE_NAME_SHORT + " item"); if ( !mSettings.mDesactiveUIElements.contains( ADD_ACT ) ) connect(mAddAct , SIGNAL(triggered()) , this , SLOT(addItem()) ); mAddFromFileAct = new QAction(QIcon(RSC_DIR + QString("addFromFile.png")), tr("Add item from file...") , this); mAddFromFileAct->setShortcut( tr("Ctrl+Shift+O") ); mAddFromFileAct->setStatusTip("Add a new " + LANGUAGE_NAME_SHORT + " item from a file"); if ( !mSettings.mDesactiveUIElements.contains( ADD_FROM_FILE_ACT ) ) connect(mAddFromFileAct , SIGNAL(triggered()) , this , SLOT(addItemFromFile()) ); mRemoveAct = new QAction(QIcon(RSC_DIR + QString("remove.png")), tr("Remove items") , this); mRemoveAct->setShortcut( QKeySequence::Delete); mRemoveAct->setStatusTip("Remove the selected " + LANGUAGE_NAME_SHORT + " items"); if ( !mSettings.mDesactiveUIElements.contains( REMOVE_ACT ) ) connect(mRemoveAct , SIGNAL(triggered()) , this , SLOT(removeSelectedItems()) ); mCopyAct = new QAction(QIcon(RSC_DIR + QString("copy.png")), tr("&Copy") , this); mCopyAct->setShortcut( QKeySequence::Copy); mCopyAct->setStatusTip("Copy the selected " + LANGUAGE_NAME_SHORT + " items"); if ( !mSettings.mDesactiveUIElements.contains( COPY_ACT ) ) connect(mCopyAct , SIGNAL(triggered()) , this , SLOT(copyItem()) ); mPasteAct = new QAction(QIcon(RSC_DIR + QString("paste.png")), tr("&Paste") , this); mPasteAct->setShortcut( QKeySequence::Paste); mPasteAct->setStatusTip(tr("Paste previously copied items")); if ( !mSettings.mDesactiveUIElements.contains( PASTE_ACT ) ) connect(mPasteAct , SIGNAL(triggered()) , this , SLOT(pasteItem()) ); mCleanHistoryAct = new QAction(QIcon(), tr("Clean history") , this); mCleanHistoryAct->setStatusTip(tr("Clean your history side bar")); if ( !mSettings.mDesactiveUIElements.contains( CLEAN_HISTORY_ACT ) ) connect(mCleanHistoryAct , SIGNAL(triggered()) , this , SLOT(cleanHistory()) ); mSelectAllAct = new QAction(QIcon(), tr("Select &All") , this); mSelectAllAct->setShortcut( QKeySequence::SelectAll); mSelectAllAct->setStatusTip(tr("Select all the items")); if ( !mSettings.mDesactiveUIElements.contains( SELECT_ALL_ACT ) ) connect(mSelectAllAct , SIGNAL(triggered()) , this , SLOT(selectAll()) ); mRescaleAct = new QAction(QIcon(RSC_DIR + QString("resize.png")), tr("&Rescale") , this); mRescaleAct->setShortcut( tr("Ctrl+R") ); mRescaleAct->setStatusTip(tr("Set the scale of all selected items to the scale of the first selected one")); if ( !mSettings.mDesactiveUIElements.contains( RESCALE_ACT ) ) connect(mRescaleAct , SIGNAL(triggered()) , this , SLOT(resizeItems()) ); mHAlignAct = new QAction(QIcon(RSC_DIR + QString("hAlign.png")), tr("&Horizontal alignment") , this); mHAlignAct->setShortcut( tr("Ctrl+H") ); mHAlignAct->setStatusTip(tr("Horizontally align all selected items on the first selected one")); if ( !mSettings.mDesactiveUIElements.contains( H_ALIGN_ACT ) ) connect(mHAlignAct , SIGNAL(triggered()) , this , SLOT(hAlignItems()) ); mVAlignAct = new QAction(QIcon(RSC_DIR + QString("vAlign.png")), tr("Ver&tical alignment") , this); mVAlignAct->setShortcut( tr("Ctrl+T") ); mVAlignAct->setStatusTip(tr("Vertically align all selected items on the first selected one")); if ( !mSettings.mDesactiveUIElements.contains( V_ALIGN_ACT ) ) connect(mVAlignAct , SIGNAL(triggered()) , this , SLOT(vAlignItems()) ); mBringToFrontAct = new QAction(QIcon(RSC_DIR + QString("bringToFront.png")), tr("Bring to front") , this); mBringToFrontAct->setStatusTip(tr("Brings the first selected item to front")); if ( !mSettings.mDesactiveUIElements.contains( BRING_TO_FRONT_ACT ) ) connect(mBringToFrontAct , SIGNAL(triggered()) , this , SLOT(bringToFront()) ); mBringForwardAct = new QAction(QIcon(RSC_DIR + QString("bringForward.png")), tr("Bring forward") , this); mBringForwardAct->setStatusTip(tr("Brings the first selected item forward")); if ( !mSettings.mDesactiveUIElements.contains( BRING_FORWARD_ACT ) ) connect(mBringForwardAct , SIGNAL(triggered()) , this , SLOT(bringForward()) ); mSendToBackAct = new QAction(QIcon(RSC_DIR + QString("sendToBack.png")), tr("Send to back") , this); mSendToBackAct->setStatusTip(tr("Sends the first selected item to back")); if ( !mSettings.mDesactiveUIElements.contains( SEND_TO_BACK_ACT ) ) connect(mSendToBackAct , SIGNAL(triggered()) , this , SLOT(sendToBack()) ); mSendBackwardAct = new QAction(QIcon(RSC_DIR + QString("sendBackward.png")), tr("Send backward") , this); mSendBackwardAct->setStatusTip(tr("Sends the first selected item backward")); if ( !mSettings.mDesactiveUIElements.contains( SEND_BACKWARD_ACT ) ) connect(mSendBackwardAct , SIGNAL(triggered()) , this , SLOT(sendBackward()) ); mSwitchHistoryVisible = 0; mSwitchStorageVisible = 0; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::createMenus() { if ( !mSettings.mDesactiveUIElements.contains( FILE_MENU ) ) { mFileMenu = menuBar()->addMenu(tr("&File")); if ( !mSettings.mDesactiveUIElements.contains( NEW_ACT ) ) mFileMenu->addAction(mNewAct); if ( !mSettings.mDesactiveUIElements.contains( OPEN_ACT ) ) mFileMenu->addAction(mOpenAct); if ( !mSettings.mDesactiveUIElements.contains( SAVE_ACT ) ) mFileMenu->addAction(mSaveAct); if ( !mSettings.mDesactiveUIElements.contains( SAVE_AS_ACT ) ) mFileMenu->addAction(mSaveAsAct); if ( !mSettings.mDesactiveUIElements.contains( SAVE_ALL_ACT ) ) mFileMenu->addAction(mSaveAllAct); if ( !mSettings.mDesactiveUIElements.contains( EXIT_ACT ) ) mFileMenu->addAction(mExitAct); } if ( !mSettings.mDesactiveUIElements.contains( EDIT_MENU ) ) { mEditMenu = menuBar()->addMenu(tr("&Edit")); if ( !mSettings.mDesactiveUIElements.contains( ADD_ACT ) ) mEditMenu->addAction(mAddAct); if ( !mSettings.mDesactiveUIElements.contains( ADD_FROM_FILE_ACT ) ) mEditMenu->addAction(mAddFromFileAct); if ( !mSettings.mDesactiveUIElements.contains( REMOVE_ACT ) ) mEditMenu->addAction(mRemoveAct); mEditMenu->addSeparator(); if ( !mSettings.mDesactiveUIElements.contains( CLEAN_HISTORY_ACT ) ) mEditMenu->addAction( mCleanHistoryAct ); mEditMenu->addSeparator(); if ( !mSettings.mDesactiveUIElements.contains( SELECT_ALL_ACT ) ) mEditMenu->addAction( mSelectAllAct ); if ( !mSettings.mDesactiveUIElements.contains( COPY_ACT ) ) mEditMenu->addAction(mCopyAct); if ( !mSettings.mDesactiveUIElements.contains( PASTE_ACT ) ) mEditMenu->addAction(mPasteAct); mEditMenu->addSeparator(); if ( !mSettings.mDesactiveUIElements.contains( RESCALE_ACT ) ) mEditMenu->addAction( mRescaleAct ); if ( !mSettings.mDesactiveUIElements.contains( H_ALIGN_ACT ) ) mEditMenu->addAction(mHAlignAct); if ( !mSettings.mDesactiveUIElements.contains( V_ALIGN_ACT ) ) mEditMenu->addAction(mVAlignAct); mEditMenu->addSeparator(); if ( !mSettings.mDesactiveUIElements.contains( BRING_TO_FRONT_ACT ) ) mEditMenu->addAction( mBringToFrontAct ); if ( !mSettings.mDesactiveUIElements.contains( BRING_FORWARD_ACT ) ) mEditMenu->addAction( mBringForwardAct ); if ( !mSettings.mDesactiveUIElements.contains( SEND_BACKWARD_ACT ) ) mEditMenu->addAction( mSendBackwardAct ); if ( !mSettings.mDesactiveUIElements.contains( SEND_TO_BACK_ACT ) ) mEditMenu->addAction( mSendToBackAct ); } if ( !mSettings.mDesactiveUIElements.contains( VIEW_MENU ) ) { mViewMenu = menuBar()->addMenu(tr("&View")); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_IN_ACT ) ) mViewMenu->addAction(mZoomInAct); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_OUT_ACT ) ) mViewMenu->addAction(mZoomOutAct); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_STANDARD_ACT ) ) mViewMenu->addAction(mZoomStandardAct); if ( !mSettings.mDesactiveUIElements.contains( FONT_BIGGER_ACT ) ) mViewMenu->addAction(mFontBiggerAct); if ( !mSettings.mDesactiveUIElements.contains( FONT_SMALLER_ACT ) ) mViewMenu->addAction(mFontSmallerAct); } if ( !mSettings.mDesactiveUIElements.contains( HELP_MENU ) ) { mHelpMenu = menuBar()->addMenu(tr("&About")); if ( !mSettings.mDesactiveUIElements.contains( ABOUT_QT_ACT ) ) mHelpMenu->addAction(mAboutQtAct); } if ( !mSettings.mDesactiveUIElements.contains( WINDOW_MENU ) ) { mWindowMenu = createPopupMenu(); mWindowMenu->setTitle( tr("&Window") ); menuBar()->addMenu( mWindowMenu ); connect( mWindowMenu , SIGNAL( aboutToShow() ) , this , SLOT( updateWindowMenu() ) ); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::createToolBars() { if ( !mSettings.mDesactiveUIElements.contains( FILE_TOOL_BAR ) ) { mFileToolBar = addToolBar(tr("&File")); if ( !mSettings.mDesactiveUIElements.contains( NEW_ACT ) ) mFileToolBar->addAction(mNewAct); if ( !mSettings.mDesactiveUIElements.contains( OPEN_ACT ) ) mFileToolBar->addAction(mOpenAct); if ( !mSettings.mDesactiveUIElements.contains( SAVE_ACT ) ) mFileToolBar->addAction(mSaveAct); if ( !mSettings.mDesactiveUIElements.contains( SAVE_ALL_ACT ) ) mFileToolBar->addAction(mSaveAllAct); mFileToolBar->addSeparator(); mFileToolBar->setObjectName("FileToolBar"); } if ( !mSettings.mDesactiveUIElements.contains( EDIT_TOOL_BAR ) ) { mEditToolBar = addToolBar(tr("Edit")); if ( !mSettings.mDesactiveUIElements.contains( ADD_ACT ) ) mEditToolBar->addAction(mAddAct); if ( !mSettings.mDesactiveUIElements.contains( ADD_FROM_FILE_ACT ) ) mEditToolBar->addAction(mAddFromFileAct); if ( !mSettings.mDesactiveUIElements.contains( REMOVE_ACT ) ) mEditToolBar->addAction(mRemoveAct); if ( !mSettings.mDesactiveUIElements.contains( COPY_ACT ) ) mEditToolBar->addAction(mCopyAct); if ( !mSettings.mDesactiveUIElements.contains( PASTE_ACT ) ) mEditToolBar->addAction(mPasteAct); mEditToolBar->addSeparator(); mEditToolBar->setObjectName("EditToolBar"); } if ( !mSettings.mDesactiveUIElements.contains( VIEW_TOOL_BAR ) ) { mViewToolBar = addToolBar(tr("View")); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_IN_ACT ) ) mViewToolBar->addAction(mZoomInAct); if ( !mSettings.mDesactiveUIElements.contains( ZOOM_OUT_ACT ) ) mViewToolBar->addAction(mZoomOutAct); if ( !mSettings.mDesactiveUIElements.contains( FONT_BIGGER_ACT ) ) mViewToolBar->addAction(mFontBiggerAct); if ( !mSettings.mDesactiveUIElements.contains( FONT_SMALLER_ACT ) ) mViewToolBar->addAction(mFontSmallerAct); mViewToolBar->addSeparator(); mViewToolBar->setObjectName("ViewToolBar"); } mResizeSlider = new QSlider(Qt::Horizontal); mResizeSlider->setRange( -1 * SLIDER_PRECISION_FACTOR , 1 * SLIDER_PRECISION_FACTOR ); mResizeSlider->setValue( 0 ); mResizeSlider->setMaximumWidth( width() / 10 + SLIDER_TOOL_BAR_MARGIN ); mResizeSlider->setMinimumWidth( width() / 10 + SLIDER_TOOL_BAR_MARGIN ); mResizeSlider->setStatusTip(tr("Resize the selected items")); connect(mResizeSlider , SIGNAL(valueChanged(int)) , this , SLOT(resizeSliderChanged(int)) ); mResizeEdit = new QDoubleSpinBox(); mResizeEdit->setRange( mSettings.mMinScale , mSettings.mMaxScale ); mResizeEdit->setDecimals(2); mResizeEdit->setValue(1); mResizeEdit->setSingleStep( 0.1f ); mResizeEdit->setAccelerated( true); mResizeEdit->setStatusTip(tr("Resize the selected items")); connect( mResizeEdit , SIGNAL(valueChanged(double)) , this , SLOT(scaleItems(double)) ); mItemXEdit = new QDoubleSpinBox(); mItemXEdit->setRange( -MAX_COORDINATE_EDIT , MAX_COORDINATE_EDIT ); mItemXEdit->setStatusTip(tr("Change the abscissa of the selected item")); mItemXEdit->setAccelerated( true); connect( mItemXEdit , SIGNAL(valueChanged(double)) , this , SLOT(moveItemX(double)) ); mItemYEdit = new QDoubleSpinBox(); mItemYEdit->setRange( -MAX_COORDINATE_EDIT , MAX_COORDINATE_EDIT ); mItemYEdit->setStatusTip(tr("Change the ordinate of the selected item")); mItemYEdit->setAccelerated( true); connect( mItemYEdit , SIGNAL(valueChanged(double)) , this , SLOT(moveItemY(double)) ); if ( !mSettings.mDesactiveUIElements.contains( SIZE_TOOL_BAR ) ) { mSizeToolBar = addToolBar(tr("Scale && position")); if ( !mSettings.mDesactiveUIElements.contains( RESCALE_ACT ) ) mSizeToolBar->addAction( mRescaleAct ); if ( !mSettings.mDesactiveUIElements.contains( RESIZE_SLIDER ) ) { mSizeToolBar->addWidget( mResizeSlider ); mResizeSlider->setParent(mSizeToolBar); } if ( !mSettings.mDesactiveUIElements.contains( RESIZE_EDIT ) ) { mSizeToolBar->addWidget( mResizeEdit ); mResizeEdit->setParent(mSizeToolBar); } mSizeToolBar->addSeparator(); if ( !mSettings.mDesactiveUIElements.contains( H_ALIGN_ACT ) ) mSizeToolBar->addAction( mHAlignAct ); if ( !mSettings.mDesactiveUIElements.contains( V_ALIGN_ACT ) ) mSizeToolBar->addAction( mVAlignAct ); if ( !mSettings.mDesactiveUIElements.contains( X_ITEM_EDIT ) ) { mSizeToolBar->addWidget( new QLabel("X:" , mSizeToolBar) ); } if ( !mSettings.mDesactiveUIElements.contains( X_ITEM_EDIT ) ) { mSizeToolBar->addWidget( mItemXEdit ); mItemXEdit->setParent(mSizeToolBar); } if ( !mSettings.mDesactiveUIElements.contains( Y_ITEM_EDIT ) ) { mSizeToolBar->addWidget( new QLabel("Y:" , mSizeToolBar) ); } if ( !mSettings.mDesactiveUIElements.contains( Y_ITEM_EDIT ) ) { mSizeToolBar->addWidget( mItemYEdit ); mItemYEdit->setParent(mSizeToolBar); } mSizeToolBar->addSeparator(); mSizeToolBar->setObjectName("ScaleToolBar"); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::createStatusBar() { statusBar()->showMessage(tr("Ready")); mViewXLabel = new QLabel( "X = 0" , this); mViewXLabel->setMinimumWidth(75); mViewXLabel->setMaximumWidth(75); mViewXLabel->setAlignment(Qt::AlignLeft); mViewYLabel = new QLabel( "Y = 0" , this); mViewYLabel->setMinimumWidth(75); mViewYLabel->setMaximumWidth(75); mViewYLabel->setAlignment(Qt::AlignLeft); mViewScaleLabel = new QLabel( "Zoom = 1.0" , this); mViewScaleLabel->setMinimumWidth(100); mViewScaleLabel->setMaximumWidth(100); mViewScaleLabel->setAlignment(Qt::AlignLeft); if ( !mSettings.mDesactiveUIElements.contains( STATUS_BAR_MOUSE_POS ) ) statusBar()->addPermanentWidget( new QLabel("View: " , this) ); if ( !mSettings.mDesactiveUIElements.contains( STATUS_BAR_MOUSE_POS ) ) statusBar()->addPermanentWidget( mViewXLabel ); if ( !mSettings.mDesactiveUIElements.contains( STATUS_BAR_MOUSE_POS ) ) statusBar()->addPermanentWidget( mViewYLabel ); if ( !mSettings.mDesactiveUIElements.contains( STATUS_BAR_ZOOM ) ) statusBar()->addPermanentWidget( mViewScaleLabel ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::setupTextEdit() { mLanguageTextEdit = new LanguageTextEdit("" , this); mLanguageTextEdit->setAcceptRichText( false ); mLanguageTextEdit->setAcceptDrops( false ); mLanguageTextEditDock = new QDockWidget(GMN_EDIT_DOCK_NAME , this); mLanguageTextEditDock->setWidget( mLanguageTextEdit ); mLanguageTextEditDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable ); mLanguageTextEditDock->setObjectName( "LanguageTextEditDock" ); connect(mLanguageTextEdit,SIGNAL(cursorPositionChanged(void)),this,SLOT(textEditActivity(void))); connect(mLanguageTextEdit,SIGNAL(textChanged(void)),this,SLOT(textEditActivity(void))); connect(mLanguageTextEdit,SIGNAL(selectionChanged(void)),this,SLOT(textEditActivity(void))); addDockWidget( Qt::BottomDockWidgetArea , mLanguageTextEditDock ); // Setup GuidoItem refresh timer (update guidoItem render when code changes) mLanguageTextEditTimer = new QTimer( this ); connect( mLanguageTextEditTimer , SIGNAL( timeout() ) , this , SLOT( updateCode() ) ); if ( !LANGUAGE_COMMANDS_FILE.isEmpty() ) { QDockWidget * gmnPaletteDock = new QDockWidget(COMMAND_PALETTE_DOCK_NAME , this); QLanguageCommandPalette * gmnPalette = new QLanguageCommandPalette( LANGUAGE_COMMANDS_FILE , this); gmnPaletteDock->setWidget( gmnPalette ); gmnPaletteDock->setFeatures( QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable ); gmnPaletteDock->setVisible( true ); gmnPaletteDock->setFloating( true ); addDockWidget( Qt::BottomDockWidgetArea , gmnPaletteDock ); gmnPaletteDock->setObjectName( "languagePaletteDock" ); mCommandPaletteDock = gmnPaletteDock; connect( gmnPalette , SIGNAL( insertCode(const QString& , int) ) , this , SLOT( insertText( const QString& , int ) ) ); // connect( mLanguageTextEdit , SIGNAL( enabled(bool) ) , gmnPalette , SLOT( setEnabled(bool) ) ); } mLanguageTextEdit->setEnabled(false); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::createHistoryAndStorage() { if ( mSettings.mHasHistory ) { mHistoryGraphicsScene = new QGraphicsScene(this); mHistoryGraphicsView = new QHistoryGraphicsView( mHistoryGraphicsScene , mFactory ); } else mHistoryGraphicsView = 0; if ( mSettings.mHasStorage ) { mStorageGraphicsScene = new QGraphicsScene( this ); mStorageGraphicsView = new QStorageGraphicsView( mStorageGraphicsScene , this , mFactory ); } else { mStorageGraphicsView = 0; } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::reinitScene(QRectF sceneRect) { if ( mGraphicsScene == 0 ) { mGraphicsScene = new QGraphicsScene(this); connect(mGraphicsScene,SIGNAL(selectionChanged ()),this,SLOT(sceneSelectionChanged())); connect(mGraphicsScene,SIGNAL(changed( const QList& )),this,SLOT(sceneChanged( const QList &))); mGraphicsView->setScene( mGraphicsScene ); mBackgroundItem = new QBackgroundItem( this , QSizeF(sceneRect.width() , sceneRect.height()) ); // mBackgroundItem->setPos( sceneRect.x() , sceneRect.y() ); mBackgroundItem->setZValue( -1 ); mGraphicsScene->addItem( mBackgroundItem ); } else // Removes all languageItems. removeAllItems(); // mBackgroundItem->setPageSize( QSizeF(sceneRect.width() , sceneRect.height()) ); // mBackgroundItem->setPos( sceneRect.x() , sceneRect.y() ); mBackgroundItem->setRect( sceneRect ); if ( mSettings.mHasHistory ) mHistoryGraphicsView->clear(); if ( mSettings.mHasStorage ) mStorageGraphicsView->clear(); } /* * Shows the user a dialog with 3 choices : * - save : saves the scene and returns true * - don't save : doesn't save the scene and returns true * - cancel : doesn't save the scene and returns false * * If save isn't necessary (no changes detected), no dialog is shown, * returns true. */ //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::saveOrCancelDialog() { if ( ( !mSceneHasChanged ) || ( mGraphicsScene->items().size() == 0 ) ) return true; if ( !checkAllItems() ) return false; QMessageBox::StandardButton result = QMessageBox::question ( 0, "Save", "The scene has been modified. Would you like to save the current scene ?", QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Cancel ); if ( result != QMessageBox::Cancel ) { if ( result == QMessageBox::Yes ) saveScene(); return true; } else { return false; } } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::checkAllItems() { QList items = languageItems(); for ( int i = 0 ; i < items.size() ; i++ ) { if ( !saveItemModificationsDialog( items[i] ) ) return false; } return true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::saveScene() { QString savePath = windowFilePath(); if ( savePath == "" ) { saveSceneAs(); } else { saveSceneFile(savePath); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::saveSceneFile(const QString& fileName) { //Create & initialize a DomDocument QDomDocument doc( DOM_DOC + mSettings.mLanguageNameShort ); QDomElement root = doc.createElement( DOM_ROOT ); doc.appendChild( root ); //Add first element : Scene QPointF viewCenter = viewCenterInSceneCoordinate(); QDomElement element = doc.createElement( DOM_SCENE ); element.setAttribute( DOM_SCENE_X, mGraphicsScene->sceneRect().x() ); element.setAttribute( DOM_SCENE_Y, mGraphicsScene->sceneRect().y() ); element.setAttribute( DOM_SCENE_WIDTH, mGraphicsScene->sceneRect().width() ); element.setAttribute( DOM_SCENE_HEIGHT, mGraphicsScene->sceneRect().height() ); element.setAttribute( DOM_VIEW_X, viewCenter.x() ); element.setAttribute( DOM_VIEW_Y, viewCenter.y() ); element.setAttribute( DOM_VIEW_ZOOM, mGraphicsView->transform().m11() ); if ( mSettings.mHasStorage ) { QList splitterSizes = mSplitter->sizes(); element.setAttribute( DOM_SPLITTER_SIZE_0 , splitterSizes[0] ); element.setAttribute( DOM_SPLITTER_SIZE_1 , splitterSizes[1] ); } root.appendChild( element ); //Add 2nd element : storage if ( mSettings.mHasStorage ) root.appendChild( mStorageGraphicsView->save( doc ) ); //Add 3rd element : history if ( mSettings.mHasHistory ) root.appendChild( mHistoryGraphicsView->save( doc ) ); //Populate the DomDocument with the GuidoItems. QList items = languageItems(); for ( int i = 0 ; i < items.size() ; i++ ) { root.appendChild( items[i]->saveToDomElement(&doc) ); } QFile file(fileName); if (file.open(QFile::WriteOnly | QFile::Truncate)) { QTextStream ts( &file ); ts << doc.toString(); setWindowFilePath(fileName); mSceneHasChanged = false; } file.close(); QSettings("grame.fr", "FaustWorks").setValue( CURRENT_SCENE_SETTING, fileName ); } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::loadSceneFile(const QString& fileName) { QFile file( fileName ); if( !file.open( QFile::ReadOnly ) ) //Can't read file return false; //Create a new DomDocument with file contents QDomDocument doc( DOM_DOC + mSettings.mLanguageNameShort ); if( !doc.setContent( &file ) ) { file.close(); //File doesn't contain valid XML data return false; } file.close(); //Check the root QDomElement root = doc.documentElement(); if( root.tagName() != DOM_ROOT ) //No valid Guido-Root found. return false; //Read the first DomElement: scene float centerX; float centerY; QRectF sceneRect; QDomNode n = root.firstChild(); if ( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if( e.tagName() == DOM_SCENE ) { float sceneX = QVariant( e.attribute( DOM_SCENE_X, "" ) ).toDouble(); float sceneY = QVariant( e.attribute( DOM_SCENE_Y, "" ) ).toDouble(); float sceneWidth = QVariant( e.attribute( DOM_SCENE_WIDTH, "" ) ).toDouble(); float sceneHeight = QVariant( e.attribute( DOM_SCENE_HEIGHT, "" ) ).toDouble(); centerX = QVariant( e.attribute( DOM_VIEW_X, "" ) ).toDouble(); centerY = QVariant( e.attribute( DOM_VIEW_Y, "" ) ).toDouble(); float zoom = QVariant( e.attribute( DOM_VIEW_ZOOM, "" ) ).toDouble(); sceneRect.setX(sceneX); sceneRect.setY(sceneY); sceneRect.setWidth(sceneWidth); sceneRect.setHeight(sceneHeight); reinitScene(sceneRect); mGraphicsView->setTransform( QTransform() ); mGraphicsView->scale( zoom , zoom ); mGraphicsView->centerOn( centerX , centerY ); if ( mSettings.mHasStorage ) { int splitterSize0 = QVariant( e.attribute( DOM_SPLITTER_SIZE_0, "" ) ).toInt(); int splitterSize1 = QVariant( e.attribute( DOM_SPLITTER_SIZE_1, "" ) ).toInt(); mSplitter->setSizes( QList() << splitterSize0 << splitterSize1 ); } } } } n = n.nextSibling(); //Load storage if ( mSettings.mHasStorage ) { if( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if( e.tagName() == mStorageGraphicsView->domId() ) { if ( !mStorageGraphicsView->load( e ) ) return false; } } } n = n.nextSibling(); } //Load history if ( mSettings.mHasHistory ) { if( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if( e.tagName() == mHistoryGraphicsView->domId() ) { if ( !mHistoryGraphicsView->load( e ) ) return false; } } } n = n.nextSibling(); } //Create the Guido Items while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { QLanguageItem * i = mFactory->buildLanguageItem(&e); if ( fileControl(i) ) setupNAddItem(i); } n = n.nextSibling(); } setWindowFilePath(fileName); QSettings("grame.fr", "FaustWorks").setValue( CURRENT_SCENE_SETTING , fileName ); updateWindowState(); updateZoomLabel(); mSceneHasChanged = false; return true; } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::dropItem( const QMimeData * mimeData , const QPointF& pos , QLanguageItem** createdItem ) { // mGraphicsView->setFocus(); //Drop a/several file(s) from outside the application. if ( mimeData->hasUrls() && !mimeData->hasFormat( FROM_SCENE_DRAG_MIME ) && !mimeData->hasFormat( FROM_HISTORY_DRAG_MIME ) && !mimeData->hasFormat( FROM_STORAGE_DRAG_MIME ) ) { int dx = 0; //Unselect all unselectAll(); //Drop several files at a time for ( int i = 0 ; i < mimeData->urls().size() ; i++ ) { //Create an item for each dropped file QString fileName = mimeData->urls()[i].toLocalFile(); if ( !addFile( fileName , createdItem ) ) return false; else { //Move each new item a the right border of the previously added item, to put them //in an horizontal line. QRectF itemRect = (*createdItem)->boundingRect(); if ( i==0 ) dx -= itemRect.width() / 2; dx += itemRect.width() / 2 + 1; (*createdItem)->setPos( pos.x() - itemRect.width() /2 + dx , pos.y() - itemRect.height()/2 ); dx += itemRect.width() / 2 + 1; //Each dropped item is selected (*createdItem)->setSelected(true); } } return true; } //Drop an item from within the application (storage/history bars, or copying an item inside the //main scene). else if ( ( mimeData->hasFormat(FROM_STORAGE_DRAG_MIME) ) || ( mimeData->hasFormat(FROM_SCENE_DRAG_MIME) ) || ( mimeData->hasFormat(FROM_HISTORY_DRAG_MIME) ) ) { (*createdItem) = mFactory->buildLanguageItem(mimeData); /* setupNAddItem(*createdItem); QRectF itemRect = (*createdItem)->boundingRect(); if ( ( mimeData->hasFormat(FROM_STORAGE_DRAG_MIME) ) || ( mimeData->hasFormat(FROM_SCENE_DRAG_MIME) ) || ( mimeData->hasFormat(FROM_HISTORY_DRAG_MIME) ) ) { (*createdItem)->moveBy( -itemRect.width()/2.0f , -itemRect.height()/2.0f ); } */ setupNAddNewItem( *createdItem ); (*createdItem)->moveBy( pos.x() , pos.y() ); unselectAll(); (*createdItem)->setSelected(true); return true; } return false; } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::addFile( const QString &fileName , QLanguageItem** createdItem) { if ( QFile::exists( fileName ) ) { setLastManagedFile( fileName ); return addLanguageItem( fileName , true , createdItem ); } else return false; } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::addCode(const QString &gmnCode , QLanguageItem** createdItem) { return addLanguageItem( gmnCode , false , createdItem ); } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::addLanguageItem(const QString &gmnSource, bool sourceIsAFile , QLanguageItem** createdItem) { statusBar()->showMessage( "Loading " + mSettings.mLanguageNameShort + " code..." ); QApplication::setOverrideCursor(Qt::WaitCursor); //Create a new QLanguageItem. QLanguageItem * languageItem; if ( sourceIsAFile ) { languageItem = mFactory->buildLanguageItemFromFile( gmnSource ); if ( !fileControl( languageItem ) ) return false; } else { languageItem = mFactory->buildLanguageItemFromCode( gmnSource ); } setupNAddNewItem( languageItem ); if ( createdItem != 0 ) (*createdItem) = languageItem; return languageItem->isValid(); } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::fileControl(QLanguageItem* languageItem) { if ( languageItem->fileNotFound() ) { unselectAll(); languageItem->setSelected( true ); QMessageBox::StandardButton result = QMessageBox::warning ( this, "File not found", "Can't open file \"" + languageItem->file() + "\". Find it ?", QMessageBox::Yes | QMessageBox::Ignore , QMessageBox::Yes ); if ( result == QMessageBox::Yes ) { QString newFile = findFile( languageItem->file() ); if ( QFile::exists(newFile) ) { languageItem->loadFile( newFile ); return true; } } delete languageItem; return false; } return true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::setupNAddItem(QLanguageItem* languageItem) { //Adds the languageItem at its correct place in the mZOrderedItems list. //Fill with 0. while ( mZOrderedItems.size() <= languageItem->zValue() ) mZOrderedItems << 0; //Replace if the corresponding place is free ( mZOrderedItems[zValue] = 0 ). if ( mZOrderedItems[int(languageItem->zValue())] == 0 ) mZOrderedItems.replace( languageItem->zValue() , languageItem ); else //There is already an item with this ZValue : { //insert the item mZOrderedItems.insert( languageItem->zValue() , languageItem ); //Updates all the items zValue acording to their index in mZOrderedItems list. updateZOrders(); } languageItem->setFlags( QGraphicsItem::ItemIsSelectable ); languageItem->setMimeId( FROM_SCENE_DRAG_MIME ); if ( mSettings.mHasStorage ) { QLanguageItemAction * storeAct = new QLanguageItemAction( languageItem , "Store" ); connect( storeAct , SIGNAL(triggered(QLanguageItem*)) , this , SLOT(storeItem(QLanguageItem*)) ); } connect( languageItem , SIGNAL( saveItemAs() ) , this , SLOT( saveItemAs() ) ); connect( languageItem , SIGNAL( fileChanged(bool) ) , this , SLOT( fileChanged(bool) ) ); connect( languageItem , SIGNAL( descriptiveNameChanged() ) , this , SLOT( descriptiveNameChanged() ) ); connect( languageItem , SIGNAL( itemHasBeenReloaded() ) , this , SLOT( itemHasBeenReloaded() ) ); connect( languageItem , SIGNAL( bringToFront() ) , this , SLOT( bringToFront() ) ); connect( languageItem , SIGNAL( bringForward() ) , this , SLOT( bringForward() ) ); connect( languageItem , SIGNAL( sendBackward() ) , this , SLOT( sendBackward() ) ); connect( languageItem , SIGNAL( sendToBack() ) , this , SLOT( sendToBack() ) ); plugResizer( languageItem ); connect( languageItem , SIGNAL(scaleChanged(float) ) , this , SLOT(scaleChanged( float )) ); connect( languageItem , SIGNAL(removed()) , this , SLOT( itemRemoved() ) ); //Add the item and its QLanguageItem to the scene mGraphicsScene->addItem( languageItem ); QApplication::restoreOverrideCursor(); if ( languageItem->isValid() ) { statusBar()->showMessage( tr("%1 Code Ok").arg(GraphicsSceneMainWindow::mSettings.mLanguageName) ); addToHistory( languageItem ); } else { statusBar()->showMessage( languageItem->lastErrorMessage() ); } mSceneHasChanged = true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::setupItemFromMenu(QLanguageItem* decorator) { QPointF viewCenter = viewCenterInSceneCoordinate(); decorator->moveBy( viewCenter.x() , viewCenter.y() ); unselectAll(); decorator->setSelected(true); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::setupNAddNewItem(QLanguageItem* languageItem) { //Reduce the item if too large, if a valid mSettings.mMaxItemSize is defined. float widthFactor = 1.0f , heightFactor = 1.0f; if ( ( mSettings.mMaxItemSize.height() > 0 ) && ( mSettings.mMaxItemSize.width() > 0 ) ) { if ( languageItem->boundingRect().width() > mSettings.mMaxItemSize.width() ) { widthFactor = mSettings.mMaxItemSize.width() / languageItem->boundingRect().width(); } if ( languageItem->boundingRect().height() > mSettings.mMaxItemSize.height() ) { heightFactor = mSettings.mMaxItemSize.height() / languageItem->boundingRect().height(); } float factor = MIN( widthFactor , heightFactor ); if ( factor < 1.0f ) { QRectF baseR = languageItem->boundingRect(); QRectF r( 0,0, baseR.width() * factor , baseR.height() * factor ); languageItem->resized( r ); } } //Set Z on the top. languageItem->setZValue( mZOrderedItems.size() ); setupNAddItem(languageItem); //Center the graphicsItem QRectF boundingRect = languageItem->sceneBoundingRect(); languageItem->moveBy( -boundingRect.width() / 2 , -boundingRect.height() / 2 ); } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::removeItem(QLanguageItem * item ) { if ( !saveItemModificationsDialog(item) ) { return false; } itemRemoved( item ); delete item; return true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::removeAllItems() { // Delete all the items QList items = languageItems(); for ( int i = 0 ; i < items.size() ; i++ ) { itemRemoved(items[i]); delete items[i]; } updateWindowState(); } //------------------------------------------------------------------------- // Returns false if cancelled. bool GraphicsSceneMainWindow::saveItemModificationsDialog(QLanguageItem * item) { bool fileExists = QFile::exists( item->file() ); if ( ( item->file().length() > 0 ) && ( item->isModified() || !fileExists ) ) { unselectAll(); item->setSelected( true ); QString dialogText = ( fileExists ) ? tr("%1 has changed. Save modifications ?").arg(item->file()) : tr("%1 doesn't exist. Re-save item ?").arg(item->file()) ; QMessageBox::StandardButton result = QMessageBox::warning ( this, tr("Save item"), dialogText, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel , QMessageBox::Yes ); if ( result == QMessageBox::Yes ) { item->saveItem(); } else if ( result == QMessageBox::No ) { //Do nothing. } else { return false; } } return true; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::saveItemAs(QLanguageItem * languageItem) { QString savePath = ""; if ( languageItem->file().length() > 0 ) savePath = QFileInfo( languageItem->file() ).absolutePath(); if ( savePath == "" ) savePath = getFileDialogPath(); savePath += "/" + languageItem->name(); QString filters = GMN_FILE_FILTER; QString selectedFilter(""); QString fileName = QFileDialog::getSaveFileName(this, tr("Save the %1 item").arg(LANGUAGE_NAME_SHORT), savePath, tr(filters.toAscii().data()) , &selectedFilter); if ( fileName.isEmpty() ) return; formatFileName(fileName,selectedFilter,filters); setLastManagedFile(fileName); languageItem->save( fileName ); } //------------------------------------------------------------------------- QList GraphicsSceneMainWindow::selectedLanguageItems() { QList selectedItems = mGraphicsScene->selectedItems(); QList result; for ( int i = 0 ; i < selectedItems.size() ; i++ ) { QLanguageItem* languageItem = dynamic_cast( selectedItems[i] ); if ( languageItem ) result.append( languageItem ); } return result; } //------------------------------------------------------------------------- QList GraphicsSceneMainWindow::languageItems() { QList items = mGraphicsScene->items(); QList result; for ( int i = 0 ; i < items.size() ; i++ ) { QLanguageItem* languageItem = dynamic_cast( items[i] ); if ( languageItem ) result.append( languageItem ); } return result; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::unselectAll() { while ( mGraphicsScene->selectedItems().size() > 0 ) { mGraphicsScene->selectedItems()[0]->setSelected( false ); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateWindowState() { QList selectedItems = selectedLanguageItems(); if ( selectedItems.size() > 0 ) { // If only one items is selected if ( selectedItems.size() == 1 ) { mFirstSelectedItem = selectedItems[0]; // mFirstSelectedItem->setZValue( mCurrentZOrderItem++ ); // Activate the text-edit when 1 item is selected only, mLanguageTextEdit->setEnabled(true); mLanguageTextEdit->setPlainText( mFirstSelectedItem->code() ); mLanguageTextEditDock->setWindowTitle( (mFirstSelectedItem->file().length() > 0 ) ? mFirstSelectedItem->getDescriptiveFileName() : GMN_EDIT_DOCK_NAME ); // Desactivate the resize action mRescaleAct->setEnabled(false); mHAlignAct->setEnabled(false); mVAlignAct->setEnabled(false); // Activate & update the x/y item position edit mItemXEdit->setEnabled( true ); mItemYEdit->setEnabled( true ); updateItemPositionControls( false ); } else // Several items are selected { if ( ( !mFirstSelectedItem ) || ( !mFirstSelectedItem->isSelected() ) ) mFirstSelectedItem = selectedItems[0]; // Desactivate the text-edit mLanguageTextEdit->setEnabled(false); mLanguageTextEdit->setText(""); mLanguageTextEditDock->setWindowTitle( GMN_EDIT_DOCK_NAME ); // Activate the resize/align actions mRescaleAct->setEnabled(true); mHAlignAct->setEnabled(true); mVAlignAct->setEnabled(true); // Desactivate the x/y item position edit mItemXEdit->setEnabled( false ); mItemYEdit->setEnabled( false ); } //Activate the scale-slider mResizeSlider->setEnabled( true ); mResizeEdit->setEnabled( true ); //Value of the scale-slider/edit according to the first item float scale = mFirstSelectedItem->currentScale(); updateScaleControls(scale); //Activate the copy, remove actions mCopyAct->setEnabled( true ); } else { mFirstSelectedItem = 0; // Desactivate the text-edit mLanguageTextEdit->setEnabled(false); mLanguageTextEdit->setText(""); mLanguageTextEditDock->setWindowTitle( GMN_EDIT_DOCK_NAME ); // Desactivate the scale-slider & resize action mResizeSlider->setEnabled( false ); mResizeEdit->setEnabled( false ); mResizeSlider->setValue( 0 ); // Desactivate the x/y position edit mItemXEdit->setEnabled( false ); mItemYEdit->setEnabled( false ); mRescaleAct->setEnabled(false); mHAlignAct->setEnabled(false); mVAlignAct->setEnabled(false); //Desactivate the copy, remove actions mCopyAct->setEnabled( false ); } if ( mCopiedItems.size() == 0 ) { //Desactivate paste action mPasteAct->setEnabled( false ); } else { //Activate paste action mPasteAct->setEnabled( true ); } updateRemoveActState(); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateScaleControls(double scale) { int value = ( log10(scale) * SLIDER_PRECISION_FACTOR ) + 0.5f; //+0.5f to round int->float disconnect(mResizeSlider , SIGNAL(valueChanged(int)) , this , SLOT(resizeSliderChanged(int)) ); disconnect(mResizeEdit , SIGNAL(valueChanged(double)) , this , SLOT(scaleItems(double)) ); mResizeSlider->setValue( value ); mResizeEdit->setValue( scale ); connect(mResizeSlider , SIGNAL(valueChanged(int)) , this , SLOT(resizeSliderChanged(int)) ); connect(mResizeEdit , SIGNAL(valueChanged(double)) , this , SLOT(scaleItems(double)) ); } /* * - Update the values shown in the X/Y position edits in the tool bar. * - (connectedToItem == false) means that we update the values displayed by * the edits without "back-modifying" the concerned item's position. */ //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateItemPositionControls(bool connectedToItem) { if ( !connectedToItem ) { disconnect( mItemXEdit , SIGNAL(valueChanged(double)) , this , SLOT(moveItemX(double)) ); disconnect( mItemYEdit , SIGNAL(valueChanged(double)) , this , SLOT(moveItemY(double)) ); } QList selectedItems = selectedLanguageItems(); if ( selectedItems.size() > 0 ) { mItemXEdit->setValue( mFirstSelectedItem->pos().x() ); mItemYEdit->setValue( mFirstSelectedItem->pos().y() ); } if ( !connectedToItem ) { connect( mItemXEdit , SIGNAL(valueChanged(double)) , this , SLOT(moveItemX(double)) ); connect( mItemYEdit , SIGNAL(valueChanged(double)) , this , SLOT(moveItemY(double)) ); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateCursorPos(QPointF pos) { QString xLabel , yLabel; QTextStream xStream(&xLabel); xStream.setRealNumberPrecision (5); xStream << "X=" << pos.x(); QTextStream yStream(&yLabel); yStream.setRealNumberPrecision (5); yStream << "Y=" << pos.y(); mViewXLabel->setText(xLabel); mViewYLabel->setText(yLabel); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateZoomLabel() { mViewScaleLabel->setText( getZoomLabel(mGraphicsView->transform().m11()) ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateRemoveActState() { mRemoveAct->setEnabled( ( mGraphicsScene->selectedItems().size() > 0 ) || ( ( mSettings.mHasStorage ) && ( mStorageGraphicsView->scene()->selectedItems().size() > 0 ) ) ); } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::updateZOrders() { for ( int i = 0 ; i < mZOrderedItems.size() ; i++ ) { if ( mZOrderedItems[i] ) mZOrderedItems[i]->setZValue( i ); } } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::addToHistory(QLanguageItem* item) { if ( mSettings.mHasHistory ) { if ( item->isValid() ) { if ( !mHistoryGraphicsView->find(item) ) mHistoryGraphicsView->addItem( mFactory->buildLanguageItem( item ) ); } } } //-----------------------------------------------------------------------// // Private UI events handlers // //-----------------------------------------------------------------------// //------------------------------------------------------------------------- void GraphicsSceneMainWindow::closeEvent(QCloseEvent *event) { if ( !checkAllItems() ) { unselectAll(); event->ignore(); } else { if ( mIsWorkspaceModeOn ) { QString currentScene = QSettings("grame.fr", "FaustWorks").value( CURRENT_SCENE_SETTING ).toString(); /* int version = 1; while ( QFile::exists( currentScene + "_V" + QVariant(version).toString() ) ) version++; */ QFileInfo fi(currentScene); QFile::rename( currentScene , fi.absolutePath() + "/~" + fi.fileName() ); saveSceneFile( currentScene ); } else { if ( !saveOrCancelDialog() ) { event->ignore(); return; } } writeSettings(); event->accept(); } } //------------------------------------------------------------------------- void putInFile( const QString& msg , const QString& fileName ) { QFile data(fileName); if (data.open(QFile::WriteOnly | QFile::Append | QFile::Text )) { QTextStream out(&data); out << msg << endl; } } //------------------------------------------------------------------------- bool GraphicsSceneMainWindow::eventFilter(QObject *obj, QEvent *e) { if (e->type() == QEvent::FileOpen) { e->accept(); QString fileName = ((QFileOpenEvent*)e)->file(); if ( !loadSceneFile( fileName ) ) addFile( fileName , 0 ); return true; } else if ( e->type() == QEvent::KeyPress ) { if ( ( !mResizeEdit->hasFocus() ) && ( !mItemXEdit->hasFocus() ) && ( !mItemYEdit->hasFocus() ) && ( !mLanguageTextEdit->hasFocus() ) ) { e->setAccepted(false); QList selectedItems = selectedLanguageItems(); for ( int i = 0 ; i < selectedItems.size() ; i++ ) { selectedItems[i]->keyPressEvent( (QKeyEvent*) e ); } if ( e->isAccepted() ) { return true; } } return QMainWindow::eventFilter(obj, e); } else { if ( e->type() == QEvent::Shortcut ) { QShortcutEvent *keyEvent = (QShortcutEvent*)(e); QKeySequence keySequence = QKeySequence::SelectAll; if ( (keyEvent->key()) == keySequence ) { if ( mLanguageTextEdit->hasFocus() ) { mLanguageTextEdit->selectAll(); e->accept(); return true; } } } // standard event processing return QMainWindow::eventFilter(obj, e); } } //------------------------------------------------------------------------- QMenu * GraphicsSceneMainWindow::createPopupMenu() { QMenu * menu = QMainWindow::createPopupMenu(); if ( mSettings.mHasHistory || mSettings.mHasStorage ) menu->addSeparator(); if ( mSettings.mHasHistory ) { QAction * switchHistoryVisible = new QAction( tr("History") , this ); switchHistoryVisible->setCheckable(true); connect( switchHistoryVisible , SIGNAL(triggered()) , this , SLOT(switchHistoryVisible()) ); switchHistoryVisible->setChecked( mHistoryGraphicsView->isVisible() ); menu->addAction( switchHistoryVisible ); if ( !mSwitchHistoryVisible ) { mSwitchHistoryVisible = switchHistoryVisible; } } if ( mSettings.mHasStorage ) { QAction * switchStorageVisible = new QAction( tr("Storage") , this ); switchStorageVisible->setCheckable(true); connect( switchStorageVisible , SIGNAL(triggered()) , this , SLOT(switchStorageVisible()) ); switchStorageVisible->setChecked( mStorageGraphicsView->isVisible() ); menu->addAction( switchStorageVisible ); if ( !mSwitchStorageVisible ) { mSwitchStorageVisible = switchStorageVisible; } } return menu; } //------------------------------------------------------------------------- void GraphicsSceneMainWindow::dragEnterEvent(QDragEnterEvent* event) { if ( ( ( event->mimeData()->hasText() ) || ( event->mimeData()->hasUrls() ) ) && ( !event->mimeData()->hasFormat(FROM_STORAGE_DRAG_MIME) ) && ( !event->mimeData()->hasFormat(FROM_HISTORY_DRAG_MIME) ) ) { event->acceptProposedAction(); } } // Drop in the GraphicsSceneMainWindow space. // Note : the GuidoGraphicsView has its own dropEvent handler when // an item is dropped specifically in the view. //------------------------------------------------------------------------- void GraphicsSceneMainWindow::dropEvent(QDropEvent* event) { if ( ( ( event->mimeData()->hasText() ) || ( event->mimeData()->hasUrls() ) ) && ( !event->mimeData()->hasFormat(FROM_STORAGE_DRAG_MIME) ) && ( !event->mimeData()->hasFormat(FROM_HISTORY_DRAG_MIME) ) && ( !event->mimeData()->hasFormat(FROM_SCENE_DRAG_MIME) ) ) { QLanguageItem* createdItem = 0; //If a new item has been dropped, move to the mouse position dropItem( event->mimeData() , viewCenterInSceneCoordinate() , &createdItem ); event->accept(); } else { event->ignore(); } } //------------------------------------------------------------------------- QGraphicsPixmapItem * buildPixmapItem( const QString& fileName ) { QGraphicsPixmapItem * i = new QGraphicsPixmapItem( QPixmap( fileName ) ); i->setTransformationMode( Qt::SmoothTransformation ); return i; } //------------------------------------------------------------------------- QItemResizer * GraphicsSceneMainWindow::plugResizer( QLanguageItem * itemContainer ) { QRectF guidoRect = itemContainer->boundingRect(); QItemResizer * itemResizer = new QItemResizer( guidoRect , itemContainer ); itemResizer->setVisible( false ); itemResizer->setKeepAspectRatio(true); itemResizer->setZValue(2); itemResizer->setPen( QPen(Qt::black) ); connect( itemResizer , SIGNAL( resized(const QRectF&) ) , itemContainer , SLOT(resized(const QRectF&)) ); connect( itemContainer , SIGNAL( updateChildrenItemsGeometry(const QRectF&) ) , itemResizer , SLOT(updateGeometry(const QRectF&)) ); connect( itemContainer , SIGNAL( showResizer(bool) ) , itemResizer , SLOT(show(bool)) ); return itemResizer; } FaustWorks-0.4/GraphicsSceneMainWindow.h0000755000175000017500000003456412130743520017027 0ustar miramira/* * MainWindow.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef GRAPHICS_SCENE_MAINWINDOW_H #define GRAPHICS_SCENE_MAINWINDOW_H #include #include #include #include #include #include #include #include #include #include #include #define RSC_DIR QString(":/") #define MAX(a,b) ((a)>(b)) ? (a) : (b) #define MIN(a,b) ((a)<(b)) ? (a) : (b) #define FROM_STORAGE_DRAG_MIME "FromStorageMimeType" #define FROM_SCENE_DRAG_MIME "FromSceneMimeType" #define FROM_HISTORY_DRAG_MIME "FromHistoryMimeType" #define PAGE_ITEM_OUT_MARGIN 20 #define PAGE_ITEM_IN_MARGIN 5 #define EXPORT_MIN_DETAIL 5 #define EXPORT_MAX_DETAIL 50 #define EXPORT_DEFAULT_DETAIL 30 #define EXPORT_DETAIL_TO_SCALE_FACTOR 0.1f #define MIN_FONT_SIZE 6 #define MAX_FONT_SIZE 72 #define DEFAULT_FONT_SIZE 12 #define PALETTE_UNDEFINED -1 #define PNG_FILE_EXTENSION QString("png") #define PDF_FILE_EXTENSION QString("pdf") #define PS_FILE_EXTENSION QString("ps") #define MIDI_FILE_EXTENSION QString("midi") #define PNG_FILE_FILTER QString("Image (*." + PNG_FILE_EXTENSION + ")") #define PDF_FILE_FILTER QString("PDF (*." + PDF_FILE_EXTENSION + ")") #define PS_FILE_FILTER QString("PostScript (*." + PS_FILE_EXTENSION + ")") #define MIDI_FILE_FILTER QString("Midi (*." + MIDI_FILE_EXTENSION + ")") #define FONT_SIZE_SETTING "FontSizeSetting" #define WORKSPACE_MODE_SETTING "WorkspaceModeSetting" class QLanguageItem; class QAction; class QMenu; class QGraphicsView; class QGraphicsScene; class LanguageGraphicsView; class LanguageTextEdit; class QBackgroundItem; class QSideBarGraphicsView; class QStorageGraphicsView; class QPaintDevice; class QLanguageItemFactory; class QItemResizer; #define DEFAULT_MAX_SCALE 10.0f #define DEFAULT_MIN_SCALE 0.1f #define DEFAULT_MIN_ZOOM 0.1f #define DEFAULT_MAX_ZOOM 10.0f #define DEFAULT_ZOOM_FACTOR 1.414213562f enum UIElementId { EXIT_ACT = 0, ABOUT_QT_ACT, ZOOM_IN_ACT, ZOOM_OUT_ACT, ZOOM_STANDARD_ACT, FONT_BIGGER_ACT, FONT_SMALLER_ACT, ADD_ACT, ADD_FROM_FILE_ACT, REMOVE_ACT, COPY_ACT, PASTE_ACT, CLEAN_HISTORY_ACT, SEND_TO_BACK_ACT, SEND_BACKWARD_ACT, BRING_TO_FRONT_ACT, BRING_FORWARD_ACT, SELECT_ALL_ACT, NEW_ACT, SAVE_ACT, SAVE_AS_ACT, SAVE_ALL_ACT, OPEN_ACT, RESCALE_ACT, H_ALIGN_ACT, V_ALIGN_ACT, FILE_MENU, HELP_MENU, VIEW_MENU, EDIT_MENU, WINDOW_MENU, FILE_TOOL_BAR, VIEW_TOOL_BAR , EDIT_TOOL_BAR , SIZE_TOOL_BAR , RESIZE_SLIDER , RESIZE_EDIT , X_ITEM_EDIT , Y_ITEM_EDIT , STATUS_BAR_MOUSE_POS , STATUS_BAR_ZOOM }; struct GraphicsSceneMainWindowSettings { GraphicsSceneMainWindowSettings() { mMaxScale = DEFAULT_MAX_SCALE; mMinScale = DEFAULT_MIN_SCALE; mMinZoom = DEFAULT_MIN_ZOOM; mMaxZoom = DEFAULT_MAX_ZOOM; mZoomFactor = DEFAULT_ZOOM_FACTOR; mLanguageNameShort = ""; mLanguageNameLong = ""; mLanguageFileExtension = ""; mSceneFileExtension = ""; mDefaultLanguageCode = ""; mLanguageCommandsFile = ""; mHasStorage = true; mHasHistory = true; } QString mLanguageName; int mResizerBorderWidth; float mMinZoom; float mMaxZoom; float mZoomFactor; float mMinScale; float mMaxScale; QSizeF mMinItemSize , mMaxItemSize; QString mLanguageNameShort; QString mLanguageNameLong; QString mLanguageFileExtension; QString mSceneFileExtension; QString mDefaultLanguageCode; QString mLanguageCommandsFile; bool mHasStorage; bool mHasHistory; QList mDesactiveUIElements; }; class GraphicsSceneMainWindow : public QMainWindow { friend class LanguageGraphicsView; friend class LanguageTextEdit; friend class QStorageGraphicsView; Q_OBJECT public: GraphicsSceneMainWindow( LanguageGraphicsView * graphicsView , QLanguageItemFactory * factory ); ~GraphicsSceneMainWindow(); virtual void reinitSettings(); static void initApplicationSettings( const GraphicsSceneMainWindowSettings& settings ); static const GraphicsSceneMainWindowSettings& applicationSettings(); protected Q_SLOTS: void addItem(); void addItemFromFile(); void removeSelectedItems(); void copyItem(); void pasteItem(); void selectAll(); void cleanHistory(); void zoomIn(); void zoomOut(); void zoomStandard(); virtual void fontBigger(); virtual void fontSmaller(); void sceneSelectionChanged(); void sceneChanged( const QList & region ); void textEditActivity(); virtual void updateCode(); void resizeSliderChanged(int value); void scaleItems(double scale); void scaleItems(double xScale , double yScale , double sizeScale ); void scaleChanged(float newScale); void moveItemX(double x); void moveItemY(double y); void resizeItems(); void hAlignItems(); void vAlignItems(); void newScene(); void save(); void saveSceneAs(); void saveAll(); void loadScene(); void rescaleItem(float xScale , float yScale , float sizeScale ); void resizePage( const QRectF& newRect ); void storeItem(QLanguageItem * container); void itemRemoved(); virtual void itemRemoved( QLanguageItem * ); void insertText( const QString& gmnCode , int insertIndex ); void switchCommandPaletteVisible(); void switchTextEditVisible(); virtual void updateWindowMenu(); void switchStorageVisible(); void switchHistoryVisible(); void saveItemAs(); void fileChanged(bool isFileRemoved); void descriptiveNameChanged(); void itemHasBeenReloaded(); void focusChanged( QWidget * old, QWidget * now ); void bringForward(); void sendBackward(); void bringToFront(); void sendToBack(); protected: void init(); /*! * \brief Checks if the settings have been initialized for this application ; * and does the initialization if necessary. * Loads the settings (readSettings()). */ void checkSettings(); /*! * \brief Loads the application settings. */ virtual void readSettings(); /*! * \brief Loads the settings that can be modified in the preference menu. * * This function should be called each time the Preference dialog is asked. */ void readPreferencesSettings(); /*! * \brief Writes the application state into the settings. (usually called when the application closes) */ virtual void writeSettings(); // Widgets initialization methods. virtual void createActions(); virtual void createMenus(); virtual void createToolBars(); void createStatusBar(); void setupTextEdit(); void createHistoryAndStorage(); //Destroys the current mGraphicsScene and build a new one. void reinitScene(QRectF sceneRect); // If the scene has changed, opens a QDialog asking whether the scene should be saved or not, // and saves (or not), according to the user's choice. // Returns false if the user chooses to cancel. bool saveOrCancelDialog(); // Checks if items modifications should be saved, asking the user when necessary. bool checkAllItems(); // Calls save or saveAs, depending on whether the scene has already been saved or not. void saveScene(); // Save the scene to the specified file. (creating a new file / erasing any file with the same name) void saveSceneFile(const QString& fileName); /* * \brief Load a Guido Scene file. * * \return True if the load was successful. */ bool loadSceneFile(const QString& fileName); bool dropItem( const QMimeData * mimeData , const QPointF& pos , QLanguageItem** createdItem ); bool addFile(const QString &fileName , QLanguageItem** createdItem = 0); bool addCode(const QString &gmnCode, QLanguageItem** createdItem = 0); // Only method used to add a new QGuidoItem to the scene (on clicking on the "AddItem" button, on dragging a file inside the window, on pasting an item, ...). // \param gmnSource may contain GMN Code or the full path to the GMN file to load // \param isFileName Indicates whether gmnSource contains GMN code or a path to a GMN file // \param isPageItem Indicates whether a QGuidoItem or a QGuidoPageGraphicsItem must be instanciated. // \param pagesAlignment The pagesAlignment of the created QGuidoItem // \param createdItem a reference to the pointer to the created QGuidoItem. // \return true if the gmnSource was valid (correct GMN code/GMN file). virtual bool addLanguageItem(const QString &gmnSource, bool sourceIsAFile , QLanguageItem** createdItem); bool fileControl(QLanguageItem* languageItem); // Standard treatment applied to each QLanguageItem added to the main scene (new, dropped, from saved file, ... each one). virtual void setupNAddItem(QLanguageItem* languageItem); // Extra-treatment applied to each QLanguageItem added to the main scene from a "Add item..." menu action. virtual void setupItemFromMenu(QLanguageItem* languageItem); // Standard treatment applied to each brand new QLanguageItem added to the main scene by the user // ( <=> menu-created or dropped) : setupNAddItem, controls the size, centers the position. // note: Copied items, scene-loaded items, don't use this function. virtual void setupNAddNewItem(QLanguageItem* languageItem); // Removes and destroys the specified item. Returns false if the removal has been canceled. bool removeItem( QLanguageItem * item ); // Removes and destroys all the QGraphicsItem present in mGraphicsScene. void removeAllItems(); bool saveItemModificationsDialog(QLanguageItem * item); void saveItemAs(QLanguageItem * item); // Adds a copy of the item, at the same position. QLanguageItem* addItemCopy(QLanguageItem* item); QString findFile(const QString& file); QPointF viewCenterInSceneCoordinate(); //Scene items listing/filtering functions. QList selectedLanguageItems(); QList languageItems(); void unselectAll(); // Activate/Desactivate the actions/control widgets, depending on the number of selected items. // Updates the content of the gmn-code text edit. // Updates the item scale/position control widgets. virtual void updateWindowState(); // Updates the item scale control widgets. void updateScaleControls(double scale); // Updates the item position control widgets. // If (connectedToItem==false), the connection "control widget value"-> "actual item position" will be desactivated during the update of the value. void updateItemPositionControls(bool connectedToItem = true); // Updates the cursor position labels in the status bar. void updateCursorPos(QPointF pos); // Updates the current view zoom label in the status bar. void updateZoomLabel(); void updateRemoveActState(); // Sets the zValue of each QLanguageItem with its position in mZOrderedItems list. void updateZOrders(); // Adds the specified item to history if necessary. Should be called each time an item has been modified, added, etc... so that // each step is kept in the history. void addToHistory(QLanguageItem* item); // Misc. void formatFileName(QString& fileName , QString& selectedFilter , const QString& filters); void controlPlayingContainer( QGraphicsItem * container ); virtual void changeFontSize( float newFontPointSize ); virtual void reloadTextEdits(); //Workaround : QTextEdit won't update when calling setFontPointSize. void zoom( float zoom ); QString getFileDialogPath(); void setLastManagedFile(const QString& lastFile); // UI events handlers. void closeEvent(QCloseEvent *event); bool eventFilter(QObject *obj, QEvent *event); QMenu * createPopupMenu(); void dragEnterEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); /* * \brief Creates and plug a QItemResizer on the specified QLanguageItem. * * \return A reference to the created QItemResizer. */ virtual QItemResizer* plugResizer( QLanguageItem * itemContainer ); QGraphicsView * mGraphicsView; QGraphicsScene * mGraphicsScene; QDockWidget * mLanguageTextEditDock; LanguageTextEdit * mLanguageTextEdit; QTimer * mLanguageTextEditTimer; QWidget * mCommandPaletteDock; QLanguageItem * mFirstSelectedItem; QList mCopiedItems; QSlider * mResizeSlider; QDoubleSpinBox * mResizeEdit; QDoubleSpinBox * mItemXEdit; QDoubleSpinBox * mItemYEdit; QBackgroundItem * mBackgroundItem; QSplitter * mSplitter; QGraphicsScene * mStorageGraphicsScene; QSideBarGraphicsView * mStorageGraphicsView; QGraphicsScene * mHistoryGraphicsScene; QSideBarGraphicsView * mHistoryGraphicsView; QLabel * mViewXLabel; QLabel * mViewYLabel; QLabel * mViewScaleLabel; QMenu *mFileMenu; QMenu *mHelpMenu; QMenu *mViewMenu; QMenu *mEditMenu; QMenu *mWindowMenu; QToolBar *mFileToolBar; QToolBar *mViewToolBar; QToolBar *mEditToolBar; QToolBar *mSizeToolBar; QAction *mExitAct; QAction *mAboutQtAct; QAction *mZoomInAct; QAction *mZoomOutAct; QAction *mZoomStandardAct; QAction *mFontBiggerAct; QAction *mFontSmallerAct; QAction *mAddAct; QAction *mAddFromFileAct; QAction *mRemoveAct; QAction *mCopyAct; QAction *mPasteAct; QAction *mCleanHistoryAct; QAction *mSelectAllAct; QAction *mNewAct; QAction *mSaveAct; QAction *mSaveAsAct; QAction *mSaveAllAct; QAction *mOpenAct; QAction *mRescaleAct; QAction *mHAlignAct; QAction *mVAlignAct; QAction *mSwitchCommandPaletteVisible; QAction *mSwitchTextEditVisible; QAction *mSendBackwardAct; QAction *mSendToBackAct; QAction *mBringToFrontAct; QAction *mBringForwardAct; QByteArray mStdMainWindowState; QAction *mSwitchHistoryVisible; QAction *mSwitchStorageVisible; int mCurrentZOrderItem; bool mSceneHasChanged; QString mLastOpenFilePath; bool mIsWorkspaceModeOn; QList mZOrderedItems; QLanguageItemFactory * mFactory; static GraphicsSceneMainWindowSettings mSettings; }; QGraphicsPixmapItem * buildPixmapItem( const QString& fileName ); QGraphicsItem * buildTextItem(const QString& text); #endif //GRAPHICS_SCENE_MAINWINDOW_H FaustWorks-0.4/Info.plist0000644000175000017500000000117012130743520014073 0ustar miramira CFBundleIconFile FaustWorks.icns CFBundlePackageType APPL CFBundleGetInfoString Created by Qt/QMake CFBundleSignature ???? CFBundleExecutable FaustWorks CFBundleIdentifier fr.grame.FaustWorks NOTE This file was generated by Qt/QMake. FaustWorks-0.4/MainWindowObjects.cpp0000755000175000017500000006365612130743520016241 0ustar miramira/* * MainWindowObjects.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "MainWindowObjects.h" #include "GraphicsSceneMainWindow.h" #include "QLanguageItem.h" #include "QLanguageItemFactory.h" #include "QItemResizer.h" #include "QPaletteItem.h" #include #include #include #include #include #include #include #include #define DOM_GMN_CONTAINER_ITEM "containerItem" #define DOM_GMN_CONTAINER_ITEM_X "containerItemX" #define DOM_GMN_CONTAINER_ITEM_Y "containerItemY" #define DOM_HISTORY "history" #define DOM_STORAGE "storage" #define PAGE_ITEM_SHADOW_DISTANCE 5 #define HISTORY_ITEM_MARGIN 25 #define HISTORY_WIDTH 120 #define STORAGE_WIDTH 150 #define STORAGE_ITEM_WIDTH 66 #define STORAGE_ITEM_HEIGHT 100 #define TEXT_MARGIN_X 10 #define TEXT_MARGIN_Y 15 #define MAX_FONT 15 //------------------------------------------------------------------------------------------------------------------------ QSideBarGraphicsView::QSideBarGraphicsView(QGraphicsScene * s , QLanguageItemFactory* factory ) : QGraphicsView(s) , mFactory(factory) {} //------------------------------------------------------------------------------------------------------------------------ QDomElement QSideBarGraphicsView::save(QDomDocument &d) { QDomElement root = d.createElement( domId() ); for ( int i = 0 ; i < mAddedItems.size() ; i++ ) { root.appendChild( mAddedItems[i]->saveToDomElement(&d) ); } return root; } //------------------------------------------------------------------------------------------------------------------------ bool QSideBarGraphicsView::load( const QDomElement& root ) { if( root.tagName() != domId() ) return false; clear(); QDomNode n = root.firstChild(); while ( !n.isNull() ) { QDomElement e = n.toElement(); if ( ( !e.isNull() ) && ( e.tagName() == DOM_LANGUAGE_ITEM ) ) { QLanguageItem * container = mFactory->buildLanguageItem(&e); if ( !find(container) ) addItem( container ); else delete container; } n = n.nextSibling(); } return true; } //------------------------------------------------------------------------------------------------------------------------ void QSideBarGraphicsView::clear() { while ( mAddedItems.size() > 0 ) { scene()->removeItem( mAddedItems[0] ); delete mAddedItems[0]; mAddedItems.removeAt(0); } } //------------------------------------------------------------------------------------------------------------------------ void QSideBarGraphicsView::removeItem( QGraphicsItem * item ) { QLanguageItem * selectionItem = dynamic_cast(item); assert( selectionItem ); scene()->removeItem( selectionItem ); mAddedItems.removeAll(selectionItem); delete item; } //------------------------------------------------------------------------------------------------------------------------ QLanguageItem* QSideBarGraphicsView::find(const QLanguageItem * other ) { for ( int i = 0 ; i < mAddedItems.size() ; i++ ) { QLanguageItem * languageItem = mAddedItems[i]; if ( other->isEqualTo( languageItem ) ) return languageItem; } return 0; } //------------------------------------------------------------------------------------------------------------------------ void QSideBarGraphicsView::setupContainer( QLanguageItem * container ) { container->setMimeId( mimeId() ); container->setStorageMode(true); container->unlinkFile(); } #define SCROLL_BAR_MARGIN 5 #define MAX_HISTORY_SIZE 30 #define EMPTY_SCENE_HEIGHT 1 //------------------------------------------------------------------------------------------------------------------------ QHistoryGraphicsView::QHistoryGraphicsView(QGraphicsScene * s , QLanguageItemFactory* factory ) : QSideBarGraphicsView(s , factory ) { setFixedWidth( HISTORY_WIDTH ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setStatusTip ( "Keep trace of all items added to the scene" ); } //------------------------------------------------------------------------------------------------------------------------ void QHistoryGraphicsView::clear() { QSideBarGraphicsView::clear(); scene()->setSceneRect( QRectF(0,0,0,EMPTY_SCENE_HEIGHT ) ); } //------------------------------------------------------------------------------------------------------------------------ void QHistoryGraphicsView::resizeEvent( QResizeEvent * ) { scene()->setSceneRect( QRectF(0,0,width() - HISTORY_ITEM_MARGIN , MAX( height() - SCROLL_BAR_MARGIN , scene()->sceneRect().height() ) ) ); } //------------------------------------------------------------------------------------------------------------------------ void QHistoryGraphicsView::addItem( QLanguageItem * container ) { setupContainer( container ); //Scale the item so that it fits inside the side bar, maximizing its size but keeping margins. float widthScaleFactor = ( this->width() - HISTORY_ITEM_MARGIN ) / container->sceneBoundingRect().width(); float heightScaleFactor = ( 1.5f * this->width() - HISTORY_ITEM_MARGIN ) / container->sceneBoundingRect().height(); float scaleFactor = MIN(widthScaleFactor,heightScaleFactor); scaleFactor = MIN( MIN(scaleFactor,1.0f/container->transform().m11()) , MIN(scaleFactor,1.0f/container->transform().m22()) ); container->scale( scaleFactor , scaleFactor ); //Add the item to the scene, and to the list of all items. scene()->addItem( container ); mAddedItems.append( container ); reorderItems(); } //------------------------------------------------------------------------------------------------------------------------ QString QHistoryGraphicsView::domId() { return DOM_HISTORY; } //------------------------------------------------------------------------------------------------------------------------ QString QHistoryGraphicsView::mimeId() { return FROM_HISTORY_DRAG_MIME; } #include //------------------------------------------------------------------------------------------------------------------------ void QHistoryGraphicsView::reorderItems() { if ( mAddedItems.size() > MAX_HISTORY_SIZE ) { removeItem( mAddedItems.first() ); } int currentY = 0; int maxWidth = 0; for ( int i = mAddedItems.size()-1 ; i >= 0 ; i-- ) { QRectF r(mAddedItems[i]->sceneBoundingRect()); mAddedItems[i]->setPos( 0 , currentY ); currentY += r.height(); maxWidth = MAX( r.width() , maxWidth ); } for ( int i = mAddedItems.size()-1 ; i >= 0 ; i-- ) { QRectF r(mAddedItems[i]->sceneBoundingRect()); mAddedItems[i]->setPos( (maxWidth - r.width())/2.0f , mAddedItems[i]->pos().y() ); } int sceneHeight = scene()->sceneRect().height(); if ( ( sceneHeight == EMPTY_SCENE_HEIGHT ) || ( currentY > sceneHeight ) ) { sceneHeight += height() - SCROLL_BAR_MARGIN; } scene()->setSceneRect( QRectF(0,0,width() - HISTORY_ITEM_MARGIN , sceneHeight ) ); } //------------------------------------------------------------------------------------------------------------------------ QStorageGraphicsView::QStorageGraphicsView( QGraphicsScene * s , GraphicsSceneMainWindow * mainWindow , QLanguageItemFactory* factory ) : QSideBarGraphicsView(s , factory) { setAcceptDrops(true); setDragMode(QGraphicsView::RubberBandDrag); mMainWindow = mainWindow; setStatusTip ( tr("Drag&drop an item to store it in the Storage Zone") ); connect( s , SIGNAL( changed(const QList &) ) , this , SLOT( sceneChanged(const QList &) ) ); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::addItem( QLanguageItem * container ) { setupContainer(container); container->setPos(0,0); //Scale the item so that it fits within a constraint size (STORAGE_ITEM_WIDTH,STORAGE_ITEM_HEIGHT) QRectF rect = container->sceneBoundingRect(); float scaleFactor = MIN( float(STORAGE_ITEM_WIDTH) / rect.width() , float(STORAGE_ITEM_HEIGHT) / rect.height() ); scaleFactor = MIN( MIN(scaleFactor,1.0f/container->transform().m11()) , MIN(scaleFactor,1.0f/container->transform().m22()) ); container->scale( scaleFactor , scaleFactor ); //Item is only selectable, not movable. (moved by drag&drop, other mechanism) container->setFlags( QGraphicsItem::ItemIsSelectable ); //Add the item to the scene, and to the list of all items. scene()->addItem( container ); mAddedItems.append( container ); reorderItems(); } //------------------------------------------------------------------------------------------------------------------------ QString QStorageGraphicsView::domId() { return DOM_STORAGE; } //------------------------------------------------------------------------------------------------------------------------ QString QStorageGraphicsView::mimeId() { return FROM_STORAGE_DRAG_MIME; } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::sceneChanged( const QList &) { mMainWindow->updateRemoveActState(); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::resizeEvent( QResizeEvent * ) { scene()->setSceneRect( 0 , 0 , this->width()-SCROLL_BAR_MARGIN , this->height()-SCROLL_BAR_MARGIN ); reorderItems(); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::dragEnterEvent(QDragEnterEvent* event) { // qDebug() << "QStorageGraphicsView::dragEnterEvent"; if ( ( event->mimeData()->hasFormat(FROM_SCENE_DRAG_MIME) ) || ( event->mimeData()->hasFormat(FROM_STORAGE_DRAG_MIME) ) || ( event->mimeData()->hasFormat(FROM_HISTORY_DRAG_MIME) ) ) { event->acceptProposedAction(); } else event->ignore(); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::dragMoveEvent(QDragMoveEvent* event) { event->acceptProposedAction(); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::dragLeaveEvent(QDragLeaveEvent* ) { // qDebug() << "QStorageGraphicsView::dragLeaveEvent"; // QGraphicsView::dragLeaveEvent( event ); } /*! * \brief Drops a QLanguageItem in the QStorageGraphicsView. The * QLanguageItem is built from the information in the QMimeData. */ //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::dropEvent(QDropEvent* event) { // Only accepts drops that come from within the application : main scene, or sidebars. if ( ( event->mimeData()->hasFormat(FROM_SCENE_DRAG_MIME) ) || ( event->mimeData()->hasFormat(FROM_STORAGE_DRAG_MIME) ) || ( event->mimeData()->hasFormat(FROM_HISTORY_DRAG_MIME) ) ) { // Build the QLanguageItem from the informations in the QMimeData. QLanguageItem * container = mFactory->buildLanguageItem( event->mimeData() ); // Do not accept invalid items. if ( !(container->isValid()) ) { delete container; return; } // If the storage scene already contains an equivalent item, // do not add the new item ; only move the existing one. QLanguageItem * other = find(container); if ( other ) { QRectF itemRect = other->sceneBoundingRect(); other->setPos( event->pos() - QPointF(itemRect.width(),itemRect.height())/2.0f ); reorderItems(); delete container; } else { // There is no equivalent item in the scene : add the created item. addItem( container ); QPointF scenePos = mapToScene( event->pos() ); QRectF itemRect = container->sceneBoundingRect(); container->setPos( scenePos - QPointF( itemRect.width() , itemRect.height() )/2.0f ); } event->accept(); if ( event->mimeData()->hasFormat(FROM_SCENE_DRAG_MIME) ) { QLanguageItem * item = (QLanguageItem*)((const void *) event->mimeData()->data( FROM_SCENE_DRAG_MIME )); if ( mMainWindow->saveItemModificationsDialog(item) ) { mMainWindow->itemRemoved( item ); item->deleteLater(); } } } else { event->ignore(); } } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::focusOutEvent( QFocusEvent * event ) { QGraphicsView::focusOutEvent( event ); while ( scene()->selectedItems().size() > 0 ) scene()->selectedItems()[0]->setSelected( false ); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::focusInEvent( QFocusEvent * event ) { QGraphicsView::focusOutEvent( event ); mMainWindow->unselectAll(); } //------------------------------------------------------------------------------------------------------------------------ void QStorageGraphicsView::reorderItems() { /* QList decorators = filterItems( scene()->items() ); QRectF visibleRect = mapFromScene( sceneRect() ).boundingRect(); for ( int i = 0 ; i < decorators.size() ; i++ ) { QRectF decoratorRect = decorators[i]->sceneBoundingRect(); if ( decoratorRect.x() < visibleRect.x() ) decorators[i]->setPos( visibleRect.x() , decorators[i]->y() ); if ( decorators[i]->y() < visibleRect.y() ) decorators[i]->setPos( decorators[i]->x() , visibleRect.y() ); if ( decoratorRect.bottomRight().x() > visibleRect.bottomRight().x() ) decorators[i]->setPos( visibleRect.bottomRight().x() - decoratorRect.width() , decorators[i]->y() ); if ( decoratorRect.bottomRight().y() > visibleRect.bottomRight().y() ) decorators[i]->setPos( decorators[i]->x() , visibleRect.bottomRight().y() - decoratorRect.height() ); } */ } //------------------------------------------------------------------------------------------------------------------------ QList QStorageGraphicsView::filterItems(const QList& list) { QList result; for ( int i = 0 ; i < list.size() ; i++ ) { QLanguageItem * languageItem = dynamic_cast (list[i]); if ( languageItem ) result.append( languageItem ); } return result; } #define SHADOW_COLOR QColor(150,150,150,50) //------------------------------------------------------------------------------------------------------------------------ QBackgroundItem::QBackgroundItem( GraphicsSceneMainWindow * mainWindow , const QSizeF& size ) { mRect = QRectF( 0, 0, size.width() , size.height() ); mPage = new QGraphicsRectItem( QRectF() , this ); mPage->setBrush( Qt::white ); mPage->setPen( Qt::NoPen ); mPage->setZValue(0); mBackgroundItemResizer = new QItemResizer( QRectF() , mPage ); mBackgroundItemResizer->setZValue(1); mBackgroundItemResizer->setKeepAspectRatio(false); QPen resizerPen(Qt::black); resizerPen.setStyle( Qt::DotLine ); mBackgroundItemResizer->setPen( resizerPen ); mBackgroundItemResizer->setBrush( SHADOW_COLOR ); mIsResizeEnabled = true; QObject::connect( mBackgroundItemResizer , SIGNAL(resized(const QRectF&) ) , mainWindow , SLOT(resizePage(const QRectF&)) ); updatePageRect(); } //------------------------------------------------------------------------------------------------------------------------ void QBackgroundItem::setRect( const QRectF& r ) { // qDebug() << "QBackgroundItem::setRect : " << mRect << " -> " << r; if ( ( r.width() != mRect.width() ) || ( r.height() != mRect.height() ) ) { prepareGeometryChange(); mRect.setWidth(r.width()); mRect.setHeight(r.height()); update(); updatePageRect(); } setPos( r.x() , r.y() ); } //------------------------------------------------------------------------------------------------------------------------ QRectF QBackgroundItem::boundingRect() const { return mRect; } //------------------------------------------------------------------------------------------------------------------------ QRectF QBackgroundItem::pageRectInSceneCoords() const { return mPage->mapToScene(mPage->boundingRect()).boundingRect(); } //------------------------------------------------------------------------------------------------------------------------ void QBackgroundItem::setPageSize( const QSizeF& size ) { setResizeEnabled( true ); QSize totalSize(size.width() + 2*PAGE_ITEM_OUT_MARGIN , size.height() + 2*PAGE_ITEM_OUT_MARGIN ); // setSize( totalSize ); setRect( QRectF( pos().x() , pos().y() , totalSize.width() , totalSize.height() ) ); } //------------------------------------------------------------------------------------------------------------------------ QSizeF QBackgroundItem::pageSize() const { return QSize( mPage->boundingRect().width() , mPage->boundingRect().height() ); } //------------------------------------------------------------------------------------------------------------------------ void QBackgroundItem::setResizeEnabled( bool isEnabled ) { mIsResizeEnabled = isEnabled; } //------------------------------------------------------------------------------------------------------------------------ bool QBackgroundItem::isResizeEnabled() const { return mIsResizeEnabled; } //------------------------------------------------------------------------------------------------------------------------ void QBackgroundItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * , QWidget * ) { QRectF pageRect = mPage->boundingRect(); pageRect.translate( mPage->pos() ); QRectF shadowRect( pageRect ); shadowRect.translate( PAGE_ITEM_SHADOW_DISTANCE , PAGE_ITEM_SHADOW_DISTANCE ); painter->setPen( Qt::NoPen ); painter->setBrush( QBrush(Qt::darkGray) ); painter->drawRect( shadowRect ); } // The pageRect is the "white paper" part of the QBackgroundItem. // // ---------------------------------------------------------------------------------------------------------------------- void QBackgroundItem::updatePageRect() { if ( mIsResizeEnabled ) { QRectF pageRect(0,0,0,0); pageRect.setWidth( mRect.width() - 2*PAGE_ITEM_OUT_MARGIN ); pageRect.setHeight( mRect.height() - 2*PAGE_ITEM_OUT_MARGIN ); mPage->setRect( pageRect ); mPage->setPos( PAGE_ITEM_OUT_MARGIN , PAGE_ITEM_OUT_MARGIN ); mBackgroundItemResizer->updateGeometry( pageRect ); } } //------------------------------------------------------------------------------------------------------------------------ LanguageTextEdit::LanguageTextEdit(const QString& initString , GraphicsSceneMainWindow * mainWindow) : QTextEdit(initString) , mMainWindow(mainWindow) { } //------------------------------------------------------------------------------------------------------------------------ void LanguageTextEdit::wheelEvent( QWheelEvent * e ) { mMainWindow->textEditActivity(); QTextEdit::wheelEvent( e ); } //------------------------------------------------------------------------------------------------------------------------ void LanguageTextEdit::focusOutEvent( QFocusEvent * event ) { mMainWindow->updateCode(); QTextEdit::focusOutEvent( event ); } //------------------------------------------------------------------------------------------------------------------------ void LanguageTextEdit::changeEvent ( QEvent * event ) { if ( event->type() == QEvent::EnabledChange ) Q_EMIT enabled( isEnabled() ); } //------------------------------------------------------------------------------------------------------------------------ void LanguageTextEdit::dragEnterEvent(QDragEnterEvent* event) { if ( ( ( event->mimeData()->hasText() ) || ( event->mimeData()->hasUrls() ) ) ) { event->acceptProposedAction(); } else { qDebug("LanguageTextEdit::dragEnterEvent : refused"); } } //------------------------------------------------------------------------------------------------------------------------ void LanguageTextEdit::dragMoveEvent(QDragEnterEvent* event) { if ( ( ( event->mimeData()->hasText() ) || ( event->mimeData()->hasUrls() ) ) ) { event->acceptProposedAction(); } } //------------------------------------------------------------------------------------------------------------------------ void LanguageTextEdit::dropEvent(QDropEvent* event) { QLanguageItem* createdItem = 0; mMainWindow->dropItem( event->mimeData() , mMainWindow->viewCenterInSceneCoordinate() , &createdItem ); event->accept(); } //------------------------------------------------------------------------------------------------------------------------ LanguageGraphicsView::LanguageGraphicsView() : QGraphicsView() { setDragMode(QGraphicsView::RubberBandDrag); setAcceptDrops(true); setMouseTracking (true); } //------------------------------------------------------------------------------------------------------------------------ QSize LanguageGraphicsView::sizeHint () const { //return QSize(500,500); return QSize(50,50); } //------------------------------------------------------------------------------------------------------------------------ void LanguageGraphicsView::setMainWindow( GraphicsSceneMainWindow * mainWindow ) { setParent( mainWindow ); mMainWindow = mainWindow; } //------------------------------------------------------------------------------------------------------------------------ void LanguageGraphicsView::dragEnterEvent(QDragEnterEvent* event) { // qDebug() << "LanguageGraphicsView::dragEnterEvent"; if ( ( event->mimeData()->hasText() || event->mimeData()->hasUrls() ) || ( event->mimeData()->hasFormat( FROM_SCENE_DRAG_MIME ) ) ) { event->acceptProposedAction(); } } //------------------------------------------------------------------------------------------------------------------------ void LanguageGraphicsView::dragLeaveEvent(QDragLeaveEvent* ) { // qDebug() << "LanguageGraphicsView::dragLeaveEvent"; } //------------------------------------------------------------------------------------------------------------------------ void LanguageGraphicsView::dropEvent(QDropEvent* event) { // Take the focus. setFocus(); QLanguageItem* droppedItem = 0; QPointF pos = mapToScene( event->pos() ); // Check if the drop QMimeData contains the "copy drag" flag. bool doCopy = false; if ( event->mimeData()->hasFormat( MIME_DO_COPY ) ) { doCopy = QVariant( event->mimeData()->data( MIME_DO_COPY ).data() ).toBool(); } // Check if the drop triggers a palette interaction. bool isPaletteDrop = event->mimeData()->hasFormat( MIME_PALETTE_ID ); QGraphicsItem * draggedItem = 0; int paletteId = -1; if ( isPaletteDrop ) { paletteId = event->mimeData()->data( MIME_PALETTE_ID ).toInt(); draggedItem = (QGraphicsItem*)((const void *) event->mimeData()->data( MIME_PALETTE_ITEM )); } if ( (!isPaletteDrop) || (!QPaletteManager::instance()->drop( scene() , paletteId , draggedItem ) ) ) { // The drop didn't triggered a palette interaction. // If the QMimeData tells that the drop comes from the main scene, then // the QMimeData also contains the dragged item pointer. if ( event->mimeData()->hasFormat( FROM_SCENE_DRAG_MIME ) ) { droppedItem = (QLanguageItem*)((const void *) event->mimeData()->data( FROM_SCENE_DRAG_MIME )); // Move the item to the drop position, and get the resulting movement coordinate. QPointF movementValue = droppedItem->moveItem( mapToScene( event->pos() ) ); // Move all other selected item of the scene by the same (dx,dy). QList selectedItems = mMainWindow->selectedLanguageItems(); QList otherSelectedItems(selectedItems); otherSelectedItems.removeAll( droppedItem ); for ( int i = 0 ; i < otherSelectedItems.size() ; i++ ) otherSelectedItems[i]->moveBy( movementValue.x() , movementValue.y() ); if ( doCopy ) { // The "copy flag" is on: QList copiedItems; for ( int i = 0 ; i < selectedItems.size() ; i++ ) { // 1. copy all the moved items (storing their respective copies in a list) copiedItems << mMainWindow->addItemCopy(selectedItems[i]); // 2. then put them back to their original position, selectedItems[i]->moveBy( -movementValue.x() , -movementValue.y() ); } // 3. then select all the copied items. scene()->clearSelection(); for ( int i = 0 ; i < copiedItems.size() ; i++ ) copiedItems[i]->setSelected( true ); } } else { // The drop comes whether: // - from the OS file explorer, // - from the side-bar scenes // create a new item according to the content of the QMimeData. // (the mainWindow handles this operation) mMainWindow->dropItem( event->mimeData() , pos , &droppedItem ); } } event->accept(); } //------------------------------------------------------------------------------------------------------------------------ void LanguageGraphicsView::dragMoveEvent(QDragMoveEvent* event) { event->acceptProposedAction(); // If we are dragging a "Palette Enabled" item if ( event->mimeData()->hasFormat( MIME_PALETTE_ID ) ) { // Get the paletteId and the dragged item... int paletteId = event->mimeData()->data( MIME_PALETTE_ID ).toInt(); QGraphicsItem * draggedItem = (QGraphicsItem*)((const void *) event->mimeData()->data( MIME_PALETTE_ITEM )); // ... and notify the QPaletteManager that we are moving it, so it can, if necessary, activate the palette. QPaletteManager::instance()->move( mapToScene( event->pos() ) , scene() , paletteId , draggedItem ); } } //------------------------------------------------------------------------- void LanguageGraphicsView::mouseMoveEvent( QMouseEvent * event ) { QGraphicsView::mouseMoveEvent(event); QPointF posSceneCoords = mMainWindow->mGraphicsView->mapToScene( event->pos() ); mMainWindow->updateCursorPos( posSceneCoords ); } FaustWorks-0.4/MainWindowObjects.h0000755000175000017500000001264312130743520015674 0ustar miramira/* * MainWindowObjects.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef MAINWINDOW_OBJECTS_H #define MAINWINDOW_OBJECTS_H #include #include #include #include #include //#include "ui_ResolutionDialog.h" #include #include class QItemResizer; class GraphicsSceneMainWindow; class QLanguageItem; class QLanguageItemFactory; //------------------------------------------------------------------------------------------------------------------------ class QSideBarGraphicsView : public QGraphicsView { public : QSideBarGraphicsView(QGraphicsScene * s , QLanguageItemFactory* factory ); virtual ~QSideBarGraphicsView() {} virtual void addItem( QLanguageItem * container ) = 0; QLanguageItem * find(const QLanguageItem * other ); virtual QString domId() = 0; virtual QString mimeId() = 0; virtual QDomElement save(QDomDocument &d); virtual bool load( const QDomElement& root ); virtual void clear(); void removeItem( QGraphicsItem * item ); protected : void setupContainer( QLanguageItem * container ); QList mAddedItems; QLanguageItemFactory* mFactory; }; //------------------------------------------------------------------------------------------------------------------------ class QHistoryGraphicsView : public QSideBarGraphicsView { public : QHistoryGraphicsView(QGraphicsScene * s , QLanguageItemFactory* factory ); virtual ~QHistoryGraphicsView() {} void addItem( QLanguageItem * container ); virtual void clear(); QString domId(); QString mimeId(); protected : void reorderItems(); void resizeEvent( QResizeEvent * e ); }; //------------------------------------------------------------------------------------------------------------------------ class QStorageGraphicsView : public QSideBarGraphicsView { Q_OBJECT public : QStorageGraphicsView( QGraphicsScene * s , GraphicsSceneMainWindow * mainWindow , QLanguageItemFactory * factory ); virtual ~QStorageGraphicsView() {} void addItem( QLanguageItem * container ); QString domId(); QString mimeId(); protected Q_SLOTS: void sceneChanged(const QList &); protected : // void mousePressEvent( QMouseEvent * event ); void resizeEvent( QResizeEvent * ); void dragEnterEvent(QDragEnterEvent* event); void dragMoveEvent(QDragMoveEvent* event); void dragLeaveEvent(QDragLeaveEvent* event); void dropEvent(QDropEvent* event); void focusOutEvent( QFocusEvent * event ); void focusInEvent( QFocusEvent * event ); void reorderItems(); QList filterItems(const QList& list); GraphicsSceneMainWindow * mMainWindow; int mPreferredWidth; }; //------------------------------------------------------------------------------------------------------------------------ class QBackgroundItem : public QGraphicsItem { public: QBackgroundItem( GraphicsSceneMainWindow * mainWindow , const QSizeF& size ); virtual ~QBackgroundItem() {} void setRect( const QRectF& size ); QRectF boundingRect() const; QRectF pageRectInSceneCoords() const; void setPageSize( const QSizeF& size ); QSizeF pageSize() const; void setResizeEnabled( bool isEnabled ); bool isResizeEnabled() const; protected: void paint ( QPainter * painter, const QStyleOptionGraphicsItem * , QWidget * ); void updatePageRect(); QRectF mRect; QGraphicsRectItem * mPage; QItemResizer * mBackgroundItemResizer; bool mIsResizeEnabled; }; //------------------------------------------------------------------------------------------------------------------------ class LanguageTextEdit : public QTextEdit { Q_OBJECT public : LanguageTextEdit(const QString& initString , GraphicsSceneMainWindow * mainWindow); virtual ~LanguageTextEdit() {} Q_SIGNALS: void enabled( bool isEnabled ); protected : void changeEvent ( QEvent * event ); void wheelEvent( QWheelEvent * e ); void focusOutEvent( QFocusEvent * event ); void dragEnterEvent(QDragEnterEvent* event); void dragMoveEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); GraphicsSceneMainWindow * mMainWindow; }; //------------------------------------------------------------------------------------------------------------------------ class LanguageGraphicsView : public QGraphicsView { public: LanguageGraphicsView(); virtual ~LanguageGraphicsView() {} void setMainWindow( GraphicsSceneMainWindow * mainWindow ); QSize sizeHint () const; protected: void dragEnterEvent(QDragEnterEvent* event); void dragLeaveEvent(QDragLeaveEvent* event); void dragMoveEvent(QDragMoveEvent* event); void dropEvent(QDropEvent* event); void mouseMoveEvent(QMouseEvent * event); GraphicsSceneMainWindow * mMainWindow; }; #endif FaustWorks-0.4/Makefile0000644000175000017500000000364412130743520013573 0ustar miramirasystem := $(shell uname -s) qm4 := $(shell which qmake-qt4) qm := $(if $(qm4),$(qm4),qmake) VERSION="0.4" DISTRIB=FaustWorks-$(VERSION) TMPDIR=$(DISTRIB)-Distribution ifeq ($(system), Darwin) SPEC := -spec macx-llvm DST := "FaustWorks.app/Contents/" else SPEC := "" PREFIX := /usr endif all : Makefile.qt4 make -f Makefile.qt4 install : install-$(system) uninstall : uninstall-$(system) install-Linux : install FaustWorks $(PREFIX)/bin install faustworks.desktop $(PREFIX)/share/applications/ install Resources/faustworks.xpm $(PREFIX)/share/pixmaps/ install Resources/faustworks.png $(PREFIX)/share/icons/hicolor/32x32/apps/ install Resources/faustworks.svg $(PREFIX)/share/icons/hicolor/scalable/apps/ uninstall-Linux : rm -f $(PREFIX)/bin/FaustWorks rm -f $(PREFIX)/share/applications/faustworks.desktop rm -f $(PREFIX)/share/pixmaps/faustworks.xpm rm -f $(PREFIX)/share/icons/hicolor/32x32/apps/faustworks.png rm -f $(PREFIX)/share/icons/hicolor/scalable/apps/faustworks.svg install-Darwin : cp -r FaustWorks.app /Applications dmg : $(DISTRIB).dmg $(DISTRIB).dmg : all rm -rf $(TMPDIR) mkdir $(TMPDIR) cp -r FaustWorks.app $(TMPDIR) macdeployqt $(TMPDIR)/FaustWorks.app/ rm -rf $(DISTRIB).dmg hdiutil create $(DISTRIB).dmg -srcfolder $(TMPDIR) rm -rf $(TMPDIR) # make a FaustWorks distribution by cloning the git repository clonedist : git clone git://faudiostream.git.sourceforge.net/gitroot/faudiostream/FaustWorks FaustWorks-$(version) rm -rf FaustWorks-$(version)/.git rm -f FaustWorks-$(version).tar.gz tar czfv FaustWorks-$(version).tar.gz FaustWorks-$(version) rm -rf FaustWorks-$(version) # make a FaustWorks source distribution using git archive distribution : git archive -o $(DISTRIB).zip HEAD clean : Makefile.qt4 make -f Makefile.qt4 clean rm -f FaustWorks.pro.user rm -rf FaustWorks.app rm -f $(DISTRIB).dmg rm -f $(DISTRIB).zip Makefile.qt4: $(qm) $(SPEC) -o Makefile.qt4 FaustWorks-0.4/MusicNotationHighlighter.cpp0000755000175000017500000001013012130743520017601 0ustar miramira/* * MusicNotationHighligher.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "MusicNotationHighlighter.h" //------------------------------------------------------------------------- void MusicNotationHighlighter::appendLineRule(const QStringList& patterns, const QTextCharFormat& format, bool setMinimal=false) { mLastFormat = format; foreach (QString pattern, patterns) { QRegExp rx=QRegExp(pattern); rx.setMinimal(setMinimal); mLineRule.pattern = rx; mLineRule.format = format; mHighlightingLineRules.append(mLineRule); } } //------------------------------------------------------------------------- void MusicNotationHighlighter::appendMultilineRule(const QString& startPattern, const QString& endPattern, const QTextCharFormat& format, bool) { mLastFormat = format; QRegExp srx=QRegExp(startPattern); QRegExp erx=QRegExp(endPattern); mMultiLineRule.startPattern = srx; mMultiLineRule.endPattern=erx; mMultiLineRule.format = format; mHighlightingMultilineRules.append(mMultiLineRule); } //------------------------------------------------------------------------- MusicNotationHighlighter::MusicNotationHighlighter(QTextDocument *parent) :QSyntaxHighlighter(parent) {} //------------------------------------------------------------------------- MusicNotationHighlighter::~MusicNotationHighlighter() {} //------------------------------------------------------------------------- void MusicNotationHighlighter::highlightLine(const QString& text,bool ) { foreach (HighlightingLineRule rule, mHighlightingLineRules) { QRegExp expression(rule.pattern); int index = text.indexOf(expression); while (index >= 0) { int length = expression.matchedLength(); setFormat(index, length, rule.format); index = text.indexOf(expression, index + length); } } } //------------------------------------------------------------------------- bool MusicNotationHighlighter::highlightMultiline(const QString& text ) { bool result = false; for(int i=0;i= 0) { result = true; int endIndex = text.indexOf(mHighlightingMultilineRules[i].endPattern, startIndex); int commentLength; if (endIndex == -1) { setCurrentBlockState(IN_BLOCK); commentLength = text.length() - startIndex; } else { commentLength = endIndex - startIndex + mHighlightingMultilineRules[i].endPattern.matchedLength(); } setFormat( startIndex, commentLength, mHighlightingMultilineRules[i].format ); startIndex = text.indexOf(mHighlightingMultilineRules[i].startPattern, startIndex + commentLength); } } return result; } #include //------------------------------------------------------------------------- void MusicNotationHighlighter::highlightBlock ( const QString & text ) { highlightLine(text,false); highlightMultiline(text); } //------------------------------------------------------------------------- QTextCharFormat MusicNotationHighlighter::buildTextCharFormat( const QColor& foreground , const QColor& background , QFont::Weight fontWeight ) { QTextCharFormat result; result.setForeground( foreground ); result.setBackground( background ); result.setFontWeight( fontWeight ); return result; } FaustWorks-0.4/MusicNotationHighlighter.h0000755000175000017500000000456012130743520017260 0ustar miramira/* * MusicNotationHighligher.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef MNHIGHLIGHTER_H_ #define MNHIGHLIGHTER_H_ #include #include #include #include typedef enum BlockState { OUTOFF_BLOCK=0, IN_BLOCK } BlockState ; class MusicNotationHighlighter : public QSyntaxHighlighter { public: MusicNotationHighlighter(QTextDocument *parent = 0); virtual ~MusicNotationHighlighter(); void highlightBlock ( const QString & text ); protected: void appendLineRule(const QStringList& patterns, const QTextCharFormat& format, bool setMinimal); void appendMultilineRule(const QString& startPattern, const QString& endPattern, const QTextCharFormat& format, bool setMinimal); void highlightLine(const QString& text,bool useLastBackground); bool highlightMultiline(const QString& text); static QTextCharFormat buildTextCharFormat( const QColor& foreground , const QColor& background , QFont::Weight fontWeight ); class HighlightingLineRule { public: QRegExp pattern; QTextCharFormat format; }; class HighlightingMultilineRule { public: HighlightingMultilineRule() { currentState=OUTOFF_BLOCK; previousState=OUTOFF_BLOCK; }; QRegExp startPattern; QRegExp endPattern; QTextCharFormat format; BlockState currentState; BlockState previousState; }; QTextCharFormat mLastFormat; HighlightingLineRule mLineRule; HighlightingMultilineRule mMultiLineRule; QVector mHighlightingLineRules; QVector mHighlightingMultilineRules; }; #endif /*MNHIGHLIGHTER_H_*/ FaustWorks-0.4/QFaustItem.cpp0000755000175000017500000010751612130743520014667 0ustar miramira/* * QFaustItem.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QFaustItem.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "QPaletteItem.h" #define PI 3.1415f #define CPP_EXT QString(".cpp") #define DSP_EXT QString(".dsp") #define SVG_FOLDER_EXT QString("-svg") //#define FAUST_KEYWORD "$FAUST" //#define CPP_FILE_KEYWORD "$CPP" #define DSP_FILE_KEYWORD "$DSP" //#define FILE_KEYWORD "$NAME" #define OPTIONS_KEYWORD "$OPTIONS" #define PREFIX QString("/tmp/") #define FILE_MENU "FileMenu" #define IDLE_FLAG 1 #define HIGHLIGHTED_FLAG 2 #define SELECTED_FLAG 3 #define MIME_FAUST_ITEM_RECT_WIDTH "MimeFaustItemRectWidth" #define MIME_FAUST_ITEM_RECT_HEIGHT "MimeFaustItemRectHeight" #define DOM_FAUST_ITEM_RECT_WIDTH "DomFaustItemRectWidth" #define DOM_FAUST_ITEM_RECT_HEIGHT "DomFaustItemRectHeight" QTextEdit* gErrorWindow = 0; static void removeFolder( const QString& folderName ); // Removes recursively any folder or file. //------------------------------------------------------------ static void remove(const QString& name) { if ( QDir( name ).exists() ) { removeFolder(name); } else if ( QFile::exists(name) ) { QFile::remove(name); } } //------------------------------------------------------------ static void removeFolder( const QString& folderName ) { QDir dir( folderName ); QStringList files = dir.entryList(); for (int i = 0; i < files.size(); ++i) { if ( ( files[i] != "." ) && ( files[i] != ".." ) ) remove( folderName + "/" + files[i] ); } QDir d; d.rmdir ( folderName ); } //------------------------------------------------------------ static void copyFolder( const QString& folderName , const QString& newName ) { removeFolder( newName ); QDir dir( folderName ); QStringList files = dir.entryList(); QDir newDir; newDir.mkdir (newName); for (int i = 0; i < files.size(); ++i) { QFile::copy( folderName + "/" + files[i] , newName + "/" + files[i] ); } } //------------------------------------------------------------------------ // QBuildItem class // //------------------------------------------------------------------------ class QBuildItem : public QGraphicsRectItem { public : QBuildItem( float ballSize , float radius , int ballNb , int rotationPeriod , QGraphicsItem * parent = 0 ) : QGraphicsRectItem( parent ) { float rectSize = radius * 2 + ballSize; setRect( QRectF( -rectSize/2.0f , -rectSize/2.0f , rectSize , rectSize ) ); setPen( Qt::NoPen ); setBrush( Qt::NoBrush ); for ( int i = 0 ; i < ballNb ; i++ ) { QAbstractGraphicsShapeItem * ball = new QGraphicsEllipseItem( -ballSize/2.0f, -ballSize/2.0f, ballSize , ballSize ); ball->setParentItem( this ); ball->setPos( radius * qCos( i * ( 2*PI / float(ballNb) ) ) , radius * qSin( i * ( 2*PI / float(ballNb) ) ) ); ball->setPen( Qt::NoPen ); ball->setBrush( QBrush( Qt::red ) ); ball->setVisible( false ); mBalls << ball; } int frameCount = int(rotationPeriod / 100.0f); mAnimationTimeLine = new QTimeLine(rotationPeriod); mAnimationTimeLine->setFrameRange(0, frameCount ); mAnimationTimeLine->setLoopCount( 0 ); mAnimationTimeLine->setCurveShape( QTimeLine::LinearCurve ); mAnimation = new QGraphicsItemAnimation(); mAnimation->setItem(this); mAnimation->setTimeLine(mAnimationTimeLine); for (int i = 0; i < frameCount; ++i) mAnimation->setRotationAt(i / float(frameCount) , i * 360.0f / float(frameCount) ); QGraphicsEllipseItem * ellipseItem = new QGraphicsEllipseItem( rect() ); ellipseItem->setParentItem( this ); ellipseItem->setPen( Qt::NoPen ); ellipseItem->setBrush( QBrush( Qt::green ) ); ellipseItem->setVisible( false ); mIdleItem = ellipseItem; } ~QBuildItem() { delete mAnimation; delete mAnimationTimeLine; } void start() { // mIdleItem->setVisible( false ); showBalls( true ); mAnimationTimeLine->start(); } void done() { // mIdleItem->setVisible( true ); showBalls( false ); mAnimationTimeLine->stop(); } void error() { // mIdleItem->setVisible( true ); showBalls( false ); mAnimationTimeLine->stop(); } protected : void showBalls( bool areShown ) { for ( int i = 0 ; i < mBalls.size() ; i++ ) mBalls[i]->setVisible( areShown ); } QTimeLine * mAnimationTimeLine; QGraphicsItemAnimation * mAnimation; QList mBalls; QGraphicsItem * mIdleItem; }; //------------------------------------------------------------------------ // Public functions // //------------------------------------------------------------------------ //------------------------------------------------------------------------- QFaustItem::QFaustItem(QGraphicsItem * parent) : QLanguageItem( parent ) { init(); } //------------------------------------------------------------------------- QFaustItem::QFaustItem(const QMimeData * mimeData , QGraphicsItem * parent ) : QLanguageItem( parent ) { init(mimeData); } //------------------------------------------------------------------------- QFaustItem::QFaustItem(const QDomElement * domElement , QGraphicsItem * parent ) : QLanguageItem( parent ) { init(domElement); } //------------------------------------------------------------------------- QFaustItem::QFaustItem(const QFaustItem * other , QGraphicsItem * parent ) : QLanguageItem( parent ) { init(other); } //------------------------------------------------------------------------- QFaustItem::~QFaustItem() { cleanFiles(); } //------------------------------------------------------------ void QFaustItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * , QWidget *) { // qDebug( "QFaustItem::paint : %02X" , this); painter->setPen( pen() ); painter->setBrush( brush() ); painter->drawRect( rect() ); } //------------------------------------------------------------ bool QFaustItem::setCode( const QString& code ) { // qDebug() << "QFaustItem::setCode : code = " << code; if ( code == mCode ) return true; mCode = code; // qDebug() << "QFaustItem::setCode : " << dspFile(); QFile * file0 = new QFile( dspFile() ); if (!file0->open(QIODevice::WriteOnly | QIODevice::Text)) return false; QTextStream out(file0); out << mCode; delete file0; #ifdef WIN32 //This is a bug : //On Windows, we need to call the svg generation command twice, //the first one to create the folder, the second one to create //the SVG files. if ( !generateSVG() ) return false; #endif if ( !generateSVG() ) return false; if ( mIsValid ) { mSVGRenderer.load( svgRootFile() ); mSVGItem->setSharedRenderer(&mSVGRenderer); faustUpdateGeometry( rect() ); //faustUpdateGeometry( QRect( 0 , 0 , mSVGItem->boundingRect().width() * mSVGItem->transform().m11() , mSVGItem->boundingRect().height() * mSVGItem->transform().m22() ) ); generateCPP(); } codeChanged(); return isValid(); } //------------------------------------------------------------ QString QFaustItem::code() const { return mCode; } //------------------------------------------------------------ QString QFaustItem::lastErrorMessage() const { return "Invalid Faust Code"; } //------------------------------------------------------------ bool QFaustItem::isValid() const { return mIsValid; } //------------------------------------------------------------------------ // Protected functions // //------------------------------------------------------------------------ //------------------------------------------------------------ void QFaustItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * ) { runBinary(); } //------------------------------------------------------------ void QFaustItem::connectNotify ( const char * signal ) { // It is possible that the launchScriptError signal is emitted // before that the connection is made, so we re-emit it if necessary. if (QLatin1String(signal) == SIGNAL(launchScriptError(const QString&))) { if ( mBuildError ) Q_EMIT launchScriptError( mItemBuildCommand ); } } /** * Run the binary code associated to a Faust item (if any) */ //------------------------------------------------------------ void QFaustItem::runBinary() { if (mBinaryFiles.size() > 0) { QString bin = mBinaryFiles[0]; //Little hack to use .app on MacosX. qDebug () << bin; if ( bin.right(4) == ".app" ) { bin = "open " + bin ; } QProcess::startDetached ( bin); } else { QMessageBox msgBox; msgBox.setText("Faust Item has no binary to execute"); msgBox.exec(); } } /** * Explore the SVG block-diagram using the appropriate desktop application */ void QFaustItem::exploreSVG () { QString filename = QFileInfo(svgRootFile()).absoluteFilePath(); QUrl url = QUrl::fromLocalFile(filename); qDebug() << "QDesktopServices::openUrl (" << url << ")" ; bool b = QDesktopServices::openUrl(url); if (!b) { qDebug() << "ERROR : Can't open the SVG URL " << url ; } } /** * Call external script to generate and view mathematical documentation */ void QFaustItem::generateMath () { QProcess qproc; QString cmd = "faust2mathviewer " + dspFileQuotedSpecial(); bool b = qproc.startDetached(cmd); qDebug() << cmd; if (!b) { qDebug() << "ERROR : Can't generate math doc " ; } } /** * Call external script to generate and view internal Loop DAG */ void QFaustItem::generateLoopGraph () { QProcess qproc; QString cmd = "faust2graphviewer " + dspFileQuotedSpecial(); bool b = qproc.startDetached(cmd); qDebug() << cmd; if (!b) { qDebug() << "ERROR : Can't generate DAG view " ; } } /** * Call external script to generate and view internal signal directed graph */ void QFaustItem::generateSigGraph () { QProcess qproc; QString cmd = "faust2sigviewer " + dspFileQuotedSpecial(); bool b = qproc.startDetached(cmd); qDebug() << cmd; if (!b) { qDebug() << "ERROR : Can't generate signal graph view " ; } } //------------------------------------------------------------ void QFaustItem::resized( const QRectF& newRect ) { // qDebug() << "QFaustItem::resized : " << rect() << " -> " << newRect; if ( newRect.toRect() == rect().toRect() ) return; moveBy( newRect.x() , newRect.y() ); faustUpdateGeometry( QRect(0,0, newRect.width(), newRect.height())); Q_EMIT scaleChanged( currentScale() ); } extern QMainWindow* gMainWin; //------------------------------------------------------------ bool QFaustItem::generateSVG() { // qDebug() << "QFaustItem::generateSVG() : " << mFaustPath + " -svg " + dspFileQuoted(); QProcess faustProcess; faustProcess.start( mFaustPath + " -svg -blur " + " " + dspFileQuoted() ); if (!faustProcess.waitForStarted()) return false; if (!faustProcess.waitForFinished()) return false; mIsValid = ( faustProcess.exitCode() == 0 ); // traitement des erreurs if (!gErrorWindow) { gErrorWindow = new QTextEdit(gMainWin); gErrorWindow->setWindowFlags(Qt::WindowStaysOnTopHint|Qt::Tool ); gErrorWindow->setFontPointSize(10); gErrorWindow->setTextInteractionFlags(Qt::NoTextInteraction); gErrorWindow->ensureCursorVisible(); //gErrorWindow->setWindowTitle("Invalid Faust Code"); } if (faustProcess.exitCode()) { gErrorWindow->setWindowTitle(tr("Invalid Faust Code")); gErrorWindow->show(); gErrorWindow->append(QString(faustProcess.readAllStandardError())); gErrorWindow->append("--------------------\n"); qDebug() << "des erreurs"; //qDebug() << faustProcess.readAllStandardError(); } else { gErrorWindow->setWindowTitle(tr("Faust Code OK")); } return true; } //------------------------------------------------------------------------- static QString getFileContent(const QString& fileName) { if ( !QFile::exists(fileName) ) return ""; QString content = ""; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { file.close(); return ""; } while (!file.atEnd()) { QByteArray line = file.readLine(); content += QString::fromUtf8(line); } file.close(); return content; } //------------------------------------------------------------ bool QFaustItem::generateCPP() { QProcess faustProcess; mItemBuildOptions = QFaustItem::mBuildOptions; faustProcess.start( mFaustPath + " -o " + cppFileQuoted() + " " + QFaustItem::mBuildOptions + " " + dspFileQuoted() ); if (!faustProcess.waitForStarted()) { mCppCode = ""; return false; } if (!faustProcess.waitForFinished()) { mCppCode = ""; return false; } mCppCode = getFileContent( cppFile() ); return true; } //------------------------------------------------------------ void QFaustItem::checkBinary() { if ( interpretCommand( QFaustItem::mBuildCommand ) != mItemBuildCommand ) { if ( !isModified() ) { generateBinary(); } } if ( QFaustItem::mBuildOptions != mItemBuildOptions ) { generateCPP(); } } //------------------------------------------------------------ void QFaustItem::setModified( bool modified ) { if ( isModified() != modified ) { QLanguageItem::setModified( modified ); if ( modified ) cleanBinaries(); else generateBinary(); } } //------------------------------------------------------------ bool QFaustItem::generateBinary() { if ( file().length() == 0 ) return true; if ( code().length() == 0 ) return true; if ( mBuildCommand.length() == 0 ) return true; if ( mBuildProcess ) { mBuildProcess->waitForFinished(); } cleanBinaries(); mIsBinaryReady = false; mBuildProcess = new QProcess(); connect( mBuildProcess , SIGNAL( finished ( int , QProcess::ExitStatus ) ) , this , SLOT( buildFinished ( int , QProcess::ExitStatus ) ) ); qDebug() << "mItemBuildCommand[1] = " << mItemBuildCommand; mItemBuildCommand = interpretCommand( mBuildCommand ); qDebug() << "mItemBuildCommand[2] = " << mItemBuildCommand; mBuildProcess->start( mItemBuildCommand ); if (!mBuildProcess->waitForStarted()) { Q_EMIT launchScriptError( mItemBuildCommand ); mBuildError = true; delete mBuildProcess; mBuildProcess = 0; return false; } mBuildError = false; mBuildAnimationItem->start(); return true; } //------------------------------------------------------------ QVariant QFaustItem::itemChange( GraphicsItemChange change, const QVariant& value ) { QVariant result = QLanguageItem::itemChange( change , value ); if ( change == QGraphicsItem::ItemSelectedHasChanged ) { if ( value.toBool() ) { checkBinary(); } mPenBrushSwitcher.setFlag(SELECTED_FLAG, value.toBool() ); updatePenAndBrush(); } return result; } //------------------------------------------------------------ void QFaustItem::hoverEnterEvent ( QGraphicsSceneHoverEvent * ) { mPenBrushSwitcher.setFlag(HIGHLIGHTED_FLAG, true); updatePenAndBrush(); } //------------------------------------------------------------ void QFaustItem::hoverLeaveEvent ( QGraphicsSceneHoverEvent * ) { mPenBrushSwitcher.setFlag(HIGHLIGHTED_FLAG, false); updatePenAndBrush(); } //------------------------------------------------------------ QImage* QFaustItem::buildDragImage() { return new QImage( itemToImage( this , 1.0f , 0 , true ) ); } //------------------------------------------------------------ QMimeData * QFaustItem::buildMimeData() { QMimeData * result = QLanguageItem::buildMimeData(); result->setData( MIME_FAUST_ITEM_RECT_WIDTH , QByteArray::number(rect().width()) ); result->setData( MIME_FAUST_ITEM_RECT_HEIGHT , QByteArray::number(rect().height()) ); if ( !mIsStorageModeOn ) { QStringList copiedFile; QString extension; bool isDir = false; switch ( QFaustItem::mDroppedFileType ) { case DROP_CPP: copiedFile << cppFile(); extension = CPP_EXT; break; case DROP_SVG: copiedFile << svgFolder(); extension = SVG_FOLDER_EXT; isDir = true; break; case DROP_BINARY: { if ( mIsBinaryReady ) { QList binariesUrls; for ( int i = 0 ; i < mBinaryFiles.size() ; i++ ) { binariesUrls << QUrl::fromLocalFile( QFileInfo( mBinaryFiles[i] ).absoluteFilePath() ); } result->setUrls( binariesUrls ); } return result; } case DROP_DSP: copiedFile << dspFile(); extension = DSP_EXT; break; } QList urls; for ( int i = 0 ; i < copiedFile.size() ; i++ ) { QString fileName = PREFIX + mIdString + "/" + itemName() + extension; if ( !isDir ) { QFile::remove( fileName ); QFile::copy( copiedFile[i] , fileName ); } else copyFolder( copiedFile[i] , fileName ); urls << QUrl::fromLocalFile( QFileInfo( fileName ).absoluteFilePath() ); } result->setUrls( urls ); } return result; } //------------------------------------------------------------ float QFaustItem::currentScale() const { return mSVGItem->transform().m11(); } /** * Fonction called at the end of the build process that checks if all the resulting files * have been properly created. */ void QFaustItem::buildFinished ( int exitCode, QProcess::ExitStatus exitStatus ) { // qDebug() << "QFaustItem::buildFinished"; if ( exitStatus == QProcess::NormalExit ) { if ( exitCode == 0 ) { // qDebug() << "QFaustItem::buildFinished : return 0"; mIsBinaryReady = true; mBuildAnimationItem->done(); //----- list files names { mBinaryFiles = QStringList(); QString s = mBuildProcess->readAllStandardOutput(); int n = s.length(); QString f; //filename under construction int i = 0; // current position int state = 0; // state of the state-machine while(ierror(); Q_EMIT buildError( SCRIPT_ERROR , mBuildProcess->readAllStandardError() ); } } else { //Error with executable. mBuildAnimationItem->error(); // qDebug() << "QFaustItem::buildFinished : error"; Q_EMIT buildError( SCRIPT_CRASHED , mBuildProcess->readAllStandardError() ); } delete mBuildProcess; mBuildProcess = 0; } #define TITLE_BAR_TEXT_MARGIN 5 //------------------------------------------------------------ void QFaustItem::updateNameLabel() { if ( !mIsStorageModeOn ) { QString baseName = getDescriptiveFileName(); mFileNameItem->setText( baseName ); QString truncString = "..."; int skippedChar = truncString.length() + 1; while ( ( mFileNameItem->boundingRect().width() > rect().width() - TITLE_BAR_TEXT_MARGIN ) && ( skippedChar < baseName.length() ) ) { mFileNameItem->setText( baseName.left( baseName.length() - skippedChar ) + truncString ); skippedChar++; } mFileNameItem->setPos( ( rect().width() - mFileNameItem->boundingRect().width() )/2.0f , 0 ); } } /* //------------------------------------------------------------ void QFaustItem::centerSVGItem() { QRectF r = mapFromItem( mSVGItem , mSVGItem->boundingRect() ).boundingRect(); float xScaleFactor = ( ( r.width() - mPenWhenSelected.width() ) / r.width() ); float yScaleFactor = ( ( r.height() - mPenWhenSelected.width() ) / r.height() ); mSVGItem->scale(xScaleFactor / mSVGItem->transform().m11() , yScaleFactor / mSVGItem->transform().m22() ); float halfPenWidth = mPenWhenSelected.width() / 2.0f; mSVGItem->setPos( halfPenWidth , halfPenWidth ); } */ //------------------------------------------------------------ QString QFaustItem::svgFolder() const { QString p = mWorkingDirectory + "/" + tempName() + SVG_FOLDER_EXT; qDebug() << "QFaustItem::svgFolder()" << p; return p; } //------------------------------------------------------------ QString QFaustItem::svgRootFile() const { return svgFolder() + "/process.svg"; } //------------------------------------------------------------ QString QFaustItem::svgRootFileQuoted() const { QString p = "\"" + svgRootFile() + "\""; return p; } //------------------------------------------------------------ QString QFaustItem::cppFile() const { return mWorkingDirectory + "/" + tempName() + CPP_EXT; } //------------------------------------------------------------ QString QFaustItem::cppFileQuoted() const { return "\"" + cppFile() + "\""; } //------------------------------------------------------------ QString QFaustItem::dspFile() const { return mWorkingDirectory + "/" + tempName() + DSP_EXT; // return mWorkingDirectory + "/" + tempName(); } //------------------------------------------------------------ QString QFaustItem::dspFileQuoted() const { return "\"" + dspFile() + "\""; } //------------------------------------------------------------ // If file modified but not saved, uses tmp filename otherwise // uses real filename QString QFaustItem::dspFileQuotedSpecial() const { if (isModified()) { return "\"" + dspFile() + "\""; } else { return "\"" + file() + "\""; } } //------------------------------------------------------------ QString QFaustItem::tempName() const { return mTempName; } //------------------------------------------------------------ QString QFaustItem::itemName() const { if ( !file().length() ) return "untitled"; return QFileInfo( file() ).completeBaseName(); } ////------------------------------------------------------------ //QString QFaustItem::namedDSPFile() const //{ // return PREFIX + mIdString + "/" + itemName() + DSP_EXT; //} //------------------------------------------------------------ QString QFaustItem::cppCode() const { return mCppCode; } //------------------------------------------------------------ void QFaustItem::setFile(const QString& f ) { mExName = itemName(); QLanguageItem::setFile( f ); mWorkingDirectory = QFileInfo( f ).dir().absolutePath(); updateName(); //Binaries only available for non-modified file-linked items. if ( ! (file().length()) ) cleanBinaries(); } /* //------------------------------------------------------------ void QFaustItem::cleanFiles() { cleanWorkingDirectoryFiles(); cleanNamedFiles(); } */ //------------------------------------------------------------ void QFaustItem::cleanFiles() { //Remove binaries cleanBinaries(); //Remove all tmp files : tmp.dsp, svg, cpp, ... for ( int i = 0 ; i < mFiles.size() ; i++ ) { remove( mFiles[i] ); } removeFolder( PREFIX + mIdString ); } //------------------------------------------------------------ void QFaustItem::cleanBinaries() { for ( int i = 0 ; i < mBinaryFiles.size() ; i++ ) { remove( mBinaryFiles[i] ); } } //------------------------------------------------------------ void QFaustItem::init() { mSVGItem = new QGraphicsSvgItem(this); mSVGItem->setSharedRenderer( &mSVGRenderer ); //#if !linux // bug in Qt 4.4 with the linux cache mode mSVGItem->setCacheMode( QGraphicsItem::DeviceCoordinateCache ); //#endif mWorkingDirectory = PREFIX + "."; mItemId = QFaustItem::mCount++; updateName(); mBuildError = false; mBuildProcess = 0; setupAnimation(); connect( this, SIGNAL( descriptiveNameChanged() ), this , SLOT( updateNameLabel() ) ); setAcceptsHoverEvents(true); // mPenBrushSwitcher.addFlag(IDLE_FLAG, 0, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,50) , 3) , QBrush(QColor(FAUST_ITEM_BASE_RGB,50)) ) ); // mPenBrushSwitcher.addFlag(HIGHLIGHTED_FLAG, 1, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,100) , 3) , QBrush(QColor(FAUST_ITEM_BASE_RGB,100)) ) ); // mPenBrushSwitcher.addFlag(SELECTED_FLAG, 2, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,255) , 3) , QBrush(QColor(FAUST_ITEM_BASE_RGB,100)) ) ); //mPenBrushSwitcher.addFlag(IDLE_FLAG, 0, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,50) , 3) ) ); mPenBrushSwitcher.addFlag(IDLE_FLAG, 0, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,0) , 3) ) ); // pas de bord jaune quand l'item n'est pas selectionné mPenBrushSwitcher.addFlag(HIGHLIGHTED_FLAG, 1, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,100) , 3) ) ); // le bord devient visible quand on passe sur l'item mPenBrushSwitcher.addFlag(SELECTED_FLAG, 2, PenBrush( QPen(QColor(FAUST_ITEM_BASE_RGB,255) , 3) ) ); mPenBrushSwitcher.setFlag(IDLE_FLAG, true); updatePenAndBrush(); mFileNameItem = new QGraphicsSimpleTextItem(this); // mFileNameItem = new QTextPathItem( getDescriptiveFileName() , true , Qt::black , "Arial" , 1.0f , this ); mFileNameItem->setZValue(2); QLanguageItem::plug( new QPaletteItemDropper( FAUST_ITEM_PALETTE , QList() << FAUST_ITEM_PALETTE , this , this ) ); faustUpdateGeometry( QRect(0,0,100,100) ); } //------------------------------------------------------------ void QFaustItem::init(const QMimeData * mimeData) { init(); QLanguageItem::load( mimeData ); // Load specific QFaustItem data resized( QRect( 0,0, mimeData->data( MIME_FAUST_ITEM_RECT_WIDTH ).toFloat(), mimeData->data( MIME_FAUST_ITEM_RECT_HEIGHT ).toFloat() ) ); } //------------------------------------------------------------ void QFaustItem::init(const QDomElement * domElement) { init(); QLanguageItem::load( domElement ); // Load specific QFaustItem data resized( QRect( 0,0, QVariant( domElement->attribute( DOM_FAUST_ITEM_RECT_WIDTH, "100" )).toDouble(), QVariant( domElement->attribute( DOM_FAUST_ITEM_RECT_HEIGHT, "100" )).toDouble() ) ); } //------------------------------------------------------------ void QFaustItem::init(const QFaustItem * other) { init(); QLanguageItem::load( other ); // Load specific QFaustItem data resized( other->rect() ); } //------------------------------------------------------------ QDomElement QFaustItem::saveToDomElement( QDomDocument * doc) { QDomElement result = QLanguageItem::saveToDomElement(doc); result.setAttribute( DOM_FAUST_ITEM_RECT_WIDTH, rect().width() ); result.setAttribute( DOM_FAUST_ITEM_RECT_HEIGHT, rect().height() ); return result; } //------------------------------------------------------------ void QFaustItem::updateName() { if ( !QDir( PREFIX ).exists() ) { qDebug() << "Make dir" << PREFIX ; QDir().mkdir( PREFIX ); } else { qDebug() << PREFIX << " already exists"; } // qDebug() << "QFaustItem::updateName() : ex : " << mExName << " to " << itemName(); QString exIdString = mIdString; mIdString = itemName() + "." + QVariant( mItemId ).toString(); mTempName = mIdString + ".tmp" /* + DSP_EXT*/; if ( !QDir( PREFIX + mIdString ).exists() ) QDir().mkdir( PREFIX + mIdString ); QStringList exFiles = mFiles; // qDebug() << "exFiles : " << exFiles; /* for ( int i = 0 ; i < mBinaryFiles.size() ; i++ ) { mBinaryFiles[i] = mBinaryFiles[i].replace( mExName , itemName() ); } */ mFiles.clear(); mFiles //D&D files << PREFIX + mIdString + "/" + itemName() + DSP_EXT << PREFIX + mIdString + "/" + itemName() + CPP_EXT << PREFIX + mIdString + "/" + itemName() + SVG_FOLDER_EXT //Tmp dsp << dspFile() //Generated files from tmp Dsp << cppFile() << svgFolder() // //Binaries // << mBinaryFiles ; // qDebug() << "mFiles : " << mFiles; for ( int i = 0 ; i < exFiles.size() ; i++ ) { if ( QDir(exFiles[i]).exists() ) { //Is a directory // qDebug() << "QFaustItem::updateName() : dir renamed " << exFiles[i] << " -> " << mFiles[i]; QDir().rename( exFiles[i] , mFiles[i] ); } else { // qDebug() << "QFaustItem::updateName() : file renamed " << exFiles[i] << " -> " << mFiles[i]; QFile::rename( exFiles[i] , mFiles[i] ); } } if ( QDir(PREFIX + exIdString).exists() && exIdString.length() ) { // qDebug() << "QFaustItem::updateName() : removed : " << PREFIX + exIdString; removeFolder( PREFIX + exIdString ); } } //------------------------------------------------------------ void QFaustItem::updatePenAndBrush() { setPen( mPenBrushSwitcher.activeObject().mPen ); setBrush( mPenBrushSwitcher.activeObject().mBrush ); } //------------------------------------------------------------ // Create the shell command that translates the dsp code // into binary code QString QFaustItem::interpretCommand(const QString& command) const { QString result; // if (command.startsWith("/")) // { // result = command; // } else { // result = QCoreApplication::applicationDirPath() + "/" + command; // } result = command; result.replace( DSP_FILE_KEYWORD , "\""+file()+"\"" ); result.replace( OPTIONS_KEYWORD , QFaustItem::mBuildOptions ); //QFileInfo fileInfo( file() ); //QString f = file().length() ? fileInfo.absolutePath() + fileInfo.completeBaseName() : "untitled"; return result; } //------------------------------------------------------------ void QFaustItem::setupAnimation() { int ballSize = 4; int radius = 5; int ballNb = 5; mBuildAnimationItem = new QBuildItem( ballSize , radius , ballNb , 2000 , this ); mBuildAnimationItem->setZValue( 10 ); } #define SVG_BORDER_MARGIN 5 //------------------------------------------------------------------------- void QFaustItem::faustUpdateGeometry( const QRectF& newGeometry ) { // qDebug() << "QFaustItem::faustUpdateGeometry : " << newGeometry; // qDebug() << "QFaustItem::faustUpdateGeometry r = : " << mSVGItem->boundingRect(); // QLanguageItem function: setRect, and update related children items' geometry. QLanguageItem::updateGeometry( newGeometry ); // Scale the mSGVItem to fit inside the newGeometry. if ( mSVGItem->boundingRect().isValid() ) { QRectF itemGeometry = mapFromItem( mSVGItem , mSVGItem->boundingRect() ).boundingRect(); float heightRatio = float(rect().height() - 2*SVG_BORDER_MARGIN) / itemGeometry.height() ; float widthRatio = float(rect().width() - 2*SVG_BORDER_MARGIN) / itemGeometry.width(); float minRatio = qMin( heightRatio , widthRatio ); // qDebug() << "QFaustItem::faustUpdateGeometry : transform().m11() = "<< mSVGItem->transform().m11(); mSVGItem->scale( minRatio , minRatio ); itemGeometry = mapFromItem( mSVGItem , mSVGItem->boundingRect() ).boundingRect(); float emptyWidth = rect().width() - itemGeometry.width(); float emptyHeight = rect().height() - itemGeometry.height(); mSVGItem->setPos( emptyWidth/2.0f , emptyHeight/2.0f ); // qDebug() << "QFaustItem::faustUpdateGeometry : transform().m11() = "<< mSVGItem->transform().m11(); } // Move the mBuildAnimationItem to the top-right corner. mBuildAnimationItem->setPos( newGeometry.width() - mBuildAnimationItem->boundingRect().width()/2.0f , newGeometry.height() - mBuildAnimationItem->boundingRect().height()/2.0f ); // Updates the item name label (center it). updateNameLabel(); } //------------------------------------------------------------------------- // Static members /// //------------------------------------------------------------------------- QString QFaustItem::mFaustPath = ""; QString QFaustItem::mBuildCommand = ""; QString QFaustItem::mBuildOptions = ""; int QFaustItem::mDroppedFileType = QFaustItem::DROP_BINARY; int QFaustItem::mCount = 0; //------------------------------------------------------------ void QFaustItem::setFaustPath( const QString& faustPath ) { mFaustPath = faustPath; } //------------------------------------------------------------ void QFaustItem::setBuildCommand( const QString& buildCommand ) { mBuildCommand = buildCommand; } //------------------------------------------------------------ void QFaustItem::setBuildOptions( const QString& buildOptions ) { mBuildOptions = buildOptions; } //------------------------------------------------------------ void QFaustItem::setDroppedFileType( int droppedFileType ) { mDroppedFileType = droppedFileType; } //------------------------------------------------------------------------- QMenu* QFaustItem::buildContextMenu() { QMenu * m = new QMenu(); m->addAction( tr("Save"), this , SLOT(saveItem()) ); m->addAction( tr("Save as..."), this , SIGNAL(saveItemAs()) ); //m->addAction( "Show Faust code", this , SIGNAL(showFaustCode()) ); //m->addAction( "Show C++ code", this , SIGNAL(showCppCode()) ); m->addAction( tr("Browse Diagram"), this , SLOT(exploreSVG()) ); m->addAction( tr("Generate Math"), this , SLOT(generateMath()) ); m->addAction( tr("Generate Loop Graph"), this , SLOT(generateLoopGraph()) ); m->addAction( tr("Generate Signal Graph"), this , SLOT(generateSigGraph()) ); m->addAction( tr("Run Binary"), this , SLOT(runBinary()), QKeySequence(Qt::CTRL + Qt::Key_R) ); return m; } //------------------------------------------------------------ void QFaustItem::save(const QString& fileName) { QLanguageItem::save(fileName); mSaveTime = QTime::currentTime(); // generateBinary(); } //------------------------------------------------------------------------- // MyWebView class /// //------------------------------------------------------------------------- /* //------------------------------------------------------------ MyWebView::MyWebView() { // setWindowModality( Qt::WindowModal ); // setSizePolicy( QSizePolicy::Fixed , QSizePolicy::Fixed ); connect( this , SIGNAL( loadFinished ( bool ) ) , this , SLOT( loadIsFinished(bool) ) ); } #include #define SVG_MARGIN QSize(30,30) //------------------------------------------------------------ void MyWebView::loadIsFinished(bool ) { QSvgWidget w( page()->mainFrame()->url().toLocalFile() ); resize(w.sizeHint() * 1.1f ); } */ FaustWorks-0.4/QFaustItem.h0000755000175000017500000001417212130743520014327 0ustar miramira/* * QFaustItem.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef FAUST_ITEM_H #define FAUST_ITEM_H #include "QLanguageItem.h" #include #include #include #include #include #include #include "QSwitcher.h" #define FAUST_ITEM_PALETTE 1 #define FAUST_ITEM_BASE_RGB 238,219,0 extern QTextEdit* gErrorWindow; class QGraphicsSvgItem; class QBuildItem; class QFaustItem : public QLanguageItem { Q_OBJECT public: enum { SCRIPT_NO_FILE = 0 , SCRIPT_ERROR, SCRIPT_CRASHED, SCRIPT_FILE_NOT_FOUND }; /** * \brief Constructor. */ QFaustItem(QGraphicsItem * parent = 0); QFaustItem(const QMimeData * mimeData , QGraphicsItem * parent = 0); QFaustItem(const QDomElement * domElement , QGraphicsItem * parent = 0); QFaustItem(const QFaustItem * other , QGraphicsItem * parent = 0); ~QFaustItem(); void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget); void save(const QString& fileName); bool setCode( const QString& code ); QString code() const; QString cppCode() const; void checkBinary(); void setModified( bool isModified ); QString lastErrorMessage() const; bool isValid() const; float currentScale() const; Q_SIGNALS: void launchScriptError( const QString& command ); void buildError( int errorType , const QString& msg ); public Q_SLOTS: void runBinary(); // run the binary code of the item void exploreSVG (); // run an external brwoser to explore the SVG block-diagram void generateMath (); // generate mathematical documentation void generateLoopGraph (); // generate internal loop DAG void generateSigGraph (); // generate internal signal graph void resized( const QRectF& newRect ); protected Q_SLOTS: void buildFinished ( int exitCode, QProcess::ExitStatus exitStatus ); void updateNameLabel(); protected: virtual QMenu * buildContextMenu(); void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * ); void connectNotify ( const char * signal ); bool generateSVG(); bool generateCPP(); bool generateBinary(); QString interpretCommand(const QString& command) const; void setupAnimation(); void faustUpdateGeometry( const QRectF& newGeometry ); QString svgFolder() const; QString svgRootFile() const; QString svgRootFileQuoted() const; QString cppFile() const; QString cppFileQuoted() const; QString dspFile() const; QString dspFileQuoted() const; QString dspFileQuotedSpecial() const; QString tempName() const; QString itemName() const; //QString namedDSPFile() const; void setFile(const QString& file); void cleanFiles(); void cleanWorkingDirectoryFiles(); void cleanSVGFiles(); void cleanNamedFiles(); void cleanBinaries(); void init(); void init( const QMimeData * mimeData ); void init( const QDomElement * e ); void init( const QFaustItem * other ); /*! * \brief Specialization of QLanguageItem::saveToDomElement */ QDomElement saveToDomElement( QDomDocument * doc); /*! * \brief Specialization of QLanguageItem::buildMimeData */ QMimeData * buildMimeData(); void updateName(); void updatePenAndBrush(); /*! * \brief QGraphicsItem standard event handler implementation. */ QVariant itemChange( GraphicsItemChange change, const QVariant& value ); /*! * \brief QGraphicsItem standard event handler implementation. */ void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); /*! * \brief QGraphicsItem standard event handler implementation. */ void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); QImage* buildDragImage(); /* * \brief Scales and centers the SVG Item, as it's opaque : we have * to diminish its size to see the selection border's pen. */ // void centerSVGItem(); QGraphicsSvgItem * mSVGItem; QSvgRenderer mSVGRenderer; QGraphicsSimpleTextItem * mFileNameItem; QBuildItem * mBuildAnimationItem; struct PenBrush { QPen mPen; QBrush mBrush; PenBrush(const QPen& p = QPen() , const QBrush& b = QBrush()) { mPen = p; mBrush = b; } }; QSwitcher mPenBrushSwitcher; //QString mDSPFile; QString mFile; QString mCode; QString mCppCode; QString mTempName; QString mWorkingDirectory; QString mItemBuildCommand; QString mItemBuildOptions; QProcess * mBuildProcess; int mItemId; QString mIdString; QString mExName; QStringList mFiles; bool mIsValid; bool mIsBinaryReady; bool mBuildError; QStringList mBinaryFiles; QTime mSaveTime; // updated when saved // -------------------- Static members -------------------- public: static void setFaustPath( const QString& faustPath ); static void setBuildCommand( const QString& buildCommand ); static void setBuildOptions( const QString& buildOptions ); enum DroppedFileType { DROP_SVG = 0 , DROP_CPP , DROP_DSP , DROP_BINARY }; static void setDroppedFileType( int droppedFileType ); protected: static QString mFaustPath; static QString mBuildCommand; static QString mBuildOptions; static int mDroppedFileType; static int mCount; }; #include /* #include #include #include #include class MyWebView : public QWebView { Q_OBJECT public : MyWebView(); protected Q_SLOTS : void loadIsFinished(bool ); }; */ #endif //LANGUAGE_ITEM_H FaustWorks-0.4/QFaustItemFactory.cpp0000755000175000017500000000374412130743520016215 0ustar miramira/* * QFaustItemFactory.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QFaustItemFactory.h" #include #include "QFaustItem.h" //------------------------------------------------------ QLanguageItem * QFaustItemFactory::buildLanguageItem( QGraphicsItem * parent ) { return new QFaustItem( parent ); } //------------------------------------------------------ QLanguageItem * QFaustItemFactory::buildLanguageItem( const QString& fileName , QGraphicsItem * parent ) { QFaustItem * result = new QFaustItem( parent ); result->loadFile( fileName ); return result; } //------------------------------------------------------ QLanguageItem * QFaustItemFactory::buildLanguageItem( const QLanguageItem * other , QGraphicsItem * parent ) { assert(dynamic_cast(other)); QFaustItem * result = new QFaustItem( (QFaustItem*)other , parent ); return result; } //------------------------------------------------------ QLanguageItem * QFaustItemFactory::buildLanguageItem( const QMimeData * mimeData , QGraphicsItem * parent ) { return new QFaustItem( mimeData , parent ); } //------------------------------------------------------ QLanguageItem * QFaustItemFactory::buildLanguageItem( const QDomElement * domElement , QGraphicsItem * parent ) { return new QFaustItem( domElement , parent ); } FaustWorks-0.4/QFaustItemFactory.h0000755000175000017500000000260012130743520015650 0ustar miramira/* * QFaustItemFactory.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef FAUST_ITEM_FACTORY_H #define FAUST_ITEM_FACTORY_H #include "QLanguageItemFactory.h" class QFaustItemFactory : public QLanguageItemFactory { public: QLanguageItem * buildLanguageItem( QGraphicsItem * parent = 0 ); QLanguageItem * buildLanguageItem( const QString& fileName , QGraphicsItem * parent = 0 ); QLanguageItem * buildLanguageItem( const QLanguageItem * other , QGraphicsItem * parent = 0); QLanguageItem * buildLanguageItem( const QMimeData * mimeData , QGraphicsItem * parent = 0); QLanguageItem * buildLanguageItem( const QDomElement * domElement , QGraphicsItem * parent = 0); }; #endif //FAUST_ITEM_FACTORY_H FaustWorks-0.4/QFaustPreferences.cpp0000755000175000017500000002513212130743520016223 0ustar miramira/* * QFaustPreferences.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QFaustPreferences.h" #include "ui_FaustPreferences.h" #include "FaustMainWindow.h" #include #include #include #include //------------------------------------------------------------------------- QFaustPreferences::QFaustPreferences(FaustMainWindow * parent) : QDialog(parent) { mMainWindow = parent; saveSettings(); mUI = new Ui::FaustPreferences(); mUI->setupUi(this); mUI->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setAutoDefault( false ); mUI->buttonBox->button(QDialogButtonBox::Apply)->setAutoDefault( true ); QObject::connect( mUI->buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); QObject::connect( mUI->buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancel())); QObject::connect( mUI->buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), this, SLOT(reset())); QObject::connect( mUI->findFaustPathButton , SIGNAL(clicked()) , this , SLOT(findFaustPath()) ); QObject::connect( mUI->addTargetButton , SIGNAL(clicked()) , this , SLOT(addTarget()) ); QObject::connect( mUI->addOptionButton , SIGNAL(clicked()) , this , SLOT(addOption()) ); updateWidgets(); } //------------------------------------------------------------------------- void QFaustPreferences::reset() { mMainWindow->reinitPreferencesSettings(); updateWidgets(); } //------------------------------------------------------------------------- void QFaustPreferences::findFaustPath() { QString faustPath = QFileDialog::getOpenFileName ( this, "Find faust" , mUI->faustPathEdit->text() ); mUI->faustPathEdit->setText( faustPath ); } #define TARGET_WIDGET "TargetWidget" #define TARGET_NAME "TargetName" #define TARGET_COMMAND "TargetCommand" #define OPTION_WIDGET "OptionWidget" #define OPTION_NAME "OptionName" #define OPTION_COMMAND "OptionCommand" //------------------------------------------------------------------------- void QFaustPreferences::apply() { QSettings settings("grame.fr", "FaustWorks"); settings.setValue( FAUST_PATH_SETTING , mUI->faustPathEdit->text() ); applyConfiguration( TARGETS_SETTING , TARGET_WIDGET , TARGET_NAME , TARGET_COMMAND , mUI->targetsBox ); applyConfiguration( OPTIONS_SETTING , OPTION_WIDGET , OPTION_NAME , OPTION_COMMAND , mUI->optionsBox ); accept(); } //------------------------------------------------------------------------- void QFaustPreferences::cancel() { restoreSettings(); reject(); } //------------------------------------------------------------------------- void QFaustPreferences::addTarget() { addTarget("untitled_target","/path/to/my/Script/myScript $DSP $OPTIONS"); } //------------------------------------------------------------------------- void QFaustPreferences::removeTarget() { QToolButton * removeButton = (QToolButton *)sender(); QWidget * targetWidget = (QWidget *)removeButton->parent(); targetWidget->deleteLater(); updateTabOrder(); } //------------------------------------------------------------------------- void QFaustPreferences::addOption() { addOption("untitled_option","-myOption"); } //------------------------------------------------------------------------- void QFaustPreferences::applyConfiguration( const QString& settingKey , const QString& widgetName , const QString& nameEditName , const QString& commandEditName , QWidget * box ) { QSettings settings("grame.fr", "FaustWorks"); settings.remove( settingKey ); QList targetWidgets = qFindChildren( box , widgetName ); for ( int i = 0 ; i < targetWidgets.size() ; i++) { QList nameEdit = qFindChildren( targetWidgets[i] , nameEditName ); QList commandEdit = qFindChildren( targetWidgets[i] , commandEditName ); assert( nameEdit.size() == 1 ); assert( commandEdit.size() == 1 ); settings.setValue(settingKey + "/" + nameEdit[0]->text() , commandEdit[0]->text() ); } } //------------------------------------------------------------------------- void QFaustPreferences::updateWidgets() { QSettings settings("grame.fr", "FaustWorks"); mUI->faustPathEdit->setText( settings.value( FAUST_PATH_SETTING ).toString() ); updateConfigurationWidgets( TARGETS_SETTING , TARGET_WIDGET , TARGET_NAME , TARGET_COMMAND , mUI->targetsBox ); updateConfigurationWidgets( OPTIONS_SETTING , OPTION_WIDGET , OPTION_NAME , OPTION_COMMAND , mUI->optionsBox ); } //------------------------------------------------------------------------- void QFaustPreferences::updateTabOrder() { setTabOrder( mUI->faustPathEdit , mUI->findFaustPathButton ); } //------------------------------------------------------------------------- void QFaustPreferences::updateConfigurationWidgets( const QString& settingKey , const QString& widgetName , const QString& nameEditName , const QString& commandEditName , QWidget * parent ) { QSettings settings("grame.fr", "FaustWorks"); //Clear targets QList targetWidgets = qFindChildren( parent , widgetName ); for ( int i = 0 ; i < targetWidgets.size() ; i++) { delete targetWidgets[i]; } //Add targets that are in the QSettings. settings.beginGroup(settingKey); QStringList keys = settings.allKeys(); for ( int i = 0 ; i < keys.size() ; i++ ) { QString command = settings.value( keys[i] ).toString(); QString target = keys[i]; addConfigurationLine( target , command , widgetName , nameEditName , commandEditName , parent ); } settings.endGroup(); updateTabOrder(); } //------------------------------------------------------------------------- void QFaustPreferences::addConfigurationLine( const QString& targetName , const QString& targetCommand , const QString& widgetName , const QString& nameEditName , const QString& commandEditName , QWidget * parent ) { QWidget * target = new QWidget(this); target->setObjectName( widgetName ); QSizePolicy p; QLabel * targetNameLabel = new QLabel(tr("Name :") , target); QLineEdit * targetNameEdit = new QLineEdit(targetName , target); targetNameEdit->setObjectName( nameEditName ); p = targetNameEdit->sizePolicy(); p.setHorizontalStretch( 1 ); targetNameEdit->setSizePolicy( p ); QLabel * targetCommandLabel = new QLabel(tr("Command :") , target); QLineEdit *targetCommandEdit= new QLineEdit(targetCommand , target); targetCommandEdit->setObjectName( commandEditName ); p = targetCommandEdit->sizePolicy(); p.setHorizontalStretch( 3 ); targetCommandEdit->setSizePolicy( p ); QToolButton * removeTargetButton = new QToolButton( target ); removeTargetButton->setText( tr("Remove") ); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(targetNameLabel); layout->addWidget(targetNameEdit); layout->addWidget(targetCommandLabel); layout->addWidget(targetCommandEdit); layout->addWidget(removeTargetButton); target->setLayout(layout); p = target->sizePolicy(); p.setVerticalPolicy( QSizePolicy::Fixed ); target->setSizePolicy( p ); ((QVBoxLayout*)parent->layout())->insertWidget( parent->layout()->count() - 1 , target ); QObject::connect( removeTargetButton , SIGNAL(clicked()) , this , SLOT(removeTarget()) ); } /* //------------------------------------------------------------------------- void QFaustPreferences::addTarget( const QString& targetName , const QString& targetCommand ) { QWidget * target = new QWidget(this); target->setObjectName( TARGET_WIDGET ); QSizePolicy p; QLabel * targetNameLabel = new QLabel("Name :" , target); QLineEdit * targetNameEdit = new QLineEdit(targetName , target); targetNameEdit->setObjectName( TARGET_NAME ); p = targetNameEdit->sizePolicy(); p.setHorizontalStretch( 1 ); targetNameEdit->setSizePolicy( p ); QLabel * targetCommandLabel = new QLabel("Command :" , target); QLineEdit *targetCommandEdit= new QLineEdit(targetCommand , target); targetCommandEdit->setObjectName( TARGET_COMMAND ); p = targetCommandEdit->sizePolicy(); p.setHorizontalStretch( 3 ); targetCommandEdit->setSizePolicy( p ); QToolButton * removeTargetButton = new QToolButton( target ); removeTargetButton->setText( "Remove" ); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(targetNameLabel); layout->addWidget(targetNameEdit); layout->addWidget(targetCommandLabel); layout->addWidget(targetCommandEdit); layout->addWidget(removeTargetButton); target->setLayout(layout); p = target->sizePolicy(); p.setVerticalPolicy( QSizePolicy::Fixed ); target->setSizePolicy( p ); ((QVBoxLayout*)mUI->targetsBox->layout())->insertWidget( mUI->targetsBox->layout()->count() - 1 , target ); QObject::connect( removeTargetButton , SIGNAL(clicked()) , this , SLOT(removeTarget()) ); } */ //------------------------------------------------------------------------- void QFaustPreferences::addTarget( const QString& targetName , const QString& targetCommand ) { addConfigurationLine(targetName,targetCommand,TARGET_WIDGET,TARGET_NAME,TARGET_COMMAND,mUI->targetsBox); updateTabOrder(); } //------------------------------------------------------------------------- void QFaustPreferences::addOption( const QString& optionName , const QString& optionCommand ) { addConfigurationLine(optionName,optionCommand,OPTION_WIDGET,OPTION_NAME,OPTION_COMMAND,mUI->optionsBox); updateTabOrder(); } QHash QFaustPreferences::mSavedSettings; //------------------------------------------------------------------------- void QFaustPreferences::saveSettings() { mSavedSettings.clear(); QSettings settings("grame.fr", "FaustWorks"); QStringList keys = settings.allKeys(); for ( int i = 0 ; i < keys.size() ; i++ ) { mSavedSettings[keys[i]] = settings.value( keys[i] ); } } //------------------------------------------------------------------------- void QFaustPreferences::restoreSettings() { QSettings settings("grame.fr", "FaustWorks"); settings.clear(); QStringList keys = mSavedSettings.keys(); for ( int i = 0 ; i < keys.size() ; i++ ) { settings.setValue( keys[i] , mSavedSettings[keys[i]] ); } } FaustWorks-0.4/QFaustPreferences.h0000755000175000017500000000442112130743520015666 0ustar miramira/* * QFaustPreferences.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef FaustPreferences_H #define FaustPreferences_H #include #include #include namespace Ui { class FaustPreferences; } class FaustMainWindow; //------------------------------------------------------------------------------------------------------------------------ class QFaustPreferences : public QDialog { Q_OBJECT public: QFaustPreferences(FaustMainWindow * parent = 0); protected slots: void apply(); void cancel(); void reset(); void findFaustPath(); void addTarget(); void removeTarget(); void addOption(); protected: void updateWidgets(); void updateConfigurationWidgets( const QString& settingKey , const QString& widgetName , const QString& nameEditName , const QString& commandEditName , QWidget * parent ); void addConfigurationLine( const QString& targetName , const QString& targetCommand , const QString& widgetName , const QString& nameEditName , const QString& commandEditName , QWidget * parent ); void updateTabOrder(); void addTarget( const QString& targetName , const QString& targetCommand ); void addOption( const QString& optionName , const QString& optionCommand ); void applyConfiguration( const QString& settingKey , const QString& widgetName , const QString& nameEditName , const QString& commandEditName , QWidget * box ); FaustMainWindow* mMainWindow; static void saveSettings(); static void restoreSettings(); static QHash mSavedSettings; private: Ui::FaustPreferences * mUI; }; #endif FaustWorks-0.4/QItemResizer.cpp0000755000175000017500000003332112130743520015220 0ustar miramira/* * QItemResizer.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QItemResizer.h" #include #include #include #include #define DEFAULT_BORDER_WIDTH 5 #define DEFAULT_BORDER_BRUSH QColor(0,150,0,50) // couleur quand on fait un resize //------------------------------------------------------------------------- QItemResizer::QItemResizer( const QRectF& rect , QGraphicsItem * parent ) : QGraphicsRectItem( rect , parent ) { setAcceptHoverEvents( true ); mIsResizing = false; mRoundedRectRadius = 0; mIsAspectRatioKept = false; mScaleFocus = FOCUS_NONE; mBorderBrush = DEFAULT_BORDER_BRUSH; mBorderWidth = DEFAULT_BORDER_WIDTH; mMinSize = QSize(0,0); mMaxSize = QSize(0,0); } #include //------------------------------------------------------------------------- void QItemResizer::updateGeometry(const QRectF& newGeometry) { setRect( newGeometry ); } //------------------------------------------------------------------------- void QItemResizer::setKeepAspectRatio( bool isAspectRatioKept ) { mIsAspectRatioKept = isAspectRatioKept; } //------------------------------------------------------------------------- void QItemResizer::paint(QPainter* painter , const QStyleOptionGraphicsItem* , QWidget* ) { QRectF r = boundingRect(); if ( mIsResizing ) { painter->setPen( pen() ); painter->setBrush( brush() ); painter->drawRoundedRect( r , mRoundedRectRadius , mRoundedRectRadius ); } else if ( hasCursor() ) { painter->setBrush( mBorderBrush ); painter->setPen( Qt::NoPen ); painter->drawRect( 0 , 0 , r.width() , mBorderWidth ); painter->drawRect( 0 , mBorderWidth , mBorderWidth , r.height() - mBorderWidth ); painter->drawRect( mBorderWidth , r.height() , r.width() - 2 * mBorderWidth , -mBorderWidth ); painter->drawRect( r.width() , mBorderWidth , -mBorderWidth , r.height() - mBorderWidth ); } } //------------------------------------------------------------------------- void QItemResizer::setRoundedRectRadius( float radius ) { mRoundedRectRadius = radius; } //------------------------------------------------------------------------- void QItemResizer::setResizeBorder( float width , const QBrush& brush ) { mBorderBrush = brush; mBorderWidth = width; } //------------------------------------------------------------------------- void QItemResizer::setSizeBounds( const QSizeF& min , const QSizeF& max ) { mMinSize = min; mMaxSize = max; } //------------------------------------------------------------------------- void QItemResizer::checkCursorPosition( const QPointF& position ) { QRectF r = boundingRect(); if ( position.x() < mBorderWidth ) { if ( position.y() < mBorderWidth ) { mScaleFocus = FOCUS_BOTTOM_RIGHT; setCursorAndUpdate( Qt::SizeFDiagCursor ); } else if ( position.y() > r.height() - mBorderWidth ) { mScaleFocus = FOCUS_TOP_RIGHT; setCursorAndUpdate( Qt::SizeBDiagCursor ); } else { mScaleFocus = FOCUS_RIGHT; setCursorAndUpdate( Qt::SizeHorCursor ); } } else if ( position.x() > r.width() - mBorderWidth ) { if ( position.y() < mBorderWidth ) { mScaleFocus = FOCUS_BOTTOM_LEFT; setCursorAndUpdate( Qt::SizeBDiagCursor ); } else if ( position.y() > r.height() - mBorderWidth ) { mScaleFocus = FOCUS_TOP_LEFT; setCursorAndUpdate( Qt::SizeFDiagCursor ); } else { mScaleFocus = FOCUS_LEFT; setCursorAndUpdate( Qt::SizeHorCursor ); } } else if ( position.y() < mBorderWidth ) { mScaleFocus = FOCUS_BOTTOM; setCursorAndUpdate( Qt::SizeVerCursor ); } else if ( position.y() > r.height() - mBorderWidth ) { mScaleFocus = FOCUS_TOP; setCursorAndUpdate( Qt::SizeVerCursor ); } else { if ( mScaleFocus != FOCUS_NONE ) { mScaleFocus = FOCUS_NONE; unsetCursor(); update(); } } } //------------------------------------------------------------------------- void QItemResizer::hoverMoveEvent ( QGraphicsSceneHoverEvent * event ) { QPointF position = event->pos(); checkCursorPosition(position); } //------------------------------------------------------------------------- void QItemResizer::setCursorAndUpdate( const QCursor& newCursor ) { if ( cursor().shape() != newCursor.shape() ) { setCursor( newCursor ); update(); } } //------------------------------------------------------------------------- QRectF QItemResizer::getRescaledRectWithAspectRatio( const QRectF& baseRect , const QPointF& delta , QItemResizer::ScaleFocus scaleFocus ) { QRectF newRect(baseRect); float heightForWidth = baseRect.height() / baseRect.width(); switch ( scaleFocus ) { case QItemResizer::FOCUS_BOTTOM_LEFT: { QPointF p = newRect.topRight(); if ( heightForWidth > 1 ) p += QPointF( - delta.y() / heightForWidth , delta.y() ); else p += QPointF( delta.x() , -delta.x() * heightForWidth ); newRect.setTopRight( p ); break; } case QItemResizer::FOCUS_BOTTOM_RIGHT: { QPointF p = newRect.topLeft(); if ( heightForWidth > 1 ) p += QPointF( delta.y() / heightForWidth , delta.y() ); else p += QPointF( delta.x() , delta.x() * heightForWidth ); newRect.setTopLeft( p ); break; } case QItemResizer::FOCUS_TOP_RIGHT: { QPointF p = newRect.bottomLeft(); if ( heightForWidth > 1 ) p += QPointF( - delta.y() / heightForWidth , delta.y() ); else p += QPointF( delta.x() , -delta.x() * heightForWidth ); newRect.setBottomLeft( p ); break; } case QItemResizer::FOCUS_TOP_LEFT: { QPointF p = newRect.bottomRight(); if ( heightForWidth > 1 ) p += QPointF( delta.y() / heightForWidth , delta.y() ); else p += QPointF( delta.x() , delta.x() * heightForWidth ); newRect.setBottomRight( p ); break; } case QItemResizer::FOCUS_BOTTOM: { QPointF p = newRect.topRight(); p += QPointF( - delta.y() / (2 * heightForWidth ), delta.y() ); newRect.setTopRight( p ); p = newRect.topLeft(); p += QPointF( + delta.y() / (2 *heightForWidth ), 0 ); newRect.setTopLeft( p ); break; } case QItemResizer::FOCUS_RIGHT: { QPointF p = newRect.topLeft(); p += QPointF( delta.x() , delta.x() * (heightForWidth/2) ); newRect.setTopLeft( p ); p = newRect.bottomLeft(); p += QPointF( 0 , -delta.x() * (heightForWidth/2) ); newRect.setBottomLeft( p ); break; } case QItemResizer::FOCUS_TOP: { QPointF p = newRect.bottomLeft(); p += QPointF( - delta.y() / (2*heightForWidth) , delta.y() ); newRect.setBottomLeft( p ); p = newRect.bottomRight(); p += QPointF( delta.y() / (2*heightForWidth) , 0 ); newRect.setBottomRight( p ); break; } case QItemResizer::FOCUS_LEFT: { QPointF p = newRect.bottomRight(); p += QPointF( delta.x() , delta.x() * (heightForWidth/2) ); newRect.setBottomRight( p ); p = newRect.topRight(); p += QPointF( 0 , -delta.x() * (heightForWidth/2) ); newRect.setTopRight( p ); break; } default: break; } return newRect; } //------------------------------------------------------------------------- QRectF QItemResizer::getRescaledRectWithoutAspectRatio( const QRectF& baseRect , const QPointF& delta , QItemResizer::ScaleFocus scaleFocus ) { QRectF newRect(baseRect); switch ( scaleFocus ) { case QItemResizer::FOCUS_BOTTOM_LEFT: { QPointF p = newRect.topRight(); p += QPointF( delta.x() , delta.y() ); newRect.setTopRight( p ); break; } case QItemResizer::FOCUS_BOTTOM_RIGHT: { QPointF p = newRect.topLeft(); p += QPointF( delta.x() , delta.y() ); newRect.setTopLeft( p ); break; } case QItemResizer::FOCUS_TOP_RIGHT: { QPointF p = newRect.bottomLeft(); p += QPointF( delta.x() , delta.y() ); newRect.setBottomLeft( p ); break; } case QItemResizer::FOCUS_TOP_LEFT: { QPointF p = newRect.bottomRight(); p += QPointF( delta.x() , delta.y() ); newRect.setBottomRight( p ); break; } case QItemResizer::FOCUS_BOTTOM: { QPointF p = newRect.topRight(); p += QPointF( 0 , delta.y() ); newRect.setTopRight( p ); break; } case QItemResizer::FOCUS_RIGHT: { QPointF p = newRect.topLeft(); p += QPointF( delta.x(), 0 ); newRect.setTopLeft( p ); break; } case QItemResizer::FOCUS_TOP: { QPointF p = newRect.bottomLeft(); p += QPointF( 0 , delta.y() ); newRect.setBottomLeft( p ); break; } case QItemResizer::FOCUS_LEFT: { QPointF p = newRect.bottomRight(); p += QPointF( delta.x() , 0 ); newRect.setBottomRight( p ); break; } default: break; } return newRect; } //------------------------------------------------------------------------- void QItemResizer::mouseMoveEvent( QGraphicsSceneMouseEvent * event ) { if ( (mIsResizing) && ( mScaleFocus != FOCUS_NONE ) ) { QRectF oldRect = boundingRect(); QPointF delta = event->pos() - event->lastPos(); QRectF newRect; if ( mIsAspectRatioKept ) newRect = getRescaledRectWithAspectRatio(oldRect , delta , mScaleFocus); else newRect = getRescaledRectWithoutAspectRatio(oldRect , delta , mScaleFocus); if ( ( newRect.height() < 0 ) || ( newRect.width() < 0 ) ) return; setRect( newRect ); } } //------------------------------------------------------------------------- void QItemResizer::mousePressEvent( QGraphicsSceneMouseEvent * event ) { QPointF position = event->pos(); checkCursorPosition(position); if ( mScaleFocus != FOCUS_NONE ) { event->accept(); mIsResizing = true; mStartResizeRect = rect(); } else event->ignore(); } //------------------------------------------------------------------------- void QItemResizer::hoverLeaveEvent ( QGraphicsSceneHoverEvent * ) { unsetCursor(); update(); } #include //------------------------------------------------------------------------- void QItemResizer::mouseReleaseEvent( QGraphicsSceneMouseEvent * event ) { QGraphicsRectItem::mouseReleaseEvent( event ); QRectF resizedRect = rect(); if ( mMinSize.width() * mMinSize.height() > 0 ) { QRectF min = boundRect( mMinSize , false ); if ( !resizedRect.contains( min ) ) { resizedRect = min | resizedRect; } } if ( mMaxSize.width() * mMaxSize.height() > 0 ) { QRectF max = boundRect( mMaxSize , true ); if ( !max.contains( resizedRect ) ) { resizedRect = max & resizedRect; } } setRect( mStartResizeRect ); mIsResizing = false; unsetCursor(); update(); if ( resizedRect != rect() ) { Q_EMIT resized( resizedRect ); } } //------------------------------------------------------------------------- static QPointF segmentCenter( const QPointF& a , const QPointF& b ) { QPointF result = a + b; result.setX( result.x() / 2 ); result.setY( result.y() / 2 ); return result; } //------------------------------------------------------------------------- QRectF QItemResizer::boundRect( QSizeF referenceRect , bool doReduce ) { if ( mIsAspectRatioKept ) { float widthForHeight = rect().width() / rect().height(); bool b = ( widthForHeight > 1.0f ); if ( doReduce ) b = !b; if ( b ) { referenceRect.setWidth( widthForHeight * referenceRect.height() ); } else { referenceRect.setHeight( referenceRect.width() / float(widthForHeight) ); } } QRectF result = rect(); switch ( mScaleFocus ) { case QItemResizer::FOCUS_BOTTOM_LEFT: { result.setTopRight( result.bottomLeft() + QPointF( referenceRect.width() , -referenceRect.height() ) ); break; } case QItemResizer::FOCUS_BOTTOM_RIGHT: { result.setTopLeft( result.bottomRight() - QPointF( referenceRect.width() , referenceRect.height() ) ); break; } case QItemResizer::FOCUS_TOP_RIGHT: { result.setBottomLeft( result.bottomRight() + QPointF( -referenceRect.width() , referenceRect.height() ) ); break; } case QItemResizer::FOCUS_TOP_LEFT: { result.setBottomRight( result.topLeft() + QPointF( referenceRect.width() , referenceRect.height() ) ); break; } case QItemResizer::FOCUS_BOTTOM: { QPointF c = segmentCenter( result.bottomLeft() , result.bottomRight() ); result.setBottomLeft( c - QPointF( referenceRect.width() / 2.0f, 0 ) ); result.setTopRight( result.bottomLeft() + QPointF( referenceRect.width() , -referenceRect.height() ) ); break; } case QItemResizer::FOCUS_RIGHT: { QPointF c = segmentCenter( result.topRight() , result.bottomRight() ); result.setBottomRight( c + QPointF( 0, referenceRect.height()/2.0f ) ); result.setTopLeft( result.bottomRight() - QPointF( referenceRect.width() , referenceRect.height() ) ); break; } case QItemResizer::FOCUS_TOP: { QPointF c = segmentCenter( result.topLeft() , result.topRight() ); result.setTopLeft( c - QPointF( referenceRect.width() / 2.0f, 0 ) ); result.setBottomRight( result.topLeft() + QPointF( referenceRect.width() , referenceRect.height() ) ); break; } case QItemResizer::FOCUS_LEFT: { QPointF c = segmentCenter( result.topLeft() , result.bottomLeft() ); result.setBottomLeft( c + QPointF( 0, referenceRect.height()/2.0f ) ); result.setTopRight( result.bottomLeft() + QPointF( referenceRect.width() , -referenceRect.height() ) ); break; } default: break; } return result; } //------------------------------------------------------------------------- void QItemResizer::show(bool isShown) { setVisible(isShown); } FaustWorks-0.4/QItemResizer.h0000755000175000017500000000764112130743520014673 0ustar miramira/* * QItemResizer.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef ITEM_RESIZER_H #define ITEM_RESIZER_H #include #include #include class QItemResizerSlot; /*! \brief QItemResizer adds "resize borders" to its parent item. * * The user can drag&drop the borders to change the width & height * of the parent item. On drop, the QItemResizer * emits resized(QRectF), where ths QRectF param is the new requested size. * * \important The QItemResizer doesn't actually change the scale or the size of * its parent item ; it only emits the resized(QRectF) signal. * It's on the parent's responsibility of the parent item to * process the signal accordingly. * * The QItemResizer is rectangular and thus works well with rectangular items (optionnaly with * rounded borders - see setRoundedRectRadius). * * You can set the border's thickness and brush with setResizeBorder. * * You can set if the QItemResizer keeps item's width/height ratio * with setKeepAspectRatio. * */ class QItemResizer : public QObject , public QGraphicsRectItem { Q_OBJECT public: /*! \brief Builds a QItemResizer for the QGraphicsItem * parent. */ QItemResizer( const QRectF& rect , QGraphicsItem * parent ); void paint(QPainter* painter , const QStyleOptionGraphicsItem* style , QWidget* widget); /*! \brief Sets the rounded rect radius. Zero is for a simple (not rounded) rectangle. */ void setRoundedRectRadius( float radius ); /*! \brief Indicates if the QItemResizer must keep the width/height ratio, or * is allowed to change (per example) the width without changing the height. */ void setKeepAspectRatio( bool isAspectRatioKept ); /*! \brief Sets the thickness and the brush of the border. */ void setResizeBorder( float width , const QBrush& brush ); void setSizeBounds( const QSizeF& min , const QSizeF& max ); public Q_SLOTS: void updateGeometry(const QRectF& newGeometry); void show(bool isShown); Q_SIGNALS: void resized( const QRectF& newRect ); protected : typedef enum ScaleFocus { FOCUS_TOP , FOCUS_LEFT , FOCUS_BOTTOM , FOCUS_RIGHT , FOCUS_TOP_LEFT , FOCUS_TOP_RIGHT , FOCUS_BOTTOM_LEFT , FOCUS_BOTTOM_RIGHT , FOCUS_CENTER , FOCUS_NONE } ScaleFocus; virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event ); virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * ); virtual void mouseMoveEvent( QGraphicsSceneMouseEvent * event ); virtual void mousePressEvent( QGraphicsSceneMouseEvent * event ); virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent * event ); QRectF boundRect( QSizeF referenceRect , bool doReduce ); void checkCursorPosition( const QPointF& pos ); void setCursorAndUpdate( const QCursor& cursor ); static QRectF getRescaledRectWithAspectRatio( const QRectF& baseRect , const QPointF& delta , QItemResizer::ScaleFocus scaleFocus ); static QRectF getRescaledRectWithoutAspectRatio( const QRectF& baseRect , const QPointF& delta , QItemResizer::ScaleFocus scaleFocus ); ScaleFocus mScaleFocus; float mRoundedRectRadius; bool mIsResizing; QRectF mStartResizeRect; bool mIsAspectRatioKept; QBrush mBorderBrush; float mBorderWidth; QSizeF mMaxSize , mMinSize; }; #endif //ITEM_RESIZER_H FaustWorks-0.4/QLanguageCommandPalette.cpp0000755000175000017500000000754112130743520017324 0ustar miramira/* * QLanguageCommandPalette.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QLanguageCommandPalette.h" #include "GraphicsSceneMainWindow.h" #include #include #include #define INDENT QString(" ") //------------------------------------------------------------------------------------ QLanguageCommandPalette::QLanguageCommandPalette(const QString& commandsFile , QWidget * parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); mTabStack << new QTabWidget(this); layout->addWidget( mTabStack.top() ); setLayout(layout); QLanguageCommandReader reader; reader.read( this , commandsFile ); } #include "QLanguageCommandPaletteLayout.h" //------------------------------------------------------------------------------------ void QLanguageCommandPalette::categoryBegin( const QString& name ) { //Add new tab to mCurrentTab. The new tab has the name of the category. //The new tab is another QTabWidget. // QTabWidget * newTab = new QTabWidget( this ); newTab->setUsesScrollButtons ( true ); QLanguageCommandPaletteLayout * layout = new QLanguageCommandPaletteLayout( newTab ); newTab->setLayout( layout ); mTabStack.top()->addTab( newTab , name ); mTabStack.top()->setTabToolTip( mTabStack.top()->count()-1 , name ); mTabStack << newTab; mCategories.push( name ); mIndent += INDENT; setMinimumSize( QSize(200,150) ); } //------------------------------------------------------------------------------------ void QLanguageCommandPalette::categoryEnd() { mIndent = mIndent.left( mIndent.length() - INDENT.length() ); mCategories.pop(); mTabStack.pop(); } #include //------------------------------------------------------------------------------------ void QLanguageCommandPalette::newElement( const QString& name , const QString& value , int insertIndex ) { QValuePushButton * button = new QValuePushButton( name , value , insertIndex , this ); button->setMaximumSize( QSize(10000,10000) ); connect( button , SIGNAL(clicked()) , this , SLOT(elementClick()) ); mTabStack.top()->layout()->addWidget( button ); } //------------------------------------------------------------------------------------ void QLanguageCommandPalette::elementClick() { QValuePushButton * button = dynamic_cast (sender()); Q_EMIT insertCode(button->value(),button->insertIndex()); } //------------------------------------------------------------------------------------ // QValuePushButton // //------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------ QValuePushButton::QValuePushButton(const QString& name , const QString& value , int insertIndex , QWidget * parent) : QToolButton( parent ), mValue(value) , mInsertIndex( insertIndex ) { setText( name ); setToolTip( mValue ); } //------------------------------------------------------------------------------------ int QValuePushButton::insertIndex() const { return mInsertIndex; } //------------------------------------------------------------------------------------ QString QValuePushButton::value() const { return mValue; } FaustWorks-0.4/QLanguageCommandPalette.h0000755000175000017500000000351612130743520016767 0ustar miramira/* * QLanguageCommandPalette.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef LANGUAGE_COMMAND_PALETTE_H #define LANGUAGE_COMMAND_PALETTE_H #include #include #include "QLanguageCommandReader.h" class QTabWidget; class QLanguageCommandPalette : public QWidget , public QLanguageCommandVisitor { Q_OBJECT public : QLanguageCommandPalette(const QString& commandsFile , QWidget * parent = 0); void categoryBegin( const QString& name ); void categoryEnd(); void newElement( const QString& name , const QString& value , int insertIndex ); Q_SIGNALS: void insertCode(const QString& gmnCode , int insertIndex ); protected Q_SLOTS: void elementClick(); protected : QStack mCategories; QString mIndent; QStack mTabStack; QList mCurrentWidgetList; }; #include class QValuePushButton : public QToolButton { Q_OBJECT public: QValuePushButton(const QString& name , const QString& value , int insertIndex , QWidget * parent = 0); int insertIndex() const; QString value() const; protected: QString mValue; int mInsertIndex; }; #endif //GUIDO_COMMAND_PALETTE_H FaustWorks-0.4/QLanguageCommandPaletteLayout.cpp0000755000175000017500000001450412130743520020517 0ustar miramira/* * QLanguageCommandPaletteLayout.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include "QLanguageCommandPaletteLayout.h" //---------------------------------------------------------------------- QLanguageCommandPaletteLayout::QLanguageCommandPaletteLayout(QWidget *parent, int margin, int spacing) : QLayout(parent) { setMargin(margin); setSpacing(spacing); } //---------------------------------------------------------------------- QLanguageCommandPaletteLayout::QLanguageCommandPaletteLayout(int spacing) { setSpacing(spacing); } //---------------------------------------------------------------------- QLanguageCommandPaletteLayout::~QLanguageCommandPaletteLayout() { QLayoutItem *item; while ((item = takeAt(0))) delete item; } //---------------------------------------------------------------------- void QLanguageCommandPaletteLayout::addItem(QLayoutItem *item) { mItemList.append(item); } //---------------------------------------------------------------------- int QLanguageCommandPaletteLayout::count() const { return mItemList.size(); } //---------------------------------------------------------------------- QLayoutItem *QLanguageCommandPaletteLayout::itemAt(int index) const { return mItemList.value(index); } //---------------------------------------------------------------------- QLayoutItem *QLanguageCommandPaletteLayout::takeAt(int index) { if (index >= 0 && index < mItemList.size()) return mItemList.takeAt(index); else return 0; } //---------------------------------------------------------------------- Qt::Orientations QLanguageCommandPaletteLayout::expandingDirections() const { return 0; } //---------------------------------------------------------------------- void QLanguageCommandPaletteLayout::setGeometry(const QRect &rect) { QLayout::setGeometry(rect); doLayout(rect, false); } //---------------------------------------------------------------------- QSize QLanguageCommandPaletteLayout::sizeHint() const { return minimumSize(); } //---------------------------------------------------------------------- QSize QLanguageCommandPaletteLayout::minimumSize() const { QSize size; QLayoutItem *item; foreach (item, mItemList) size = size.expandedTo(item->minimumSize()); size += QSize(2*margin(), 2*margin()); return size; } #include //---------------------------------------------------------------------- void fillWidth(int startX , int endX , QList & items) { if ( items.size() == 0 ) return; int additionalSpace = endX - items.last().right(); int spaceAdded = additionalSpace / items.size(); int currentX = startX; for ( int i = 0 ; i < items.size() ; i++ ) { int newWidth = items[i].width() + spaceAdded; items[i].setWidth( newWidth ); items[i].moveLeft( currentX ); currentX += newWidth; } items.last().setRight( endX ); } //---------------------------------------------------------------------- void fitInHeight( int startY , int endY , QList & items ) { if ( items.size() == 0 ) return; if ( items.last().bottom() > endY ) { //We need to compress the height of the items. float compressFactor = (endY - startY) / float( items.last().bottom() - items.first().top() ); //We'll apply on each item : height = compressFactor * height. int previousY = startY; int currentY = startY; for ( int i = 0 ; i < items.size() ; i++ ) { items[i].setHeight( items[i].height() * compressFactor ); if ( items[i].top() != previousY ) { //Linebreak previousY = items[i].top(); currentY = items[i-1].bottom(); } items[i].moveTop( currentY ); } } } //---------------------------------------------------------------------- int QLanguageCommandPaletteLayout::doLayout(const QRect &rect, bool testOnly) const { if ( mItemList.size() == 0 ) return 0; QList sizeHints; QList geometries; int i; int surface = 0; int largestItem = 0; for ( i = 0 ; i < mItemList.size() ; i++ ) { sizeHints << mItemList[i]->sizeHint(); surface += ( sizeHints[i].width() * sizeHints[i].height() ); largestItem = qMax( largestItem , sizeHints[i].width() ); } float surfaceRatio = surface / float( rect.width() * rect.height() ); surfaceRatio = qMin( surfaceRatio , 1.0f ); float sideRatio = qSqrt( surfaceRatio ); int newRectWidth = rect.width() * sideRatio; int newRectHeight = rect.height() * sideRatio; newRectWidth = qMin( rect.width() , qMax( newRectWidth , largestItem ) ); QRect newRect( (rect.width()-newRectWidth)/2 , qMax( (rect.height()-newRectHeight)/2 - sizeHints[0].height() , 0 ) , newRectWidth , newRectHeight ); int x = newRect.x(); int y = newRect.y(); int lineHeight = 0; QList lineItems; for ( i = 0 ; i < mItemList.size() ; i++ ) { int nextX = x + sizeHints[i].width() + spacing(); if ( (nextX - spacing() > newRect.right()) && (lineHeight > 0) ) { //Linebreak fillWidth(newRect.left() , newRect.right() , lineItems); geometries << lineItems; lineItems.clear(); x = newRect.x(); y = y + lineHeight + spacing(); nextX = x + sizeHints[i].width() + spacing(); lineHeight = 0; } lineItems << QRect(QPoint(x, y), sizeHints[i] ); x = nextX; lineHeight = qMax(lineHeight, sizeHints[i].height()); } //Linebreak fillWidth(newRect.left() , newRect.right() , lineItems); geometries << lineItems; lineItems.clear(); fitInHeight( newRect.top() , rect.bottom() , geometries ); if (!testOnly) { for ( i = 0 ; i < mItemList.size() ; i++ ) { mItemList[i]->setGeometry( geometries[i] ); } } return y + lineHeight - newRect.y(); } FaustWorks-0.4/QLanguageCommandPaletteLayout.h0000755000175000017500000000311012130743520020153 0ustar miramira/* * QLanguageCommandPaletteLayout.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef LANGUAGE_COMMAND_PALETTE_LAYOUT_H #define LANGUAGE_COMMAND_PALETTE_LAYOUT_H #include #include #include class QLanguageCommandPaletteLayout : public QLayout { public: QLanguageCommandPaletteLayout(QWidget *parent, int margin = 0, int spacing = -1); QLanguageCommandPaletteLayout(int spacing = -1); ~QLanguageCommandPaletteLayout(); void addItem(QLayoutItem *item); Qt::Orientations expandingDirections() const; int count() const; QLayoutItem * itemAt(int index) const; QSize minimumSize() const; void setGeometry(const QRect &rect); QSize sizeHint() const; QLayoutItem * takeAt(int index); private: int doLayout(const QRect &rect, bool testOnly) const; QList mItemList; }; #endif //GUIDO_COMMAND_PALETTE_LAYOUT_H FaustWorks-0.4/QLanguageCommandReader.cpp0000755000175000017500000000672212130743520017130 0ustar miramira/* * QLanguageCommandReader.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QLanguageCommandReader.h" #define DOM_LANGUAGE_COMMAND_LIBRARY "LanguageCommandsLibrary" #define DOM_LANGUAGE_COMMAND_LIBRARY_ROOT "LanguageCommandsLibraryRoot" #define DOM_LANGUAGE_COMMAND_CATEGORY "LanguageCommandsCategory" #define DOM_LANGUAGE_COMMAND_CATEGORY_NAME "name" #define DOM_LANGUAGE_COMMAND "LanguageCommand" #define DOM_LANGUAGE_COMMAND_NAME "name" #define DOM_LANGUAGE_COMMAND_VALUE "value" #define DOM_LANGUAGE_COMMAND_INSERT_INDEX "insertIndex" #include #include #include #include #include //------------------------------------------------------------------------------------ QLanguageCommandReader::QLanguageCommandReader() { } //------------------------------------------------------------------------------------ bool QLanguageCommandReader::read( QLanguageCommandVisitor * visitor , const QString& fileName ) { mVisitor = visitor; QFile file( fileName ); if( !file.open( QFile::ReadOnly ) ) { //Can't read file qDebug("QLanguageCommandReader::read : Can't read file %s" , fileName.toAscii().data() ); return false; } //Create a new DomDocument with file contents QDomDocument doc( DOM_LANGUAGE_COMMAND_LIBRARY ); if( !doc.setContent( &file ) ) { file.close(); //File doesn't contain valid XML data qDebug("QLanguageCommandReader::read : File doesn't contain valid XML data"); return false; } file.close(); //Check the root QDomElement root = doc.documentElement(); if( root.tagName() != DOM_LANGUAGE_COMMAND_LIBRARY_ROOT ) { //No valid root found. qDebug("QLanguageCommandReader::read : No valid root found"); return false; } readNode( &root ); return true; } //------------------------------------------------------------------------------------ void QLanguageCommandReader::readNode( QDomElement * element) { QDomNode n = element->firstChild(); while ( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if( e.tagName() == DOM_LANGUAGE_COMMAND_CATEGORY ) { mVisitor->categoryBegin( QVariant( e.attribute( DOM_LANGUAGE_COMMAND_CATEGORY_NAME, "" ) ).toString() ); readNode( &e ); mVisitor->categoryEnd(); } else if( e.tagName() == DOM_LANGUAGE_COMMAND ) { QString gmnCommandName = QVariant( e.attribute( DOM_LANGUAGE_COMMAND_NAME, "" ) ).toString(); QString gmnCommand = e.firstChild().toCDATASection().data(); int gmnInsertIndex = QVariant( e.attribute( DOM_LANGUAGE_COMMAND_INSERT_INDEX, "0" ) ).toInt(); mVisitor->newElement( gmnCommandName , gmnCommand , gmnInsertIndex ); } else { qWarning( "QLanguageCommandReader::QLanguageCommandReader : Unknown tag : %s" , e.tagName().toAscii().data() ); } } n = n.nextSibling(); } } FaustWorks-0.4/QLanguageCommandReader.h0000755000175000017500000000262512130743520016573 0ustar miramira/* * QLanguageCommandReader.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef LANGUAGE_COMMAND_READER_H #define LANGUAGE_COMMAND_READER_H #include class QDomElement; class QLanguageCommandVisitor { public : virtual ~QLanguageCommandVisitor() {} virtual void categoryBegin( const QString& name ) = 0; virtual void categoryEnd() = 0; virtual void newElement( const QString& name , const QString& value , int insertIndex ) = 0; }; class QLanguageCommandReader { public : QLanguageCommandReader(); bool read( QLanguageCommandVisitor * visitor , const QString& fileName ); protected : void readNode( QDomElement * element); QLanguageCommandVisitor * mVisitor; }; #endif //GUIDO_COMMAND_READER_H FaustWorks-0.4/QLanguageItem.cpp0000755000175000017500000007061412130743520015326 0ustar miramira/* * QGuidoItemContainer.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QLanguageItem.h" #include "QPaletteItem.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEFAULT_INVALID_RECT QRectF( 0 , 0 , 100 , 100 ) #define INVALID_RECT_BOTTOM_MARGIN mInvalidTextMargin #define INVALID_RECT_LEFT_MARGIN mInvalidTextMargin #define INVALID_RECT_RIGHT_MARGIN mInvalidTextMargin #define INVALID_RECT_TOP_MARGIN mInvalidTextMargin #define ITEM_SCALE_NULL_POINT QPointF(-1,-1) #define ITEM_SCALE_NULL -1 #define PROPORTIONAL_SPRING 1.0f #define PROPORTIONAL_FORCE 1500.0f #define NO_PROPORTIONAL_SPRING 1.1f #define NO_PROPORTIONAL_FORCE 750.0f #define KEY_ITEM_MOVE 5 #define TITLE_BAR_TEXT_MARGIN 10 #define DOM_LANGUAGE_ITEM_X "ItemX" #define DOM_LANGUAGE_ITEM_Y "ItemY" #define DOM_LANGUAGE_ITEM_Z "ItemZ" #define DOM_LANGUAGE_ITEM_SCALE "Scale" #define DOM_LANGUAGE_ITEM_CODE "code" #define DOM_LANGUAGE_ITEM_FILE "file" #define MIME_CODE "Code" #define MIME_FILE_NAME "FileName" #define MIME_SCALE "Scale" #define MIME_HOTSPOT_X "HotSpotX" #define MIME_HOTSPOT_Y "HotSpotY" #define FILE_MENU "FileMenu" //------------------------------------------------------------------------- // QTextPathItem class /// //------------------------------------------------------------------------- //------------------------------------------------------------------------- QTextPathItem::QTextPathItem( const QString& text , bool centerText , const QColor& textColor , const QFont& textFont , float textPenWidth , QGraphicsItem* parent ) : QGraphicsPathItem(parent) { mText = new QGraphicsSimpleTextItem( text , this); mText->setPen( QPen( textColor , textPenWidth ) ); mText->setBrush( QBrush( textColor ) ); mText->setFont( textFont ); mCenterText = centerText; } //------------------------------------------------------------------------- void QTextPathItem::setText(const QString& text) { if ( mText->text() != text ) mText->setText(text); QString truncString = "..."; int skippedChar = truncString.length() + 1; while ( ( mText->boundingRect().width() > boundingRect().width() - TITLE_BAR_TEXT_MARGIN ) && ( skippedChar < text.length() ) ) { mText->setText( text.left( text.length() - skippedChar ) + truncString ); skippedChar++; } updateTextPos(); } //------------------------------------------------------------------------- void QTextPathItem::setPath( const QPainterPath& p ) { QGraphicsPathItem::setPath(p); setText( mText->text() ); } //------------------------------------------------------------------------- void QTextPathItem::updateTextPos() { if ( mCenterText ) { QPointF c = boundingRect().center(); mText->setPos( c.x() - mText->boundingRect().width()/2.0f , c.y() - mText->boundingRect().height()/2.0f ); } else { mText->setPos( 5 , 5 ); } } //------------------------------------------------------------------------- // Misc functions // //------------------------------------------------------------------------- //------------------------------------------------------------------------- static QString getFileContent(const QString& fileName) { if ( !QFile::exists(fileName) ) return ""; QString content = ""; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { file.close(); return ""; } while (!file.atEnd()) { QByteArray line = file.readLine(); content += QString::fromUtf8(line); } file.close(); return content; } //------------------------------------------------------------------------- // Static Public functions // //------------------------------------------------------------------------- //------------------------------------------------------------------------- void QLanguageItem::addFile(const QString& fileName , QLanguageItem* usingItem) { if ( fileName.length() > 0 ) { mUsedFiles.insert( fileName , usingItem ); if ( !mFileContents.contains(fileName) ) mFileContents.insert( fileName , getFileContent(fileName) ); } } //------------------------------------------------------------------------- void QLanguageItem::removeFile(const QString& fileName , QLanguageItem* usingItem) { if ( fileName.length() > 0 ) { mUsedFiles.remove( fileName , usingItem ); if ( !mUsedFiles.contains( fileName ) ) { mFileContents.remove( fileName ); } } } //------------------------------------------------------------------------- // Public functions // //------------------------------------------------------------------------- #include //------------------------------------------------------------------------- QString getCopyName( QString originalName ) { QRegExp rx(".*\\(\\d+\\)"); int pos = rx.indexIn( originalName ); int copyNumber = 1; if ( pos != -1 ) { int numberPos = originalName.lastIndexOf("("); QString number = originalName.right( originalName.length() - numberPos - 1 ); number = number.left( number.length() - 1 ); copyNumber = QVariant(number).toInt() + 1; originalName = originalName.left( numberPos ); } return originalName + "(" + QVariant(copyNumber).toString() + ")"; } //------------------------------------------------------------------------- QLanguageItem::QLanguageItem(QGraphicsItem * parent) : QGraphicsRectItem(parent) { mFile = ""; mIsModified = false; mIsStorageModeOn = false; mDragImage = 0; mHasToUpdateDragImage = true; mIgnoreChangeNotification = false; mIsProcessingFileChange = false; } //------------------------------------------------------------------------- QLanguageItem::~QLanguageItem() { delete mDragImage; QLanguageItem::removeFile( file() , this ); } //------------------------------------------------------------------------- QDomElement QLanguageItem::saveToDomElement( QDomDocument * doc) { QDomElement element = doc->createElement( DOM_LANGUAGE_ITEM ); element.setAttribute( DOM_LANGUAGE_ITEM_X, pos().x() ); element.setAttribute( DOM_LANGUAGE_ITEM_Y, pos().y() ); element.setAttribute( DOM_LANGUAGE_ITEM_Z, zValue() ); if ( file().length() > 0 ) element.setAttribute( DOM_LANGUAGE_ITEM_FILE , file() ); else { QDomCDATASection codeSection = doc->createCDATASection( code() ); element.appendChild(codeSection); } return element; } //------------------------------------------------------------------------- bool QLanguageItem::isEqualTo( QLanguageItem * item ) const { if ( this->code() != item->code() ) return false; return true; } //------------------------------------------------------------------------- void QLanguageItem::keyPressEvent ( QKeyEvent * event ) { if (mIsStorageModeOn) return; int key = event->key(); if ( ( key == Qt::Key_Left ) || ( key == Qt::Key_Right ) || ( key == Qt::Key_Down ) || ( key == Qt::Key_Up ) ) { int dx = 0 , dy = 0; switch (key) { case Qt::Key_Left: dx = -KEY_ITEM_MOVE; dy = 0; break; case Qt::Key_Right: dx = KEY_ITEM_MOVE; dy = 0; break; case Qt::Key_Up: dy = -KEY_ITEM_MOVE; dx = 0; break; case Qt::Key_Down: dy = KEY_ITEM_MOVE; dx = 0; break; } moveBy( dx , dy ); event->accept(); return; } else { event->ignore(); } } //------------------------------------------------------------------------- QString QLanguageItem::getDescriptiveFileName() const { QString result = name(); if ( isModified() ) result += "*"; return result; } //------------------------------------------------------------------------- QString QLanguageItem::name() const { if ( file().length() ) { QFileInfo f( file() ); QString result = f.fileName(); return result; } else { return "untitled"; } } //------------------------------------------------------------------------- void QLanguageItem::plug( QPaletteItemDropper * dropper ) { dropper->setParentItem( this ); dropper->updateGeometry( this->boundingRect() ); connect( this , SIGNAL( updateChildrenItemsGeometry(const QRectF&) ) , dropper , SLOT(updateGeometry(const QRectF&)) ); connect( this , SIGNAL(dragStarted(int&,QGraphicsItem*&)) , dropper , SLOT( dragStarted(int&,QGraphicsItem*&) ) ); } //------------------------------------------------------------------------- QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen) { // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 // if we pass a value of 0.0 to QPainterPathStroker::setWidth() const qreal penWidthZero = qreal(0.00000001); if (path == QPainterPath()) return path; QPainterPathStroker ps; ps.setCapStyle(pen.capStyle()); if (pen.widthF() <= 0.0) ps.setWidth(penWidthZero); else ps.setWidth(pen.widthF()); ps.setJoinStyle(pen.joinStyle()); ps.setMiterLimit(pen.miterLimit()); QPainterPath p = ps.createStroke(path); p.addPath(path); return p; } //------------------------------------------------------------------------- void QLanguageItem::save(const QString& fileName) { QFile file( fileName ); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&file); out << code(); setFile( fileName ); setModified( false ); mIgnoreChangeNotification = true; QLanguageItem::fileChanged( fileName , code() ); mIgnoreChangeNotification = false; } //------------------------------------------------------------------------- void QLanguageItem::setFile( const QString& fileName ) { QLanguageItem::removeFile( file() , this ); mFile = fileName; Q_EMIT descriptiveNameChanged(); QLanguageItem::addFile( file() , this ); } //------------------------------------------------------------------------- QString QLanguageItem::file() const { return mFile; } //------------------------------------------------------------------------- void QLanguageItem::setMimeId( const QString& mimeId ) { mMimeId = mimeId; } //------------------------------------------------------------------------- void QLanguageItem::setStorageMode( bool isStorageModeOn ) { if ( isStorageModeOn == mIsStorageModeOn ) return; mIsStorageModeOn = isStorageModeOn; // Break the file link for items in storage mode. if ( mIsStorageModeOn ) { setFile(""); } } //------------------------------------------------------------------------- void QLanguageItem::addContainerAction( QLanguageItemAction * containerAction ) { mContainerActionList << containerAction; } //------------------------------------------------------------------------- bool QLanguageItem::isModified() const { return mIsModified; } //------------------------------------------------------------------------- bool QLanguageItem::fileNotFound() const { return ( ( mFile.length() > 0 ) && ( !QFile::exists( mFile ) ) ); } //------------------------------------------------------------------------- QPointF QLanguageItem::moveItem( const QPointF& destPoint ) { QPointF oldPos = pos(); setPos( pos() + destPoint - mMousePressPoint ); return pos() - oldPos; } //------------------------------------------------------------------------- void QLanguageItem::load(const QDomElement * e) { if ( e->tagName() != DOM_LANGUAGE_ITEM ) return; QString fileName = QVariant( e->attribute( DOM_LANGUAGE_ITEM_FILE, "" ) ).toString(); if ( fileName.length() > 0 ) loadFile( fileName ); else setCode( e->firstChild().toCDATASection().data() ); float x = QVariant( e->attribute( DOM_LANGUAGE_ITEM_X, "0" ) ).toDouble(); float y = QVariant( e->attribute( DOM_LANGUAGE_ITEM_Y, "0" )).toDouble(); setPos(x,y); setZValue( QVariant( e->attribute( DOM_LANGUAGE_ITEM_Z, "0" )).toDouble() ); } //------------------------------------------------------------------------- void QLanguageItem::load(const QLanguageItem * other) { setCode( other->code() ); setModified( other->isModified() ); setPos( other->pos() ); setZValue( other->zValue() ); } //------------------------------------------------------------ void QLanguageItem::loadFile( const QString& fileName ) { QString absoluteFileName = QFileInfo(fileName).absoluteFilePath(); setFile( absoluteFileName ); reloadItem(); } //------------------------------------------------------------ QMimeData * QLanguageItem::buildMimeData() { QMimeData *data = new QMimeData; data->setData( mMimeId , QByteArray::fromRawData( reinterpret_cast(this) , 4 ) ); data->setText( code() ); data->setData( MIME_FILE_NAME , file().toAscii().data() ); data->setData( MIME_CODE , code().toAscii().data() ); if ( !mIsStorageModeOn ) { // QByteArray a = QByteArray::number( containedItem()->transform().m11() ); // data->setData( MIME_SCALE , a ); QPointF p = mapFromScene(mMousePressPoint); data->setData( MIME_HOTSPOT_X , QByteArray::number( p.x() * sceneTransform().m11() ) ); data->setData( MIME_HOTSPOT_Y , QByteArray::number( p.y() * sceneTransform().m22() ) ); } QByteArray b; b.append(mCopyDrag); data->setData( MIME_DO_COPY , b ); return data; } //------------------------------------------------------------------------- void QLanguageItem::load(const QMimeData * mimeData) { if ( mimeData->hasFormat(MIME_CODE) ) setCode( QString( mimeData->data( MIME_CODE ) ) ); if ( mimeData->hasFormat(MIME_FILE_NAME) ) setFile( QString( mimeData->data( MIME_FILE_NAME ) ) ); setModified( code() != getFileContent( file() ) ); if ( mimeData->hasFormat( MIME_SCALE ) ) { float hotSpotX = mimeData->data( MIME_HOTSPOT_X ).toFloat(); float hotSpotY = mimeData->data( MIME_HOTSPOT_Y ).toFloat(); moveBy( -hotSpotX , -hotSpotY ); } } //------------------------------------------------------------------------- // Public slots // //------------------------------------------------------------------------- //------------------------------------------------------------------------- void QLanguageItem::saveItem() { save( mFile ); } //------------------------------------------------------------------------- void QLanguageItem::reloadItem() { if ( file().length() == 0 ) { qWarning("QLanguageItem::reloadItem() : file() is not defined"); return; } QMessageBox::StandardButton result = QMessageBox::Yes; if ( mIsModified && !mIsProcessingFileChange ) { result = QMessageBox::question ( 0, tr("Reload"), tr("Unsaved modifications will be lost. Reload?"), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel ); } if ( result == QMessageBox::Yes ) { setCode( QLanguageItem::mFileContents[ file() ] ); setModified( false ); itemHasBeenReloaded(); } } //------------------------------------------------------------------------- void QLanguageItem::unlinkFile() { setFile(""); } //------------------------------------------------------------------------- // Protected slots // //------------------------------------------------------------------------- //------------------------------------------------------------------------- void QLanguageItem::codeChanged() { if ( !isModified() ) { setModified( true ); } } //------------------------------------------------------------------------- void QLanguageItem::removeItemAndFile() { if ( file().length() == 0 ) { qWarning("QLanguageItem::removeItemAndFile() : file() is not defined."); return; } QMessageBox::StandardButton result = QMessageBox::question ( 0, tr("Delete file"), tr("Remove item and file ?"), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel ); if ( result == QMessageBox::Yes ) { QFile::remove( file() ); this->deleteLater(); Q_EMIT removed(); mIgnoreChangeNotification = true; QLanguageItem::fileRemoved( file() ); mIgnoreChangeNotification = false; } } //------------------------------------------------------------------------- // Protected functions // //------------------------------------------------------------------------- //------------------------------------------------------------------------- void QLanguageItem::contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) { if (mIsStorageModeOn) return; if ( scene()->selectedItems().size() > 1 ) { event->ignore(); return; } QMenu * m = buildContextMenu(); if ( m ) { event->accept(); m->exec( event->screenPos() ); delete m; } } //------------------------------------------------------------------------- QAction * newSeparator(QObject * parent) { QAction * separator = new QAction(parent); separator->setSeparator(true); return separator; } //------------------------------------------------------------------------- QMenu * QLanguageItem::buildContextMenu() { QMenu * menu = new QMenu(); QList actions; QAction * removeFileAct = new QAction( tr("Delete item && file") , menu ); removeFileAct->setObjectName( OBJECT_NAME_DELETE_ITEM_AND_FILE_ACT ); connect( removeFileAct , SIGNAL(triggered()) , this , SLOT(removeItemAndFile()) ); actions.append(removeFileAct); removeFileAct->setEnabled( !mFile.isEmpty() ); removeFileAct->setProperty( FILE_MENU , 1 ); QAction * unlinkAct = new QAction( tr("Unlink") , menu ); unlinkAct->setObjectName( OBJECT_NAME_UNLINK_ACT ); connect( unlinkAct , SIGNAL(triggered()) , this , SLOT(unlinkFile()) ); actions.append(unlinkAct); unlinkAct->setEnabled( !mFile.isEmpty() ); unlinkAct->setProperty( FILE_MENU , 1 ); QAction * reloadAct = new QAction( tr("Reload") , menu ); reloadAct->setObjectName( OBJECT_NAME_RELOAD_ACT ); connect( reloadAct , SIGNAL(triggered()) , this , SLOT(reloadItem()) ); actions.append(reloadAct); reloadAct->setEnabled( !mFile.isEmpty() ); reloadAct->setProperty( FILE_MENU , 1 ); QAction * saveItemAsAct = new QAction( tr("Save as...") , menu ); saveItemAsAct->setObjectName( OBJECT_NAME_SAVE_AS_ACT ); connect( saveItemAsAct , SIGNAL(triggered()) , this , SIGNAL(saveItemAs()) ); actions.append(saveItemAsAct); saveItemAsAct->setProperty( FILE_MENU , 1 ); QAction * saveItemAct = new QAction( tr("Save") , menu ); saveItemAct->setObjectName( OBJECT_NAME_SAVE_ACT ); connect( saveItemAct , SIGNAL(triggered()) , this , SLOT(saveItem()) ); actions.append(saveItemAct); saveItemAct->setEnabled( !file().isEmpty() && mIsModified ); saveItemAct->setProperty( FILE_MENU , 1 ); for ( int i = 0 ; i < mContainerActionList.size() ; i++ ) actions.append( mContainerActionList[i]->buildAction() ); QMenu * fileMenu = menu->addMenu( "File" ); fileMenu->setObjectName( OBJECT_NAME_FILE_MENU ); for ( int i = actions.size()-1 ; i >= 0 ; i-- ) { if ( actions[i]->property( FILE_MENU ).toBool() ) { fileMenu->addAction( actions[i] ); actions.removeAt(i); } } QMenu * zMenu = menu->addMenu(tr("Z order")); zMenu->setObjectName( OBJECT_NAME_Z_MENU ); QAction * bringToFrontAct = zMenu->addAction( tr("Bring to front") ); connect( bringToFrontAct , SIGNAL(triggered()) , this , SIGNAL(bringToFront()) ); QAction * bringForwardAct = zMenu->addAction( tr("Bring forward") ); connect( bringForwardAct , SIGNAL(triggered()) , this , SIGNAL(bringForward()) ); QAction * sendBackwardAct = zMenu->addAction( tr("Send backward") ); connect( sendBackwardAct , SIGNAL(triggered()) , this , SIGNAL(sendBackward()) ); QAction * sendToBackAct = zMenu->addAction( tr("Send to back") ); connect( sendToBackAct , SIGNAL(triggered()) , this , SIGNAL(sendToBack()) ); foreach (QAction *a, actions) { menu->addAction(a); } return menu; } //------------------------------------------------------------------------- QVariant QLanguageItem::itemChange( GraphicsItemChange change, const QVariant& value ) { QVariant standardResult = QGraphicsRectItem::itemChange( change , value ); if (mIsStorageModeOn) { return standardResult; } if ( change == QGraphicsItem::ItemSelectedHasChanged ) { Q_EMIT showResizer( value.toBool() ); } return standardResult; } //------------------------------------------------------------------------- void QLanguageItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { mMousePressPoint = event->scenePos(); mCopyDrag = ( event->modifiers() & Qt::AltModifier ); QGraphicsItem::mousePressEvent( event ); event->accept(); } //------------------------------------------------------------------------- void QLanguageItem::updateDragImage() { delete mDragImage; mDragImage = buildDragImage(); mHasToUpdateDragImage = false; } //------------------------------------------------------------------------- QDrag * QLanguageItem::buildDrag(QWidget * widget) { QImage image; if ( mHasToUpdateDragImage ) updateDragImage(); image = mDragImage->scaled( mDragImage->size() * sceneTransform().m11() * scene()->views()[0]->transform().m11() , Qt::KeepAspectRatio , Qt::SmoothTransformation ); QMimeData * data = buildMimeData(); QDrag *drag = new QDrag( widget ); drag->setMimeData(data); drag->setPixmap( QPixmap::fromImage( image ) ); QPointF p = mapFromScene(mMousePressPoint); p.setX( p.x() * sceneTransform().m11() * scene()->views()[0]->transform().m11() ); p.setY( p.y() * sceneTransform().m22() * scene()->views()[0]->transform().m22() ); QPointF hotSpot = mIsStorageModeOn ? QPointF( image.width()/2 , image.height()/2 ) : (p); drag->setHotSpot( hotSpot.toPoint() ); return drag; } //------------------------------------------------------------------------- void QLanguageItem::updateGeometry( const QRectF& newGeometry ) { if ( rect().toRect() != newGeometry.toRect() ) { mHasToUpdateDragImage = true; setRect(newGeometry); Q_EMIT updateChildrenItemsGeometry(newGeometry); } } //------------------------------------------------------------------------- void QLanguageItem::fileChangeEvent( bool isFileRemoved ) { if ( mIsStorageModeOn ) { return; } if ( mIgnoreChangeNotification ) return; if ( !isFileRemoved ) { setModified( true ); mIsProcessingFileChange = true; } Q_EMIT fileChanged(isFileRemoved); mIsProcessingFileChange = false; } //------------------------------------------------------------------------- void QLanguageItem::setModified( bool isModified ) { mIsModified = isModified; Q_EMIT descriptiveNameChanged(); } /* //------------------------------------------------------------------------- void QLanguageItem::paletteActivated( int elementId , QGraphicsItem * , QGraphicsItem * droppedItem ) { QLanguageItem * droppedDecorator = dynamic_cast(droppedItem); assert( droppedDecorator ); Q_EMIT combineItems(elementId, this , droppedDecorator ); } */ #define DRAG_THRESHOLD_DISTANCE 10 //------------------------------------------------------------------------- void QLanguageItem::mouseMoveEvent( QGraphicsSceneMouseEvent *event ) { QGraphicsItem::mouseMoveEvent( event ); if ( ( mMousePressPoint - event->scenePos() ).toPoint().manhattanLength() > DRAG_THRESHOLD_DISTANCE ) { //Select this item setSelected( true ); /* //Unselect all other items int index = 0; while ( scene()->selectedItems().size() > 1 ) { QGraphicsItem * item = scene()->selectedItems()[index]; if ( item == this ) index = 1; else item->setSelected( false ); } */ //Emit dragStarted for QPaletteItem int paletteId = -1; QGraphicsItem * item = 0; Q_EMIT dragStarted( paletteId , item ); //Build QDrag & start the drag. QDrag * d = buildDrag( event->widget() ); d->mimeData()->setData( MIME_PALETTE_ID , QByteArray::number(paletteId) ); d->mimeData()->setData( MIME_PALETTE_ITEM , QByteArray::fromRawData( reinterpret_cast(item) , 4 ) ); d->exec(Qt::CopyAction, Qt::CopyAction); } } //------------------------------------------------------------------------- void QLanguageItem::mouseReleaseEvent( QGraphicsSceneMouseEvent *event ) { QGraphicsItem::mouseReleaseEvent( event ); } //------------------------------------------------------------------------- // Static members /// //------------------------------------------------------------------------- QMultiHash QLanguageItem::mUsedFiles = QMultiHash(); QHash QLanguageItem::mFileContents = QHash(); //------------------------------------------------------------------------- void QLanguageItem::checkAllFiles() { QList usedFiles = mUsedFiles.uniqueKeys(); for ( int i = 0 ; i < usedFiles.size() ; i++ ) { bool fileHasBeenRemoved = ( !QFile::exists( usedFiles[i] ) ); QString newContent = getFileContent( usedFiles[i] ); if ( (fileHasBeenRemoved) || ( mFileContents[ usedFiles[i] ] != newContent ) ) { QList values = mUsedFiles.values( usedFiles[i] ); if ( fileHasBeenRemoved ) { mUsedFiles.remove( usedFiles[i] ); mFileContents.remove( usedFiles[i] ); } else { mFileContents[ usedFiles[i] ] = newContent; } for ( int j = 0 ; j < values.size() ; j++ ) { values[j]->fileChangeEvent(fileHasBeenRemoved); } } } } //------------------------------------------------------------------------- void QLanguageItem::fileChanged( const QString& fileName , const QString& newContent ) { mFileContents[ fileName ] = newContent; QList values = mUsedFiles.values( fileName ); for ( int j = 0 ; j < values.size() ; j++ ) { values[j]->fileChangeEvent(false); } } //------------------------------------------------------------------------- void QLanguageItem::fileRemoved( const QString& fileName ) { QList values = mUsedFiles.values( fileName ); for ( int j = 0 ; j < values.size() ; j++ ) { values[j]->fileChangeEvent(true); } } //------------------------------------------------------------------------ // QLanguageItemAction class // //------------------------------------------------------------------------ //------------------------------------------------------------------------ QLanguageItemAction::QLanguageItemAction( QLanguageItem * container , const QString& actionLabel , const QVariant& actionData ) : QObject(container), mContainer(container), mActionLabel(actionLabel), mActionData( actionData ) { mContainer->addContainerAction(this); } //------------------------------------------------------------------------- QAction * QLanguageItemAction::buildAction() const { QAction * result = new QAction( mActionLabel , mContainer ); result->setData( mActionData ); connect(result , SIGNAL(triggered()) , this , SLOT(triggered()) ); return result; } //------------------------------------------------------------------------- void QLanguageItemAction::triggered() { Q_EMIT triggered( mContainer ); } //------------------------------------------------------------------------- // Other functions /// //------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------------------ void paintOnDevice( QPaintDevice * device , QGraphicsItem * item , float scaleFactor , const QRect& painterWindow ) { QRectF rect(0,0,device->width() , device->height() ); QPainter painter; painter.begin( device ); if ( painterWindow.isValid() ) painter.setWindow( painterWindow ); QStyleOptionGraphicsItem option; option.exposedRect = rect; painter.scale( scaleFactor , scaleFactor ); item->paint( &painter , &option , 0 ); painter.end(); }; //------------------------------------------------------------------------------------------------------------------------ QImage itemToImage( QGraphicsItem * item , float scaleFactor , unsigned int backgroundColor , bool setPainterWindow ) { QRectF picRect = item->boundingRect(); QImage pic( (int)(picRect.width() * scaleFactor) , (int)(picRect.height() * scaleFactor) , QImage::Format_ARGB32_Premultiplied ); pic.fill( backgroundColor ); QRect painterWindow; if ( setPainterWindow ) painterWindow = picRect.toRect(); paintOnDevice( &pic , item , scaleFactor , painterWindow ); return pic; }; FaustWorks-0.4/QLanguageItem.h0000755000175000017500000003172612130743520014774 0ustar miramira/* * QLanguageItem.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef LANGUAGE_ITEM_H #define LANGUAGE_ITEM_H class QLanguageItemAction; class QPaletteItemDropper; #include #include #include #include #include #include #include #include #define DOM_LANGUAGE_ITEM "Item" #define MIME_DO_COPY "MimeDoCopy" #define MIME_PALETTE_ID "MimePaletteId" #define MIME_PALETTE_ITEM "MimePaletteItem" #define FONT_SIZE 12 #define OBJECT_NAME_DELETE_ITEM_AND_FILE_ACT "DeleteItemAndFileAct" #define OBJECT_NAME_UNLINK_ACT "UnlinkAct" #define OBJECT_NAME_SAVE_AS_ACT "SaveAsAct" #define OBJECT_NAME_SAVE_ACT "SaveAct" #define OBJECT_NAME_RELOAD_ACT "ReloadAct" #define OBJECT_NAME_FILE_MENU "FileMenu" #define OBJECT_NAME_Z_MENU "ZMenu" /*! * \brief QTextPathItem is QGraphicsPathItem with a centered text at its center. */ class QTextPathItem : public QGraphicsPathItem { public : QTextPathItem( const QString& text , bool centerText , const QColor& textColor , const QFont& textFont , float textPenWidth , QGraphicsItem* parent = 0 ); QGraphicsSimpleTextItem * textItem() { return mText; } void setText(const QString& text); void setPath( const QPainterPath& p ); protected : void updateTextPos(); QGraphicsSimpleTextItem * mText; bool mCenterText; }; /** * \brief A QLanguageItem is a QGraphicsItem with a textual attribute, its code. * Typically, the code will be expressed in a certain languauge, * and will be used to generate the item's appearance & shape. * * A QLanguageItem may be "file-linked" or not. An item is "file-linked" when * its code has been loaded from a file (loadFile( const QString& fileName )), * or saved to a file (save(const QString& fileName)). A "file-linked" item can * be unlinked with unlinkFile(). */ //class QLanguageItem : public QObject , public QSelectionItem class QLanguageItem : public QObject , public QGraphicsRectItem { Q_OBJECT public: /** * \brief Constructor. */ QLanguageItem(QGraphicsItem * parent = 0); virtual ~QLanguageItem(); /** * \brief The painting of the QLanguageItem is undefined. */ void paint( QPainter * , const QStyleOptionGraphicsItem *, QWidget * ) {} /** * \brief Sets the item's code. */ virtual bool setCode( const QString& code ) = 0; /** * \brief Returns the item's code. */ virtual QString code() const = 0; /** * \brief Returns true if the item's code is valid. */ virtual bool isValid() const { return true; } /** * \brief Returns an error message relative to the item's code. */ virtual QString lastErrorMessage() const { return ""; } virtual float currentScale() const = 0; /** * \brief Loads the specified text file and sets the item's code with the file's contents. */ void loadFile( const QString& fileName ); /** * \brief Returns the item's file. If no file has been loaded (with loadFile), returns "". */ QString file() const; /** * \brief Saves the code() to 'fileName'. */ virtual void save(const QString& fileName); /*! * \brief Create a new QDomElement storing the properties of the QLanguageItem. * * \note The QDomElement may be further used to setup another QLanguageItem, using QLanguageItem::loadFromDomElement. */ virtual QDomElement saveToDomElement( QDomDocument * doc); /*! * \brief QLanguageItem comparator. The default implementation compares the items' codes. */ virtual bool isEqualTo( QLanguageItem * item ) const; /** * \brief The standard virtual QGraphicsItem::keyPressEvent made public, because GraphicsSceneMainWindow * intercepts this event. */ virtual void keyPressEvent ( QKeyEvent * e ); /** * \brief Changes the item's position to destPoint. Only used when dropping the item inside the scene to move it : * uses the mouse position when the drag started. * * \return Returns the resulting movement. */ QPointF moveItem( const QPointF& destPoint ); /*! * \brief Sets the mimeId of the QLanguageItem. The mimeId is included in the QMimeData * when drag'N'dropping the QLanguageItem, and then is used by drop targets to accept/refuse the drop. */ void setMimeId(const QString& mimeId); /*! * \brief Sets if the QLanguageItem is in the main QGraphicsItem or if it's in a storage/history zone. */ virtual void setStorageMode( bool isStorageModeOn ); /*! * \brief Adds a QLanguageItemAction ; the QLanguageItemAction's action will be used in * the QLanguageItem's contextual menu. */ void addContainerAction( QLanguageItemAction * containerAction ); /** * \brief Returns true if the item is modified. * * An item becomes modified when calling codeChanged(). * It is not modified when calling saveItem, loadItem, reloadItem. */ bool isModified() const; /** * \brief Returns true if file() is defined, whereas the file doesn't exists. */ bool fileNotFound() const; /** * \brief Returns the descriptive file name. * * The descriptive file name is name() + "*" if the item isModified. */ QString getDescriptiveFileName() const; /** * \brief Returns the item's name. * * The name is : * - for a file-linked item, the item's file (not its full path) * - for a not file-linked item, "untitled" */ QString name() const; void plug( QPaletteItemDropper* dropper ); Q_SIGNALS: /*! * \brief Used internally. Emit when the contained QGuidoItem's format changes. */ void updateChildrenItemsGeometry(const QRectF& newGeometry); /*! * \brief Emitted when the item asks to be stored. */ void storeItem(); /** * \brief Emitted when the item asks to be be saved in a new file. */ void saveItemAs(); /*! * \brief Emitted when the item removes itself from the scene it was in. */ void removed(); /*! * \brief Emitted when the item has changed its code from inside. */ void itemHasBeenReloaded(); //QItemResizer connection void showResizer(bool isShown); /** * \brief Emitted when the item's file has been changed from outside : * - if isFileRemoved, the file has been removed or renamed * - if not, its content has changed */ void fileChanged(bool isFileRemoved); /** * \brief Emitted when descriptive file name has changed. (see getDescriptiveFileName) */ void descriptiveNameChanged(); void dragStarted(int & inId , QGraphicsItem*& inDraggedItem); /*! * \brief Emitted when the item scale has been changed from inside. */ void scaleChanged(float newScale); /*! * \brief Emitted when the item asks to be brought to front/forward/backward/back. */ void bringToFront(); void bringForward(); void sendBackward(); void sendToBack(); public Q_SLOTS: /** * \brief Resize the item with the specified QRectF. */ virtual void resized( const QRectF& newRect ) = 0; /** * \brief For a file-linked item, saves the item's code to file(). Else, does nothing. */ void saveItem(); /** * \brief For a file-linked item, sets the item's code with the contents of file(). Else, does nothing. * * If the item isModified(), ask for a confirmation before reloading. */ void reloadItem(); /** * \brief If the item was "file-linked", it won't be anymore. The previously linked file * is not affected in any way by this operation. */ void unlinkFile(); protected Q_SLOTS: /** * \brief Must be called after that the item's code() has changed (typically, in a QLanguageItem::setCode implementation). */ void codeChanged(); /** * \brief UI asks if the user wants to remove the item and the file() (for a file-linked item), * before actually doing it. * * If the item is not file-linked, does nothing. */ void removeItemAndFile(); protected: /** * \brief Loads the contents of the QDomElement. The QDomElement must have initially been created by QLanguageItem::saveToDomElement. */ void load(const QDomElement * domElement); /** * \brief Setup the item with the data of the other item. */ void load(const QLanguageItem * other); /** * \brief Loads the contents of the QMimeData. The QMimeData must have initially been created by QLanguageItem::buildMimeData. */ void load(const QMimeData * mimeData); /** * \brief Changes the file name. */ virtual void setFile( const QString& fileName ); void updateGeometry( const QRectF& newGeometry ); /*! * \brief Returns the QMenu to be used in contextMenuEvent. Caller takes ownership of the menu. */ virtual QMenu * buildContextMenu(); /** * \brief QGraphicsItem virtual function implementation. */ virtual QVariant itemChange ( GraphicsItemChange change, const QVariant& value ); /*! * \brief Builds an image that will be used when draging the item. (see QDrag::pixmap() ) */ virtual QImage* buildDragImage() = 0; /*! * \brief Builds the QMimeData containing the properties of the QLanguageItem. * * Subclasses may extend this function to add specified properties. * * \note QLanguageItem::load(QMimeData*) is the symmetrical function. */ virtual QMimeData * buildMimeData(); /** * \brief Sets isModified() to the specified value. (see QLanguageItem::isModified() ) */ virtual void setModified( bool isModified ); /** * \brief QGraphicsItem virtual function implementation. */ void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ); /** * \brief QGraphicsItem virtual function implementation. */ void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent( QGraphicsSceneMouseEvent *event ); void mouseReleaseEvent( QGraphicsSceneMouseEvent *event ); /*! * \brief Updates the cached image used when drag'n'dropping the QLanguageItem. Used only when mIsStorageModeOn == true. */ void updateDragImage(); void fileChangeEvent( bool isFileRemoved ); QString mMimeId; bool mIsStorageModeOn; QImage * mDragImage; bool mHasToUpdateDragImage; QList mContainerActionList; QSizeF mMinSize, mMaxSize; QString mFile; bool mIsModified; bool mIgnoreChangeNotification; bool mIsProcessingFileChange; QPointF mMousePressPoint; bool mCopyDrag; private: /** * \brief Build the QDrag of this item, with source QWidget. */ QDrag * buildDrag(QWidget * widget); // -------------------- Static members -------------------- public : static void checkAllFiles(); static void fileChanged( const QString& fileName , const QString& newContent ); static void fileRemoved( const QString& fileName ); protected : /** * \brief Registers the fileName as "used by" the usingItem. */ static void addFile(const QString& fileName , QLanguageItem* usingItem); static void removeFile(const QString& fileName , QLanguageItem* usingItem); static QMultiHash mUsedFiles; static QHash mFileContents; }; /** * \brief QLanguageItemAction allows to add an item in a QLanguageItem's contextual menu ; * QLanguageItemAction::triggered signal will be emitted when the action is triggered. * * - When you build a QLanguageItemAction on a QLanguageItem, * it calls QGuidoItemContainaer::addContainerAction(this). * - QLanguageItemAction::buildAction builds an action ( owned by the QLanguageItem ) ; when this action * will be triggered, the QuidoItemContainerAction will emit the signal triggered(QLanguageItem*). * * \note The QLanguageItem takes ownership of the QLanguageItemAction. */ class QLanguageItemAction : public QObject { Q_OBJECT public: QLanguageItemAction( QLanguageItem * container , const QString& actionLabel , const QVariant& actionData = QString() ); QAction * buildAction() const; Q_SIGNALS: void triggered(QLanguageItem * container); private Q_SLOTS: void triggered(); protected : QLanguageItem * mContainer; QString mActionLabel; QVariant mActionData; }; /*! * \brief * (From QGraphicsItem.cpp in Qt sources) !*/ QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen); void paintOnDevice( QPaintDevice * device , QGraphicsItem * item , float scaleFactor , const QRect& painterWindow = QRect() ); QImage itemToImage( QGraphicsItem * item , float scaleFactor = 1.0f , unsigned int backgroundColor = 0 , bool setPainterWindow = false ); QAction * newSeparator(QObject * parent); #endif //LANGUAGE_ITEM_H FaustWorks-0.4/QLanguageItemFactory.h0000755000175000017500000000402512130743520016314 0ustar miramira/* * QLanguageItemFactory.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef LANGUAGE_ITEM_FACTORY_H #define LANGUAGE_ITEM_FACTORY_H #include #include #include #include "QLanguageItem.h" /* * \brief A factory interface, that can build QLanguageItem from : * - scratch, * - another QLanguageItem (copy) * - a QMimeData (d&d information) * - a QDomElement (element of a XML-like file) */ class QLanguageItemFactory { public: virtual ~QLanguageItemFactory() {} virtual QLanguageItem * buildLanguageItem( QGraphicsItem * parent = 0 ) = 0; virtual QLanguageItem * buildLanguageItem( const QLanguageItem * other , QGraphicsItem * parent = 0) = 0; virtual QLanguageItem * buildLanguageItem( const QMimeData * mimeData , QGraphicsItem * parent = 0) = 0; virtual QLanguageItem * buildLanguageItem( const QDomElement * domElement , QGraphicsItem * parent = 0) = 0; virtual QLanguageItem * buildLanguageItemFromFile( const QString& fileName , QGraphicsItem * parent = 0 ) { QLanguageItem * item = buildLanguageItem(parent); item->loadFile(fileName); return item; } virtual QLanguageItem * buildLanguageItemFromCode( const QString& code , QGraphicsItem * parent = 0 ) { QLanguageItem * item = buildLanguageItem(parent); item->setCode(code); return item; } }; #endif //GUIDO_ITEM_CONTAINER_FACTORY_H FaustWorks-0.4/QPaletteItem.cpp0000755000175000017500000005212412130743520015175 0ustar miramira/* * QPaletteItem.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QPaletteItem.h" #include #include #include #include #include #include #define PALETTE_BRUSH_ALPHA 200 #define PALETTE_HIGHLIGHT_BRUSH QBrush( QColor(255,230,230,PALETTE_BRUSH_ALPHA) ) #define PALETTE_HIGHLIGHT_PEN QPen( QColor(255,0,0,220) ) #define PALETTE_HOLE_RATIO 0.25f #define MIN(a,b) ( ((a)<(b)) ? (a) : (b) ) #define MAX(a,b) ( ((a)>(b)) ? (a) : (b) ) #define PALETTE_DEFAULT_RADIUS 100 #define SHOW_ANIMATION_TIMER_INTERVAL 80 #define SHOW_ANIMATION_TIMER_ITERATION 4 //------------------------------------------------------------------------- // QPaletteItem class /// //------------------------------------------------------------------------- //------------------------------------------------------------------------- QPaletteItem::QPaletteItem( const QList& handledDroppedItemIds , const QList& handledTargetItemIds , float radius , QGraphicsItem * parent ) : QGraphicsEllipseItem( QRect() , parent ), mHandledDroppedItemIds(handledDroppedItemIds), mHandledTargetItemIds(handledTargetItemIds) { init(radius); } //------------------------------------------------------------------------- QPaletteItem::QPaletteItem( int paletteId , float radius , QGraphicsItem * parent ) : QGraphicsEllipseItem( QRect() , parent ) { mHandledTargetItemIds << paletteId; mHandledDroppedItemIds << paletteId; init(radius); } //------------------------------------------------------------------------- void QPaletteItem::init(float radius) { setRadius( radius ); mHighlightedInteractionIndex = -1; mOriginAngle = 0; mIsPaletteEnabled = true; mPositioningPolicy = CENTER_POLICY; setVisible(false); mHighlightPen = PALETTE_HIGHLIGHT_PEN; mHighlightBrush = PALETTE_HIGHLIGHT_BRUSH; /* mShowAnimationTimer = new QTimer(this); connect( mShowAnimationTimer , SIGNAL(timeout()) , this , SLOT( showAnimation() ) ); */ QPaletteManager::instance()->registerPalette( this ); } //------------------------------------------------------------------------- QPaletteItem::~QPaletteItem() { for ( int i = 0 ; i < mInteractions.size() ; i++ ) { delete mInteractions[i].mPath; } QPaletteManager::instance()->unregisterPalette( this ); } //------------------------------------------------------------------------- void QPaletteItem::setRadius( float newRadius ) { QPointF oldCenter = pos() + rect().center(); mRadius = newRadius; setRect( QRectF(0,0,mRadius*2,mRadius*2) ); mNeedReorder = true; update(); setCenter( oldCenter ); } //------------------------------------------------------------------------- void QPaletteItem::addInteraction( QGraphicsItem * itemIcon , int interactionId ) { itemIcon->setParentItem( this ); Interaction interaction; interaction.mId = interactionId; interaction.mItem = itemIcon; interaction.mPath = 0; mInteractions.append( interaction ); mNeedReorder = true; update(); } //------------------------------------------------------------------------- void QPaletteItem::setOriginAngle( int degreeOriginAngle ) { mOriginAngle = degreeOriginAngle; mNeedReorder = true; update(); } //------------------------------------------------------------------------- void QPaletteItem::setHighlightStyle( const QPen& pen , const QBrush& brush ) { mHighlightPen = pen; mHighlightBrush = brush; } #define PI 3.1416f float degToRad( int degree ) { return 2*PI*degree / 360.0f; } QPointF polarToOrtho( float radius , float teta ) { return radius * QPointF( cos(teta) , -sin(teta) ); } QPointF polarToOrtho( float radius , int angle ) { float teta = degToRad( angle ); return polarToOrtho( radius , teta ); } //------------------------------------------------------------------------- void QPaletteItem::paint(QPainter* painter , const QStyleOptionGraphicsItem* , QWidget* ) { if ( mNeedReorder ) reorderItems(); painter->setRenderHint( QPainter::Antialiasing ); //Render non-highlighted parts QColor brushColor( brush().color() ); brushColor.setAlpha( PALETTE_BRUSH_ALPHA ); painter->setBrush( brushColor.lighter(150) ); painter->setPen( pen() ); for ( int i = 0 ; i < mInteractions.size() ; i++ ) { if ( i == mHighlightedInteractionIndex ) continue; painter->drawPath( *(mInteractions[i].mPath) ); } //Render highlighted part if ( mHighlightedInteractionIndex != -1 ) { painter->setBrush( mHighlightBrush ); painter->setPen( mHighlightPen ); painter->drawPath( *(mInteractions[mHighlightedInteractionIndex].mPath) ); } } //------------------------------------------------------------------------- void QPaletteItem::moveOver( const QPointF& pos ) { if (!mIsPaletteEnabled) return; if ( mNeedReorder ) reorderItems(); for ( int i = 0 ; i < mInteractions.size() ; i++ ) { if ( mInteractions[i].mPath->contains(pos) ) { if ( mHighlightedInteractionIndex != i ) { mHighlightedInteractionIndex = i; update(); } return; } } if ( mHighlightedInteractionIndex != -1 ) { mHighlightedInteractionIndex = -1; update(); } } //------------------------------------------------------------------------- bool QPaletteItem::hasActiveInteraction() const { return ( mHighlightedInteractionIndex != -1 ); } //------------------------------------------------------------------------- int QPaletteItem::activeInteraction() const { if ( !hasActiveInteraction() ) return -1; else return mInteractions[ mHighlightedInteractionIndex ].mId; } /* //------------------------------------------------------------------------- void QPaletteItem::specialShow() { mShowAnimationCounter = 0; mShowAnimationTimer->start( SHOW_ANIMATION_TIMER_INTERVAL ); } //------------------------------------------------------------------------- void QPaletteItem::specialHide() { setVisible( false ); mShowAnimationTimer->stop(); } //------------------------------------------------------------------------- void QPaletteItem::showAnimation() { if ( mShowAnimationCounter < SHOW_ANIMATION_TIMER_ITERATION ) { setVisible( !isVisible() ); mShowAnimationCounter++; } else { mShowAnimationTimer->stop(); setVisible( true ); } } */ #define RADIUS_FACTOR_INCREMENT 0.1f #define RADIUS_FACTOR_MARGIN 0.1f #define HYPOTHENUSE(a) (sqrt( (a).width() * (a).width() + (a).height() * (a).height() )) //------------------------------------------------------------------------- void QPaletteItem::reorderItems() { QPointF center = QPointF( rect().width()/2 , rect().height()/2 ); if ( mInteractions.size() == 0 ) return; if ( mInteractions.size() == 1 ) { if ( mInteractions[0].mPath ) delete mInteractions[0].mPath; mInteractions[0].mPath = new QPainterPath(); mInteractions[0].mPath->addEllipse(rect()); QRectF itemBoundingRect = mInteractions[0].mItem->mapToParent( mInteractions[0].mItem->boundingRect() ).boundingRect(); mInteractions[0].mItem->setPos( center - QPointF(itemBoundingRect.width()/2 , itemBoundingRect.height()/2) ); while ( !mInteractions[0].mPath->contains( itemBoundingRect ) ) { mInteractions[0].mItem->scale(0.9f , 0.9f); itemBoundingRect = mInteractions[0].mItem->mapToParent( mInteractions[0].mItem->boundingRect() ).boundingRect(); mInteractions[0].mItem->setPos( center - QPointF(itemBoundingRect.width()/2 , itemBoundingRect.height()/2) ); } while ( mInteractions[0].mPath->contains( itemBoundingRect ) ) { mInteractions[0].mItem->scale(1/0.9f , 1/0.9f); itemBoundingRect = mInteractions[0].mItem->mapToParent( mInteractions[0].mItem->boundingRect() ).boundingRect(); mInteractions[0].mItem->setPos( center - QPointF(itemBoundingRect.width()/2 , itemBoundingRect.height()/2) ); } mInteractions[0].mItem->scale(0.9f , 0.9f); return; } QRectF littleRect(rect().x() , rect().y() , rect().width() * PALETTE_HOLE_RATIO , rect().height() * PALETTE_HOLE_RATIO ); littleRect.moveTo( rect().x() + rect().width()/2 - littleRect.width()/2 , rect().y() + rect().height()/2 - littleRect.height()/2 ); int baseItemAngle = 360 / mInteractions.size(); int completingAngle = 360 - baseItemAngle * mInteractions.size(); int currentAngle = mOriginAngle - baseItemAngle/2; for ( int i = 0 ; i < mInteractions.size() ; i++ ) { int itemAngle = baseItemAngle; if ( completingAngle > 0 ) { itemAngle++; completingAngle--; } // A. Build the element's pie path. if ( mInteractions[i].mPath ) delete mInteractions[i].mPath; mInteractions[i].mPath = new QPainterPath(); QPointF startPointA = center + polarToOrtho( littleRect.width()/2 , currentAngle ); QPointF endPointA = center + polarToOrtho( rect().width()/2 , currentAngle ); mInteractions[i].mPath->moveTo(startPointA); mInteractions[i].mPath->lineTo(endPointA); mInteractions[i].mPath->arcTo(rect(), currentAngle, itemAngle); mInteractions[i].mPath->arcTo(littleRect, currentAngle+itemAngle, -itemAngle); // B. Resize & set the position of the element's item. float radiusFactor = 0.5f; float resultingScale = 0; float maxScale = 0; float posRadius; while ( ( resultingScale >= maxScale ) && ( radiusFactor < (1-RADIUS_FACTOR_MARGIN) ) ) { mInteractions[i].mItem->resetTransform(); // B.1 Initialize: Put the element's item (<=> icon) at the center of its pie. posRadius = littleRect.width()/2 + (mRadius - littleRect.width()/2) * radiusFactor; QRectF itemBoundingRect = mInteractions[i].mItem->mapToParent( mInteractions[i].mItem->boundingRect() ).boundingRect(); QPainterPath itemBoundingCircle; float boundingCircleRadius = HYPOTHENUSE( itemBoundingRect ) / 2.0f; float startRadius = boundingCircleRadius; itemBoundingCircle.addEllipse( itemBoundingRect.center() , boundingCircleRadius , boundingCircleRadius ); // B.2 Make it fit in : Scale down the element's item until it fits inside the element's pie. while ( !mInteractions[i].mPath->contains( itemBoundingCircle ) ) { boundingCircleRadius = 0.9f * boundingCircleRadius; itemBoundingCircle = QPainterPath(); itemBoundingCircle.addEllipse( center + polarToOrtho( posRadius, currentAngle + itemAngle/2 ) , boundingCircleRadius , boundingCircleRadius ); } // B.3 Make it the biggest possible : And then, scale up the element's item while it fits inside the element's pie. while ( mInteractions[i].mPath->contains( itemBoundingCircle ) ) { boundingCircleRadius = boundingCircleRadius / 0.9f; itemBoundingCircle = QPainterPath(); itemBoundingCircle.addEllipse( center + polarToOrtho( posRadius, currentAngle + itemAngle/2 ) , boundingCircleRadius , boundingCircleRadius ); } // B.4 Finalize : Finally, scale down 1 time the element's item, so that // - the scale of the item is the biggest possible, // - and the item still fits in the pie. maxScale = resultingScale; resultingScale = boundingCircleRadius / startRadius; radiusFactor += RADIUS_FACTOR_INCREMENT; } posRadius = littleRect.width()/2 + (mRadius - littleRect.width()/2) * (radiusFactor-2*RADIUS_FACTOR_INCREMENT); mInteractions[i].mItem->scale( maxScale , maxScale ); QRectF itemBoundingRect = mInteractions[i].mItem->mapToParent( mInteractions[i].mItem->boundingRect() ).boundingRect(); mInteractions[i].mItem->setPos( center + polarToOrtho( posRadius, currentAngle + itemAngle/2 ) - QPointF(itemBoundingRect.width()/2 , itemBoundingRect.height()/2) ); currentAngle += itemAngle; } mNeedReorder = false; } //------------------------------------------------------------------------- void QPaletteItem::setCenter( const QPointF& pos ) { setPos( pos - rect().center() ); } //------------------------------------------------------------------------- void QPaletteItem::setPaletteEnabled(bool isEnabled) { mIsPaletteEnabled = isEnabled; } //------------------------------------------------------------------------- bool QPaletteItem::isPaletteEnabled() const { return mIsPaletteEnabled; } //------------------------------------------------------------------------- bool QPaletteItem::canHandle(int droppedItemId , int targetItemId) const { return ( mHandledDroppedItemIds.contains( droppedItemId ) && mHandledTargetItemIds.contains( targetItemId ) ); } //------------------------------------------------------------------------- void QPaletteItem::setPositioningPolicy( const PositioningPolicy& policy ) { mPositioningPolicy = policy; } //------------------------------------------------------------------------- void QPaletteItem::showOnItem( const QGraphicsItem * target , const QGraphicsItem * ) { switch ( mPositioningPolicy ) { case CENTER_POLICY: setCenter( target->sceneBoundingRect().center() ); break; case CENTER_AND_RESIZE_POLICY: setCenter( target->sceneBoundingRect().center() ); setRadius( target->sceneBoundingRect().height()/2.0f ); break; } QList colliding = collidingItems(); float z = zValue(); for ( int i = 0 ; i < colliding.size() ; i++ ) z = MAX( z , colliding[i]->zValue() ); setZValue( z + 0.1f ); } //------------------------------------------------------------------------- // QPaletteItemDropper class /// //------------------------------------------------------------------------- //------------------------------------------------------------------------- QPaletteItemDropper::QPaletteItemDropper(int dropperId , const QList& acceptedPaletteIds, QGraphicsItem * item , QGraphicsItem * parent) : QGraphicsRectItem( QRect() , parent) , mItem(item) , mPaletteId(dropperId), mAcceptedPaletteIds(acceptedPaletteIds) { setPen(Qt::NoPen); setBrush(Qt::NoBrush); QPaletteManager::instance()->registerDropper( this ); if ( mItem ) updateGeometry( mItem->boundingRect() ); } //------------------------------------------------------------------------- QPaletteItemDropper::~QPaletteItemDropper() { QPaletteManager::instance()->unregisterDropper( this ); } //------------------------------------------------------------------------- void QPaletteItemDropper::updateGeometry(const QRectF& newGeometry) { setRect( newGeometry ); } //------------------------------------------------------------------------- void QPaletteItemDropper::dragStarted(int & outId , QGraphicsItem*& outItem) { outId = mPaletteId; outItem = mItem; // QPaletteManager::instance()->setDraggedItem( mItem , mPaletteId ); QPaletteManager::instance()->mShowPaletteTimer->stop(); } //------------------------------------------------------------------------- int QPaletteItemDropper::paletteId() const { return mPaletteId; } //------------------------------------------------------------------------- bool QPaletteItemDropper::isAccepted(int paletteId) const { return mAcceptedPaletteIds.contains( paletteId ); } //------------------------------------------------------------------------- // QPaletteManager class /// //------------------------------------------------------------------------- QPaletteManager * QPaletteManager::mInstance = 0; //------------------------------------------------------------------------- QPaletteManager * QPaletteManager::instance() { if ( !mInstance ) mInstance = new QPaletteManager(); return mInstance; } //------------------------------------------------------------------------- QPaletteManager::QPaletteManager() { mShowPaletteTimer = new QTimer(this); connect( mShowPaletteTimer , SIGNAL(timeout()) , this , SLOT( showPalette() ) ); mShownPalette = 0; mActivationDelay = 1000; } //------------------------------------------------------------------------- void QPaletteManager::move(const QPointF& mouseScenePos , const QGraphicsScene * scene , int draggedItemPaletteId , QGraphicsItem * draggedItem ) { //If a palette is already active and the mouse is still over the same drop destination. if ( mShownPalette ) { if ( mDropDestination->isUnderMouse() || mShownPalette->isUnderMouse() ) { //Call the palette::moveOver to highlight the undermouse interaction. mShownPalette->moveOver( mShownPalette->mapFromScene( mouseScenePos ) ); return; } } QPaletteItemDropper * oldDropDestination = mDropDestination; QPaletteItemDropper * dropDestination = 0; //Watch if there is a QPaletteItemDropper undermouse that accepts the currently dragged item's paletteId. //Store the QPaletteItemDropper found in mDropDestination for ( int i = 0 ; i < mDroppers.size() ; i++ ) { if ( ( mDroppers[i]->scene() == scene ) && ( mDroppers[i]->isAccepted( draggedItemPaletteId ) ) && ( mDroppers[i]->item() != draggedItem ) && ( mDroppers[i]->isUnderMouse() ) ) { dropDestination = mDroppers[i]; break; } } //If mDropDestination has changed : // - if there was one, stop highlighting the oldDropDestination // - if there is one, start highlighting the new palette if ( oldDropDestination != dropDestination ) { if ( mShownPalette ) { mShownPalette->setVisible( false ); // mShownPalette->specialHide(); mShownPalette = 0; } mShowPaletteTimer->stop(); } if ( dropDestination ) { if ( !mShownPalette ) { mDraggedItemPaletteId = draggedItemPaletteId; mDraggedItem = draggedItem; mShowPaletteTimer->start( mActivationDelay ); mLastMousePos = mouseScenePos; } } mDropDestination = dropDestination; } //------------------------------------------------------------------------- bool QPaletteManager::drop(const QGraphicsScene * scene , int draggedItemPaletteId , QGraphicsItem * draggedItem ) { bool interactionHasBeenActivated = false; // If there is an active palette if ( mShownPalette ) { // If the drop has been done on a palette interaction, and in the right scene, // then emit the corresponding "interactionActivated" signal if ( mShownPalette->hasActiveInteraction() && ( mShownPalette->scene() == scene ) ) { Q_EMIT interactionActivated(draggedItem, mDropDestination->item(), draggedItemPaletteId , mDropDestination->paletteId() , mShownPalette->activeInteraction()); interactionHasBeenActivated = true; } } // setDragOut(); if ( mShownPalette ) { // The palette is no longer active. mShownPalette->setVisible( false ); mShownPalette = 0; } mShowPaletteTimer->stop(); mDropDestination = 0; return interactionHasBeenActivated; } /* //------------------------------------------------------------------------- void QPaletteManager::setDragIn() { qDebug() << "QPaletteManager::setDragIn()"; mIsDragging = true; } //------------------------------------------------------------------------- void QPaletteManager::setDragOut() { qDebug() << "QPaletteManager::setDragOut()"; mIsDragging = false; if ( mShownPalette ) { // The palette is no longer active. mShownPalette->setVisible( false ); mShownPalette = 0; } mShowPaletteTimer->stop(); mDropDestination = 0; } */ //------------------------------------------------------------------------- void QPaletteManager::setActivationDelay(int msTime) { mActivationDelay = msTime; } //------------------------------------------------------------------------- void QPaletteManager::registerPalette(QPaletteItem* palette) { mPalettes << palette; } //------------------------------------------------------------------------- void QPaletteManager::unregisterPalette(QPaletteItem* palette) { mPalettes.removeAll( palette ); } //------------------------------------------------------------------------- void QPaletteManager::registerDropper(QPaletteItemDropper* dropper) { mDroppers << dropper; } //------------------------------------------------------------------------- void QPaletteManager::unregisterDropper(QPaletteItemDropper* dropper) { mDroppers.removeAll( dropper ); } /* //------------------------------------------------------------------------- void QPaletteManager::setDraggedItem( QGraphicsItem* item , int paletteId ) { qDebug() << "QPaletteManager::setDraggedItem : " << paletteId; mDraggedItem = item; mDraggedItemPaletteId = paletteId; mShowPaletteTimer->stop(); } */ //------------------------------------------------------------------------- void QPaletteManager::showPalette() { mShowPaletteTimer->stop(); // Looking for an enabled palette with the ID corresponding to the dragged item, in the same scene as the mDropDestination for ( int i = 0 ; i < mPalettes.size() ; i++ ) { if ( ( mPalettes[i]->isPaletteEnabled()) && ( mPalettes[i]->canHandle( mDraggedItemPaletteId , mDropDestination->paletteId() ) ) && ( mPalettes[i]->scene() == mDropDestination->scene() ) ) { mShownPalette = mPalettes[i]; mShownPalette->setVisible( true ); // mShownPalette->specialShow(); mShownPalette->showOnItem( mDropDestination->item() , mDraggedItem ); mShownPalette->moveOver( mShownPalette->mapFromScene( mLastMousePos ) ); break; } } } FaustWorks-0.4/QPaletteItem.h0000755000175000017500000003142112130743520014637 0ustar miramira/* * QPaletteItem.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef PALETTE_ITEM_H #define PALETTE_ITEM_H class QPaletteItemDropper; class QPaletteManager; //#include "QPluggableItem.h" #include #include #include #include /*! \brief The QPaletteItem is part of the QPaletteManager system (see QPaletteManager). * * To use a QPaletteItem in the QPaletteItem system, add it to the same scene as the QGraphicsItems * that will use the QPaletteItem system. * * How to use a QPaletteItem: * - You must specify in the QPaletteItem's constructor the id of the QPaletteItemDroppers that * it can handle, both as droppedItem and as targetItem * - The QPaletteItem is a circle ; you can specify its radius. * - The circle is split in different equal pies ; each pie is for one interaction. * - You can add a new interaction with addInteraction(QGraphicsItem*,int). The QGraphicsItem* will be * the icon of the interaction (note : the QPaletteItem takes ownership of the QGraphicsItem). * The int will be the id of the interaction, used by the signal interactionActivated. * The interaction's icon is displayed at the center of the interaction's pie. The pies * are ordered in positive trigonometric order. By default, the first pie is at angle zero * (right of the palette), but you can set this with setOriginAngle(int). * * According to the place where you drop the item, it activate one type of interaction. Then the QPaletteManager::mInstance * will emit the signal interactionActivated with the id of the activated interaction, and the dropped and * destination items. * * To use several equivalent QPaletteItem (they manage the same QPaletteItemDropper's ids) but switching between * them, you can enable/disable the QPaletteItem with QPaletteItem::setPaletteEnabled. * * TODO: WRITE DOC ABOUT MAKING QPaletteItem SUBCLASSES. */ class QPaletteItem : public QObject , public QGraphicsEllipseItem { Q_OBJECT friend class QPaletteManager; public: /*! * \brief Constructor. * * \param handledDroppedItemIds List of ids that the QPaletteItem can manage as "droppedItems". Note: Ids >= 0. * \param handledTargetItemIds List of ids that the QPaletteItem can manage as "targetItems". Note: Ids >= 0. * \param radius Radius of the QPaletteItem circle. * \param parent The parentItem of the QPaletteItem. */ QPaletteItem( const QList& handledDroppedItemIds , const QList& handledTargetItemIds , float radius , QGraphicsItem * parent = 0 ); /*! * \brief Convenience constructor. Equivalent to calling QPaletteItem( QList() << paletteId , QList() << paletteId , radius , parent ). * Note: Ids >= 0. */ QPaletteItem( int paletteId , float radius , QGraphicsItem * parent = 0 ); virtual ~QPaletteItem(); /*! \brief Add a new interaction to the palette, with the specified QGraphicsItem as an icon, and * the specified Id. */ void addInteraction( QGraphicsItem * itemIcon , int interactionId ); /*! \brief Sets the origin angle of the pies. */ void setOriginAngle( int degreeOriginAngle ); /*! * \brief Sets the pen/brush used to draw an highlighted interaction's pie. */ void setHighlightStyle( const QPen& pen , const QBrush& brush ); void paint(QPainter* painter , const QStyleOptionGraphicsItem* style , QWidget* widget); /*! \brief Changes the QPaletteItem radius with the specified newRadius. * * \param newRadius New radius of the palette. If zero, the radius * will be maximized to fit in the item's parent's boundingRect. */ void setRadius( float newRadius ); /*! * \brief See showOnItem. * * CENTER_AND_RESIZE_POLICY : moves the palette at the center of the target item, * maximizing its radius to fit inside it. * CENTER_POLICY : moves the palette at the center of the target item, * without changing its radius. (default) */ typedef enum { CENTER_AND_RESIZE_POLICY , CENTER_POLICY } PositioningPolicy ; /*! * \brief Changes the QPaletteItem's PositioningPolicy. */ void setPositioningPolicy( const PositioningPolicy& policy ); void setPaletteEnabled(bool isEnabled); bool isPaletteEnabled() const; /*! * \brief Can be used instead of calling setVisible( true ). * * \note When using the specialShow(), you must call specialHide() instead of the classic setVisible( false ) * to hide the palette. */ /* void specialShow(); void specialHide(); protected Q_SLOTS: void showAnimation(); */ protected : void init(float radius); virtual void reorderItems(); /*! * \brief The implementation of showOnItem defines the behaviour (or policy) of the palette * when it has to be shown for an interaction of an item (the target) with * another (the droppedItem). * * You can override this function to define a specific behaviour. The * standard implementation uses the QPaletteItem's PositioningPolicy. */ virtual void showOnItem( const QGraphicsItem * target , const QGraphicsItem * droppedItem ); /*! * \brief Notify the QPaletteItem that something is being dragged over it. * The palette highlights the undermouse interaction if there is one. */ virtual void moveOver( const QPointF& pos ); bool canHandle(int droppedItemId , int targetItemId) const; /*! * \brief Returns true if there currently is an highlighted interaction. */ bool hasActiveInteraction() const; /*! * \brief Returns the id of the currently highlighted interaction (as specified in addInteraction). * * \note If !hasActiveInteraction(), returns -1. */ int activeInteraction() const; void setCenter( const QPointF& center ); typedef struct Interaction { int mId; QGraphicsItem * mItem; QPainterPath * mPath; } Interaction; QList mHandledDroppedItemIds; QList mHandledTargetItemIds; QList mInteractions; int mOriginAngle; int mHighlightedInteractionIndex; bool mNeedReorder; bool mIsPaletteEnabled; float mRadius; // QTimer * mShowAnimationTimer; // int mShowAnimationCounter; PositioningPolicy mPositioningPolicy; QPen mHighlightPen; QBrush mHighlightBrush; }; /*! \brief QPaletteItemDropper is part of the QPaletteItem system. (see QPaletteManager) * * Once you add a (usually as a child) QPaletteItemDropper to a QGraphicsItem, you make it possible to * use the QPaletteItem system with this QGraphicsItem. * The QPaletteItemDropper keeps all the identification informations about an item used in the QPaletteItem system: * - paletteId: id of the type of the related QGraphicsItem * - acceptedDroppersId: id of the type of item that can be dropped on the QPaletteItemDropper's related item. * Per example, "I am a QPaletteItemDropper of id 2, and I accept that someone drops QPaletteItemDropper of * id 2 (like me), 3 & 5". * Note: beware of having the QPaletteItems to handle all those possible combinations. * * Moreover : * - the QPaleteItemDropper's related item (usually also its parent) should call the * slot QPaletteItemDropper::updateGeometry when its own geometry changes, to maintain * a valid detection rectangle for the QPaletteItemDropper. * - the QPaleteItemDropper's related item (usually also its parent) should call the * slot QPaletteItemDropper::dragStarted when a drag (or move) is being started. */ class QPaletteItemDropper : public QObject , public QGraphicsRectItem { Q_OBJECT public : /*! \brief Creates a QPaletteItemDropper with the specified paletteId, rect, and parent. * * \param paletteId Allows QPaletteItems to know if they should accept or not * a drop from this QPaletteItemDropper. * \param rect Rect of the QPaletteItemDropper. Usually, its parentItem boundingRect. * \param parent The parentItem. */ QPaletteItemDropper(int paletteId , const QList& acceptedDroppersId, QGraphicsItem* relatedItem, QGraphicsItem * parent); ~QPaletteItemDropper(); /*! * \brief Returns the QPaletteItemDropper's own paletteId. */ int paletteId() const; /*! * \brief Returns true if this QPaletteItemDropper accepts */ bool isAccepted(int paletteId) const; QGraphicsItem* item() { return mItem; } public Q_SLOTS: /*! * \brief Updates the paletteItemDropper rect with the specified QRectF ( it's a QGraphicsRectItem::setRect slot ). */ void updateGeometry(const QRectF& newGeometry); void dragStarted(int & outId , QGraphicsItem*& outItem); protected : QGraphicsItem* mItem; int mPaletteId; QList mAcceptedPaletteIds; }; /*! * \brief QPaletteManager class manages the QPaletteItem system. * * The QPaletteItem system is made of : * - 1 instance of QPaletteManager, QPaletteManager::mInstance, a singleton. * - 1 QPaletteItemDropper for each QGraphicsItem you want to use in the QPaletteItem system * - several QPaletteItem ; each QPaletteItem regroups a category of interactions between 2 QGraphicsItem * * See QPaletteItemDropper & QPaletteItem for more informations about how to use them. * * How to use the QPaletteManager : * 1. QPaletteManager::move : The QPaletteManager must be noticed when you are moving a "palette enabled" QGraphicsItem, * so that it can detect the collisions between the QGraphicsItem's QPaletteItemDropper, and other QPaletteItemDropper. * If an interaction is possible (see QPaletteItemDropper), the corresponding QPaletteItem will appear, allowing to choose * between different interactions. * 2. QPaletteManager::drop : The QPaletteManager must also be noticed when you drop a "palette enabled" QGraphicsItem, or when you leave the * drop zone ( on a QGraphicsView::dragLeaveEvent, per example ). * 3. QPaletteManager::interactionActivated : Output of the system, emitted when an interaction is activated by dropping an item on a valid * part of a QPaletteItem. * * Other QPaletteManager settings: * - setActivationDelay : sets the time the mouse must be kept above an item without moving to show a QPaletteItem. */ class QPaletteManager : public QObject { Q_OBJECT friend class QPaletteItem; friend class QPaletteItemDropper; public: static QPaletteManager * instance(); //detectionRect & pos are in scene coordinates. void move(const QPointF& mouseScenePos , const QGraphicsScene * scene , int draggedItemPaletteId , QGraphicsItem * draggedItem ); bool drop(const QGraphicsScene * scene , int draggedItemPaletteId , QGraphicsItem * draggedItem ); /* void setDragIn(); void setDragOut(); */ /*! * \brief Changes the palette activation delay (time spent above an item to activate the palette). * * Default is 1000ms. */ void setActivationDelay(int msTime); Q_SIGNALS: /*! \brief Emitted when an item is dropped on an interaction of a QPaletteItem: * - droppedItem is the item that was currently dragged, and has been dropped on the QPaletteItem. * - targetItem is the item on which the droppedItem is dropped. * - droppedItemPaletteId is the paletteId of the QPaletteItemDropper of the droppedItem * - targetItemPaletteId is the paletteId of the QPaletteItemDropper of the targetItem * - interactionId is the id of the interaction on which the item has been dropped. */ void interactionActivated(QGraphicsItem* droppedItem, QGraphicsItem* targetItem, int droppedItemPaletteId, int targetItemPaletteId, int interactionId); protected Q_SLOTS: void showPalette(); protected: QPaletteManager(); static QPaletteManager * mInstance; void registerPalette(QPaletteItem* palette); void unregisterPalette(QPaletteItem* palette); void registerDropper(QPaletteItemDropper* dropper); void unregisterDropper(QPaletteItemDropper* dropper); // void setDraggedItem( QGraphicsItem* item , int paletteId ); QPaletteItemDropper* mDropDestination; QList mPalettes; QList mDroppers; QGraphicsItem* mDraggedItem; int mDraggedItemPaletteId; //< Stores the draggedItem palette id while the timer goes. (between start and timeout) QTimer * mShowPaletteTimer; //< Stores the draggedItem while the timer goes. (between start and timeout) QPaletteItem* mShownPalette; QPointF mLastMousePos; int mActivationDelay; // bool mIsDragging; }; #endif //PALETTE_ITEM_H FaustWorks-0.4/QResolutionDialog.cpp0000755000175000017500000000362212130743520016242 0ustar miramira/* * QResolutionDialog.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "QResolutionDialog.h" #include "ui_ResolutionDialog.h" #include //------------------------------------------------------------------------- QResolutionDialog::QResolutionDialog(const QRectF& baseRect , int min , int max , int def , float convertor ) : QDialog() { mUI = new Ui::ResolutionDialog(); mUI->setupUi(this); QObject::connect( mUI->buttonBox, SIGNAL(accepted()), this, SLOT(accepted())); QObject::connect( mUI->scaleSlider , SIGNAL(valueChanged(int)) , this , SLOT(updateResolution(int)) ); mBaseRect = QRectF(baseRect); mConvertor = convertor; mUI->scaleSlider->setRange( min , max ); mUI->scaleSlider->setValue( def ); } //------------------------------------------------------------------------- void QResolutionDialog::accepted() { done( mUI->scaleSlider->value() ); } //------------------------------------------------------------------------- void QResolutionDialog::updateResolution(int v) { int width = v * mBaseRect.width(); int height = v * mBaseRect.height(); QString text; QTextStream stream(&text); stream << int(width*mConvertor) << "x" << int(height*mConvertor); mUI->resolutionLabel->setText( text ); } FaustWorks-0.4/QResolutionDialog.h0000755000175000017500000000245112130743520015706 0ustar miramira/* * QResolutionDialog.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef RESOLUTION_DIALOG_H #define RESOLUTION_DIALOG_H #include namespace Ui { class ResolutionDialog; } //------------------------------------------------------------------------------------------------------------------------ class QResolutionDialog : public QDialog { Q_OBJECT public: QResolutionDialog(const QRectF& baseRect , int min , int max , int def , float convertor ); private Q_SLOTS: void accepted(); void updateResolution(int v); private: QRectF mBaseRect; float mConvertor; Ui::ResolutionDialog * mUI; }; #endif FaustWorks-0.4/QSwitcher.h0000755000175000017500000001112712130743520014213 0ustar miramira/* * QSwitcher.h * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef SWITCHER_H #define SWITCHER_H #include //#include //#include //#include #include #include #include /*! * \brief A class to determine, among a set of T objects, which one is "active", using flags and switches. * * The QSwitcher has 2 types of variable : * - flags : * - You can set a flag "on" or "off" with QSwitcher::setFlag(int flagId, bool isOn). * - One or various flags may be active at one time, or even none. * - When you create a flag, you associate it with a T object. You also * give it a priority : QSwitcher::addFlag(int flagId , int priority , const T& object). * - switchs: there is always one (and only one) active switch (QSwitcher::setActiveSwitch(int switchId) ). * * The "active" T object is the one associated with the highest priority "on" flag. * * The switch are used to associate more than one T object with a flag : you can add * others T object to a flag, associating each new T object with * a switch ( QSwitcher::setSwitchedFlag(int flagId, int switchId , const T& object) ) ; * the "active" T object will be the one associated with the active switch. * * To sum-up : * - first, the QSwitcher determine the highest priority "on" flag * - then, the QSwitcher checks, for this flag, if there is a specific T object associated with the active switch. * - if there is one, use it. If not, use the standard flag's T object. */ template class QSwitcher { typedef QMap QMapIntBrush; typedef QMap QMapIntPen; public: QSwitcher() { mSwitch = 0; } int switchValue() const { return mSwitch; } bool isFlagOn(int flagId) { return mOnFlags.contains( flagId ); } void setFlag(int flagId, bool isOn) { //Checks if we know the specified flagId if ( !mActiveObjects.contains(flagId) ) { qWarning( "QSelectionItem::setFlag : unknown flagId : %d" , flagId ); return; } //Adds or remove flagId from the "activated ids" list. if ( isOn ) { if ( !mOnFlags.contains(flagId) ) mOnFlags << flagId; } else mOnFlags.removeAll( flagId ); updateActiveObject(); } void setActiveSwitch(int switchId) { if ( switchId != mSwitch ) { mSwitch = switchId; updateActiveObject(); } } /*! * \brief Creates a new flag. * \param flagId : id, will be used to set the flag on/off. Must be >= 0. * \param priority: the flag's priority. Must be >= 0 * \param object: the T object associated with this flag. */ void addFlag(int flagId , int priority , const T& object) { mActiveObjects[flagId][0] = object; mPriorities[flagId] = priority; } void setSwitchedFlag( int flagId , int switchId , const T& object ) { if ( switchId < 0 ) qCritical("QSelectionItem::setSwitchedFlag : invalid switchId : %d" , switchId); if ( !mActiveObjects.contains(flagId) ) qCritical("QSelectionItem::setSwitchedFlag : unknown flagId : %d" , flagId); mActiveObjects[flagId][switchId] = object; } const T& activeObject() const { return mActiveObject; } protected: void updateActiveObject() { //Find the highest priority flag. int maxPriority = -1; int id = -1; for ( int i = 0 ; i < mOnFlags.size() ; i++ ) { int priority = mPriorities[mOnFlags[i]]; if ( priority > maxPriority ) { id = mOnFlags[i]; maxPriority = priority; } } if ( id >= 0 ) { //Use pen and brush for this couple (flag,switch) //if pen/brush have been defined for this switch. //Else, use default pen/brush for this flag (switch=0) if ( mActiveObjects[id].contains(mSwitch) ) mActiveObject = mActiveObjects[id][mSwitch]; else mActiveObject = mActiveObjects[id][0]; } } T mActiveObject; QMap mActiveObjects; QMap mPriorities; QList mOnFlags; int mSwitch; }; #endif //SWITCHER_H FaustWorks-0.4/README0000644000175000017500000000177712130743520013020 0ustar miramiraFAUSTWORKS (© GRAME 2013) ========================= FaustWorks is an IDE (Integrated Development Environment) for the Faust dsp programming language. You must have Faust installed to be able to use FaustWorks. Platforms supported are Linux and OSX. 1) Compile and Install Faust ---------------------------- - download Faust form here : http://sourceforge.net/projects/faudiostream/files/latest/download?source=files - uncompress the sources - cd into the faust directory - make - sudo make install 2) Install the QT4.8 SDK ------------------------ On Mac OSX you can download the SDK here : http://releases.qt-project.org/qt4/source/qt-mac-opensource-4.8.4.dmg On Linux you can use your package system. 2) Compile and install FaustWorks --------------------------------- - unzip the FaustWorks-0.4.zip source package - cd FaustWorks-0.4 - make - sudo make install FaustWorks is released under the GPL licence (http://www.gnu.org/licenses/gpl.html). This version is still experimental and undocumented. FaustWorks-0.4/build4osx0000755000175000017500000000152612130743520013773 0ustar miramira#!/bin/bash ##################################################################### # # # Build FaustWorks for MacOSX # # with an embedded version of Faust # # (c) Grame, 2010,2011,2012,2013 # # # ##################################################################### VERSION="0.4" DISTRIB="FaustWorks-$VERSION" DST="FaustWorks.app/Contents/" # then create the dmg package with the QT libraries macdeployqt FaustWorks.app/ # creates the dmg with FaustWorks, documentation and examples rm -rf $DISTRIB rm -rf $DISTRIB.dmg mkdir $DISTRIB cp -r FaustWorks.app $DISTRIB hdiutil create $DISTRIB.dmg -srcfolder $DISTRIB FaustWorks-0.4/faustworks.desktop0000755000175000017500000000034412130743520015733 0ustar miramira[Desktop Entry] Type=Application Name=FaustWorks GenericName=IDE for Faust Comment=IDE for Faust dsp programming language Encoding=UTF-8 Version=1.0 Terminal=false Exec=FaustWorks Icon=faustworks Categories=Development;Audio; FaustWorks-0.4/main.cpp0000755000175000017500000000600412130743520013557 0ustar miramira/* * main.cpp * * Created by Christophe Daudin on 12/05/09. * Copyright 2009 Grame. All rights reserved. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 2.1 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPL included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 2.1 requirements * will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. * * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include "FaustMainWindow.h" QMainWindow* gMainWin; int main(int argc, char *argv[]) { QApplication app(argc, argv); Q_INIT_RESOURCE( application ); Q_INIT_RESOURCE( i18n ); // prepare the PATH environment variable to be sure all scripts will be found qputenv("PATH", qgetenv("PATH")+":/usr/local/bin:/opt/local/bin"); qDebug() << "PATH is " << qgetenv("PATH"); app.setWindowIcon(QIcon(":/FaustWorks.png")); QPixmap pixmap(":/FaustWorks.png"); QSplashScreen splash(pixmap); splash.show(); app.processEvents(); QTranslator qtTranslator; qtTranslator.load("qt_" + QLocale::system().name()); app.installTranslator(&qtTranslator); QTranslator myappTranslator; myappTranslator.load(":/translations/i18n_" + QLocale::system().name()); app.installTranslator(&myappTranslator); QCoreApplication::setOrganizationName( "GRAME" ); QCoreApplication::setApplicationName( "FaustWorks" ); GraphicsSceneMainWindowSettings s; s.mLanguageNameShort = "Faust"; s.mLanguageNameLong = s.mLanguageNameShort; s.mDefaultLanguageCode = "process = +;"; s.mLanguageFileExtension = "dsp"; s.mSceneFileExtension = "fsc"; s.mLanguageCommandsFile = ":/FaustCommands.xml"; s.mMinScale = 0; s.mMaxScale = 0; s.mMinItemSize = QSize( 40 , 40 ); s.mMaxItemSize = QSize( 400 , 300 ); s.mDesactiveUIElements << SIZE_TOOL_BAR << RESCALE_ACT << H_ALIGN_ACT << V_ALIGN_ACT; s.mHasHistory = false; s.mHasStorage = false; GraphicsSceneMainWindow::initApplicationSettings(s); //FaustMainWindow mainWin; gMainWin = new FaustMainWindow(); QApplication::instance()->installEventFilter( gMainWin ); if ( argc >= 2 ) { QString fileName( argv[1] ); QFileOpenEvent fileOpenEvent( fileName ); QApplication::sendEvent( gMainWin , &fileOpenEvent ); } gMainWin->show(); splash.finish(gMainWin); //qDebug() << "QCoreApplication::applicationDirPath() : " << QCoreApplication::applicationDirPath(); //qDebug() << "QCoreApplication::applicationFilePath() : " << QCoreApplication::applicationFilePath(); return app.exec(); } FaustWorks-0.4/Resources/translations/0000700000175000017500000000000012142453143016607 5ustar miramiraFaustWorks-0.4/Forms/0000700000175000017500000000000012142453143013202 5ustar miramiraFaustWorks-0.4/Resources/0000700000175000017500000000000012142453143014066 5ustar miramiraFaustWorks-0.4/0000755000175000017500000000000012142453377012137 5ustar miramira