From 5432f4eb584019034f3928cbbd90506deb3c6fee Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 2 Dec 2011 07:55:24 -0600 Subject: [PATCH 001/282] Changed: Added the basic UI structure of the new Tile Editor plugin. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../src/plugins/CMakeLists.txt | 1 + .../src/plugins/tile_editor/CMakeLists.txt | 47 ++ .../plugins/tile_editor/images/add_tile.png | Bin 0 -> 7305 bytes .../tile_editor/images/delete_image.png | Bin 0 -> 4144 bytes .../tile_editor/images/delete_tile.png | Bin 0 -> 7561 bytes .../src/plugins/tile_editor/images/down.png | Bin 0 -> 4286 bytes .../tile_editor/images/empty_image.png | Bin 0 -> 2235 bytes .../tile_editor/images/ic_nel_add_item.png | Bin 0 -> 3270 bytes .../tile_editor/images/ic_nel_delete_item.png | Bin 0 -> 1496 bytes .../plugins/tile_editor/images/ic_nel_new.png | Bin 0 -> 4035 bytes .../tile_editor/images/ic_nel_open.png | Bin 0 -> 4310 bytes .../tile_editor/images/ic_nel_save.png | Bin 0 -> 6462 bytes .../tile_editor/images/ic_nel_save_as.png | Bin 0 -> 7748 bytes .../src/plugins/tile_editor/images/left.png | Bin 0 -> 4377 bytes .../src/plugins/tile_editor/images/nel.png | Bin 0 -> 15587 bytes .../tile_editor/images/replace_image.png | Bin 0 -> 4157 bytes .../src/plugins/tile_editor/images/reset.png | Bin 0 -> 2157 bytes .../src/plugins/tile_editor/images/right.png | Bin 0 -> 4395 bytes .../plugins/tile_editor/images/rotation0.png | Bin 0 -> 3643 bytes .../tile_editor/images/rotation180.png | Bin 0 -> 4492 bytes .../tile_editor/images/rotation270.png | Bin 0 -> 4516 bytes .../plugins/tile_editor/images/rotation90.png | Bin 0 -> 4548 bytes .../src/plugins/tile_editor/images/up.png | Bin 0 -> 4654 bytes .../tile_editor/ovqt_plugin_tile_editor.xml | 10 + .../src/plugins/tile_editor/tile_editor.qrc | 29 + .../tile_editor/tile_editor_main_window.cpp | 171 +++++ .../tile_editor/tile_editor_main_window.h | 63 ++ .../tile_editor/tile_editor_main_window.ui | 663 ++++++++++++++++++ .../tile_editor/tile_editor_plugin.cpp | 75 ++ .../plugins/tile_editor/tile_editor_plugin.h | 109 +++ .../src/plugins/tile_editor/tile_item.cpp | 138 ++++ .../src/plugins/tile_editor/tile_item.h | 66 ++ .../src/plugins/tile_editor/tile_model.cpp | 123 ++++ .../src/plugins/tile_editor/tile_model.h | 54 ++ 34 files changed, 1549 insertions(+) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_image.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_tile.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save_as.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/left.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation0.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation270.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation90.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/up.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt index 426d3aa61..51d44137a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt @@ -7,6 +7,7 @@ ADD_SUBDIRECTORY(disp_sheet_id) ADD_SUBDIRECTORY(object_viewer) ADD_SUBDIRECTORY(georges_editor) ADD_SUBDIRECTORY(translation_manager) +ADD_SUBDIRECTORY(tile_editor) # Note: Temporarily disabled until development continues. #ADD_SUBDIRECTORY(zone_painter) # Ryzom Specific Plugins diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt new file mode 100644 index 000000000..f3458c909 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt @@ -0,0 +1,47 @@ +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_HDR + tile_model.h + tile_editor_main_window.h + tile_editor_plugin.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_UIS + tile_editor_main_window.ui) + +SET(OVQT_PLUG_TILE_EDITOR_RCS tile_editor.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_WRAP_CPP(OVQT_TILE_EDITOR_PLUGIN_MOC_SRC ${OVQT_TILE_EDITOR_PLUGIN_HDR}) +QT4_ADD_RESOURCES( OVQT_PLUG_TILE_EDITOR_RC_SRCS ${OVQT_PLUG_TILE_EDITOR_RCS}) +QT4_WRAP_UI(OVQT_TILE_EDITOR_PLUGIN_UI_HDRS ${OVQT_TILE_EDITOR_PLUGIN_UIS}) + +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS}) +SOURCE_GROUP("Tile Editor Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ovqt_plugin_core nelmisc ${QT_LIBRARIES}) + +IF(WITH_STLPORT) + TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) +ENDIF(WITH_STLPORT) + +NL_DEFAULT_PROPS(ovqt_plugin_tile_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Tile Editor") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_tile_editor) +NL_ADD_LIB_SUFFIX(ovqt_plugin_tile_editor) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +INSTALL(TARGETS ovqt_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..a9de8f51de04f3d0f475bd0fbc9f277069244385 GIT binary patch literal 7305 zcmV;49CqW0P)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 f|J(gM7T00000NkvXXu0mjfQx9E& literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png new file mode 100644 index 0000000000000000000000000000000000000000..b0033cf64a712b8ce4be8d7af939c9a3d6be088e GIT binary patch literal 4286 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 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png new file mode 100644 index 0000000000000000000000000000000000000000..9a2e358ab13467aaddc0b8784a56b1cc2dedbd7d GIT binary patch literal 2235 zcmV;s2t@aZP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy32;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9a%BKeVQFr3 zE>1;MAa*k@Gd8K`;w1n82mnb$K~z{r?U!kAQ`Z&8^`(;!`O=cokd{fO%e2#N(rJ?> zooOc@+B5;$4kX}|0%mO?g;1DK2pA(Ucm*#tHpaGWu&{;vyvUnuc@f6DY+1IvV%b`} z+mb9Vk}){0`S+Zg$WUe&%5*Z*4|y}cd6M3}_x#T}|NGvPO!md`|5AaWp`q0yBO`lV zE>|KUJ&xP$mY$Wz)=<&>sNvz^w<*?hD|y@P_AgCNPHy!1e6Ho?WqjVp($W%UXJ<_$ zW6iggGn)Z$EjA%b%9 zaZHtszbmtFKye*=l2WlPE)iQU#pB(GC>&B8!LYkah*(@)Tyi>{f0L1tIsU=3Fos~Y z4sZUW4!=FsfDLC2*c58S*64QZO6bCY)LtCEZlM5He4K5^={yGo9mE;U5Q6D^D#wl! zY8#Fy`*AR>4|}h4V@F&EHb7u8M|tVM@g0>aPf}x$FpxEyV_T6Fx}n zL`04iX%w)?;6zD_8x<7LXqm(K!~(pY`|x=dG3mUAk@3640{VyMVYYhFU=!1#I zmKxpAG)_WYGfv6$W7CBe$g>^_;9Vt~n-d*?)oDdwoEGm;1^#%xMU;MbViyjj_ldI0 zsni#BW4O`aM7enyoi?us%E9jp&ZDYx8kvnQq}-l_f>72>;0BReIf_WC;P#kytf#g< zDuB1CjJAXjFyQRRj@V+XJ7d5`>ixD@GxjBQ<8X#W^!9wwh$wSm>lCWHW?<}}BN3D> ziRiZbVCb7gvB`sE3LaTDiqp9ce3UsLytDIir|`n>&ox7yc?sUTpSFNZ_)vh=)r+%v zsgO$vxKf>rOk)DFS}!BLDHRFT8pKo@kyLF%ev1n=olf*xr!YJ+BPzfm+6KJPnO#V$ zYeuYIji~Zagla=^B0C*NGSt|Us6fEQc!b8Ar?zW)MVnc6FA1r-?=(UWYvBQdDLn%~s(Nz9m zT)%x1*KQsEj1!2~>_nIpfb`NJc;}}@Od();`qM9Vj|mC--3V5#M_R*&kj%kQwH-&M z=_4UX-&BC!-d@nn1LNc4p#EWWbX0t&yXjNmag4=cL0elJc=ypd4+U7=El4*UM118g z0{zZLBsc6u zn&AMh=>LNA+3zB*VjGg{_aVP3jSYjbu`$rC8xDtqCkyDFE-J$Cb;e&A&XyS%7+4ug z4p(;vT3C@f2&hf*-cv1e{ zFOC=IGIw`(qpPb6?d|PoX=y=!f4>mVE#vD3gF%vUIr!)puE74}Z)11-H?SvREw)Ci zp>6mw4yF7E*K(s*GUh;!mX_!9f-Hj14Gj(G>FMF@P*-1z+WK1}TlPi^7(axlsa3UxFx z^fu>jH5W3^<$jMeFG<@U*LrFDo&=qBmAJ%YGE`QQBzaH zf+ZPkr4jKgm}tS_tFK^l@RzY!{uKnAU4?*<7Z4csO~j_05sqeaJqnBR!`FFn&P<)F z#Idwr(aXy^Tq=7H$1~qRiaJbO(`YopCtR(fq9TQi`Vqdcu&~6hOTD9Yh%E|4c+Pt( zgsI*~()B3OH>R_*^NFyra&mImT+kHdAmN4_QP&P4Gxw?po|~I1uCZB5OG|x9rE;UJ zuCDI;WUfZh2RiP5LeG18Vem6M??#zUD<<)NX4q&?g8B+clAzP+xW|HuiV7jDyu4hv zpCJML3WegQ;>DDDx0)7I(T;G?opFiYRQPRW1>V~=bJZgsz|`|E3fC&kLPI{y+#8z(O%uc&}RYtzJnSy^Y`17p5zX1;`E%3QL*~I_=002ov JPDHLkV1nBRLyG_a literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png new file mode 100644 index 0000000000000000000000000000000000000000..bde338f7851d2675b29272c7dcf9471196a8f6cc GIT binary patch literal 3270 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 Eg5p97)c^nh literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a1787d593591f855be9a7eb8da271cc8d8f214 GIT binary patch literal 1496 zcmaKs{XY{30LC|C-c2!W(h#B2QhA@kOt{brn;~tK$;-mn#DM?-zdb>=i zu*@RTd8@_pvUxpuxyoG1>Bsxw?uX}jKHujL_-0@|T~w8{l>h*Ms+%k3&``sHb<81=-~(e+|N^9C&_KHVw5X^3IM3J{S1(sAHJ}8!egC%W4+FY#L`JIX8~B! zIZ7C+< z6bcMhk7Jz$z zt<~^Npzeyeat^;b(tkMW#bRkwb5S`|-P(cZ{!1geIKC7Tzpi^Q9XhN7r*| zh)Tmw?h}4)r(e%EPx*~jbiDn>W9k_F^gyx#1J1b!&uZuD!J$Duh_I|$-B|3)pjcABT`DZr@@$gnJ?g*7niqC zPg~-q=_uM61|+bWZC}wlE4;C-L;LVrU6J(R@D0Z4=p`kt`4==LnW(d8wXiBZND)3NugXyk}j`B>QSp`rx>7I47#1U z_C?Zqn_!w_iq*Q=7#33$KOO+R;CW!bcdn#k;~tqqg>*o8s|#;{%M1@^2B=`1X*QOW z`~~EL<8YMd;Wk~hP%ln9+T{3weTCGPC>#3IdbbgtfSL(^;<-$(&+()%CWY(ZY}rUs zYZ^=Sws7E+dDpj6e_>>!qz;jFg;SMzWx6GvaM=_CJv#h+^qF(IggsR{8BYMQlBT|c zLR(J;=NJUkn>YRLcdDtY?zXt@zIEUuTe=1hEndEU6|7%)i#=`5cs5S}P9Mh=PcJfo z{ZbSwueq|yZyG~GMGk&1;XI&33fgfyu~6eIQgk!Fkv4<^W8F=|9U5oXINb+#fCen_ z{sB?u3Xfi@SxqMAC%ZI%1BJIf0uMiCx!yXz62rndMv z$=6toP8$LinV$s7C|ZjMS5+@W1rn4NxN=o7bmp|tGx-1vXy7V6(LK7Owl1b<1|o_O z>bY9rcsZ;+(mT(U8Vqy|@K*SC7Xeg!@WG?ntw{ZC`G3Vh1-90Bf1vJ=9f)jI$P4Q6YBQ@Z8;^^H#>9pe+1$q6DXU$-5VbBeJ(3kUiuh943T}3C$!G=4Zw&rX zIZx;etQ%$b10W;H`0fD|-g&n~Eq? zJZ zC}pc4u@0qD`7mQX=zMD+8o3Hi#&31p7{mxJ*6-KkigeYIgt}@Xn1a05YyE6U8VHU~ z8PL=CTn*0W$(#-|89Sz`9P!(hY?pOfm^ZQVXfjUeBhD+B#yUg0vkok?_%`$Xq0`=> g{}tB1bjDO$2a)_&SEAML{IoE@&Dj&vfF`E?18{b*hyVZp literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png new file mode 100644 index 0000000000000000000000000000000000000000..d45dcb4674ac76de749509f45685a53954062ccf GIT binary patch literal 4035 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

9hNf?Vhz@D{30l;nt_JM}mQUV~w zU}fFVhIWm|NOEs-N_P;?dO6vhZ=x6b1{FEy`NkD{ET93v*SoKsR0f6P6R8(-ZiNnchebmTE2n{zSpSfg2HYuKG#tYt4ZYTD&Z}v>Y0IYrC-DLxn)fK&= zrBxtFv;I?h(WyuX_0*ExYk&VfA~DMt^E5?fh8D@?nOi z39APLG);rhG>F+T%}S0!6A;4c5OCIAaAo0HADXp-k&!UcM#SFO%s;8m_cd>rQutM_aGu zSKJ-`AQ3zHVe*-DGCQcpGKI6SO^D0Q0`7L|qtw={ZthG@rJ*F{`$RcP$lp$Xq92r5 z)tj15Lz&81C6Xe`iB*{s0DzwlriYYC-N|Tr#>|)waFV%gUs)3XfHQ|OW27jo&txKo zZbF&_X{y`90<-Ox&x|o5?$+a(k<@e=*`yI+=D`Io?k@hPev!Z;fkguUYx{QqFWXW= T3%>DB00000NkvXXu0mjfsaq=9 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png new file mode 100644 index 0000000000000000000000000000000000000000..d2139bb2557984f999a563059ea00f7e76436293 GIT binary patch literal 15587 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 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png new file mode 100644 index 0000000000000000000000000000000000000000..94d9b76c80384a83bc196cd0e03759bfb588cbae GIT binary patch literal 4157 zcmV-D5W???P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$BHmT?0B>(^qmq|oH zRA@u(nFmnScecm(&CYwf`?4fzj3#OljWKGfW>bvD7JH|uAR4=Z0@AB+>Ai!1h!p9) z7XiT_f&>wzt0+y>s0ne6MzfpwzH@$mF5wSmcjnE$WM^LP%$Y0q{_p>PKBxW8IsWc< z|6g8)3DYK$tWxC6*LTQWXkwP~u9kk>>u>z({CZJS{=+u?lWmIZh1$cFF-x8`$~k}O zTGzrA=lxD;Ah1FUu0<>0khc&HxeK7kS@3uBztAXf7PJSk+d`nw+)z0tj zGUh8-5rX=?QT*GQzNP9No+sA~D7^qSSs%eX?L8PJO@~4J>o^!Y75XvLKmgzBMNSpJ z{l#BB;=F0*sU{w&nHWc?H8f+eueollB?42$$xFiw6GhKX-L z|HSJ!5c3)c9{Y~IialYk;84t4I1o8)^DhptD`b+2TmI^Hr~Jim%wGie;#E+P(zc|u zRmS^d@poaAJQEcEFo+|?qgnAO1B$)aVU2|I%) zVrP&fI|4}pCXh^oTblaM>ha`n-($DmRH#}#i}mJzh9Z8|zf$KB_j>T)0j^)azGDzV zRu z@x_%`R9ue2skUP%Z3#zla|nu>f>78Pgn~SjGy`awVa--s~*JwwCJzs5+QH&9x4jye?pi-$iT>YQ(OPdJ3PHuu}gIJ{sQ1)V_lp@)Th|wJVq$G$x)JxEQ-<4 zB+;-N1@*(v36E&FL_x>@B0acCD6rMjQiRU(1OJ6>9$K(WxdxlG>#$Al#NmuCA^dNf zv`$#1T!%%H1al~sK#sRz|IrrgI?{w~ftR4=(*O-6g#9@JsK#ejRnYJ-Mp@%=8N|(- zHyZ>%PfvG6MSUVHk1iHsaO8cc+IBA3{UON6>Is18tvj>?Gy)(Svov zs|a#BR*>>)*5hHGPzgnLHym?&;GEYBm;9f^i9U0n@9Z+W1R#SL$6bLzwB!u|5pYTJ zgxh(nb*#loyBaLDIZGf}@XpyJ1GsbN4g>(z>x!Y@T)35k`DT?^Y*~d(?sYgA+6aTt zFQFft4eQuuD3Y$iCG8qKvpTWIYYS8@Ct?@9A20937ftkp7}?k=Lve1#a2 zXp$r4x8Paa2Umg$IN67UGq;gldj|z|ci~9)+dlxYmAuO#s_IgQH4f*nflhKZ7OKXQAp`i$lS2&{9mrZtvMRRo{c_y${iS;~{!)K0<9n z9d7h}i+gvz$2WH$$c-a30-_d&?UDHL^cK1C*kB~>W+Wj3`Iv)to%k*#l zTL7QAh3K*y@Fl}opJ<2K@m3ffZN^G_$qSyDa)7&c?@9o4^2q?s^`>Bv#ToIVHI|wp zIoFvzkBzReB6QeN2GN(XC&(82LiWNaLJ#Iq2jCE|51&*+1ZNr{EZZ3215(>ig6{~3 z!5F5pr5^Kr<<$`C1rpyCB3vjk89*YTJmBk*c zG5Qmh>Ha6h{tgkJyF;6)VQUlBL{l*q8!S{r{pSNr-R3!w=v0)6HUq{MF{hznQ$igF62th##y zP>tZz0W{?uq&Y+j0p%OvQFIXYS&pzs4uEA+2zkQ^Isq2Y_BDfRlA0`pZr{Ewd0;p| zaeELfqUKRN)8S?NoUpE6(Pm^eJ0hdW0qKqQNNco1a)TAT^3}*YGw3v)gk982apSl9 z2sMDz1ac$DVwbQ?RIE0#es$YzWS%cZWR(Mgzt|#1R94*Ylsb5z@+w(J?;GGxpZT0r zr|$SQa2wB^u}h-r(*dY4l6jz@#TOPaa|cgjj^mwyFC(OUJ7Q}OA*R+4k=1&zPM#;` z0`6M5i{+M^Tkri5QX9UX9?B24h@XSxI#(R8HbQKT5ze+HA+E+;C@B;#-5?bAELkhw zy-U|4y2=36t?39W)syZ;_jQinAOpB{>z3q!;Q%>J9`GfLb4+tjBnA~~@b-mHq2!${ zMEBTKx+zU%tS~9ba|F-FJh2%jyaA)c88A+IlLn(VVV(L3SzAYhNn(vH+)_6qsBn)^ zl&3$}qU9vZ#Jd|U3|Nj;=))vpA)N(_#dFv|PH}PoY9%B9>gr@3$h^q$eGqyP)2JgI zFXEcpYYr2(wis?mX&x>0PfQh~CQomsDQ}C3j^}5GyahO%{R!-{=YpoaL2G;GX+t;U zFEEK*K(qFzVsur|wR}BqIvn#^7QrlL9yFaMQYE7qC2XV3|If2LD;)RZ=K;I;=B4AlMJZro%S-W0E=II-bS1`A)(rlhIghI$9d4 zj!c3gdYue_S|ADF>eZ_ z3D2?cTz)8irU)5z`xj^~nIIJiiU9klwK4!|fh2${SFXqa;%d#{U93hzRiStTjL2#> zX>(zmz%l(cS@M0@<;){jFD8pGgKw!Cb)XBR9T5T2woc>%d&xFqF16EhMVPV2cqMZv z{!JW8qIcRYF_;m9k(j5_LLvEmp*&limjzte#B@lLpaSj%V3;fU2w2WW3^mjOhc(UT4%I*61YI$m@@ z(aji!7Gd(TIizIrHbdHO5X=COfEoZA^b#$`*i-B=4o~yw1ypesQS1H@Od}Uk$h<6c z-~z&{8Xj?N!{xI!wLp>w+S=M=0O6;1i?S)5tUS~c2q{14m4UUKEr=+-Y z2erjxJl0u_!5Z?wMn~y+v@sNh=)ye;%@bCEI2&u2H?x*P%kXDjxNxB}FE7uZWb)4{|JxV8S>QJd{APh)#RC5WwsFag>)}+|00000NkvXX Hu0mjfg>t)Y literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png new file mode 100644 index 0000000000000000000000000000000000000000..6693e842c25aba38b1a87a99a06368db17151386 GIT binary patch literal 2157 zcmV-z2$J`SP)-7A@9RST){$KnOGm*#d;%mkJ@luj4;}-zFiro^yMF%3yh!%TL_TEsei1C zJ6*eNwqz&l+IGhqC%EWGKmIb!zVU0Ce(vY=pToS+i1?dN_@kfx^c+q7>WB2!GvT!l zp9+rb24L6fa-o?p7d<@nn9%$5ILNclfiJiWq3{17`tGo!E{Ge`&C$S_NumA8Nqoi{ z^!(^&E$;5n%x)02p0b^_t6k{waW2|9IVSXdZ35&^UdQO+@ERWY_Aq2pJk0<8#rVWc zCAQlOuTS|<{HW0O_!*EtzRXMuTyq;Z!sj9N!t-Jwos67%Wj(Q17uplREBz?`?65HK zl@U<>bCsPeHU_}~cjzc&k^l>T`rD2W?@xN8!I5F1ZR!zF?!Kdo#~+{?1>!jbj{Ye~ zU%V(v%S(|{mntC|2Kaj)iFS^Kg@LC|ftvmoY9^%%*pCUq1-c+JuR`*rEAfdNwGi)p z!4nM*hf(|xsHqQ%;z1WrRilAB0Is8>uz2ZJQCeNCfM^KdD>y5Yvb-{@Zn=Z`=f)PuHMnDuK#J&1khAX?}^I??$E=q z^xE5^w6<cPAv8$u5 zXz=6_p?$I+w2h=8oYD&Mdb5m)%M0$_K3IA4x+sa6(+DxQoz88u5MDlgWV8zk$%XPu zlya{rnrSuma?_u4BKW&G=$sBmXFu--5u2 z?iPIHg@zU~yfKlwk%Vxh7Yd83y47^c)1vjUQ9{j`U}GaBaGcwO=59CioFAI@w7OCJ zifQ=@*Rjrmbv78NqJV=a?4Fi})9A$z#=yzLLU_6x^2?cGyb^uhOc&z7bR{!$l{(&m zmQ~8aS+A8{NFUok5GN0=U^6UVTS!n@jSOGj5F5@ye?f@OlZS-CDRigRtZ|Mj3oiw9 zwfJg(v|8VG7K-9I2M^AG2gRooRM8@zdo3g0_d1|M47DIc2jo|BWe8GbePRPZOG&3} zeJg-<7B~k74!;YQuP*80AGxwA?#n`^XC;K_7zzr5k9I(gLC{(V({)PsmW0!)S+Keg zEn42mfwS2OOS4M}4CKhjn_J?(t;FTjiV)$TF!04ToQb^YGUhA*v7LbugsmGru>| zx3Op=5E*}8esD4H$0HDJ?`aZ3VMBa%3f(OW*~S6}G7DmsN;mFou*x$so{;xH3%%G4 z(Y7OAAvECMyZGH8Ea}wYbLivD-Ha{7eF41Ch2pzVe4h^r>xJ4H$SQuPAl_j;(A^1V zf-R1l^P4pg4FmiE#kY2Ngx-)Bq;<)*bf`(8q)NQCq_9b+)^)+@a{_S?*h+305ZC3# zYoXtDqUGD<|T67Y}5I8VG8Gn3dmV%>%mwlY534 z7^!mG^0`_(DT^m4g2!IY$lF6`wX>kl1eO*oL*u(6-Cc&T#)4+&Mn<1olfZ>z1R0SxW%j-3O1)dk z_KV(9;{D6kAE>b!!?sExbmi=7MLvU&UU*Yh>2+ z@|x%i9*UW(`{VBS7GW-%Q-5;nULJT1EPTHH0<~&IwXV3#q6*H${Jk6#ANl%SDt>j2 z#xomoY-Onu!Vp{(tuWDG2v?1N)~ z#F)?_jCeBv0)F0@NlA-8{;?L@x0P6ja1!BY3lG`6W~O@wTHfI#kQ5c&^50H^xJwlq zZSrt}-^0OrRxLtML%fgIgIJce_!GCa*uK|7C5WD84zd_r%<^swv{Xjb#eXNYvv@0n z*F^-Mi@@5J#=HfBUQUOQ6&nB2CtB=*?FSfy$3cWHAJJd9nAH;ah{!X06mNxK&tV2o zsWAf>!142UXzYP+Xb@rqPhY?*S}={pzMHO3ymfnun=*kILHvuS=jgNhwj(?EPrd_y j1Aqg71Ax68{}W&U)Vv|XcY0W@00000NkvXXu0mjfEXXC` literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png new file mode 100644 index 0000000000000000000000000000000000000000..eb51b8385549539bcdce8c1844655c4912839837 GIT binary patch literal 4395 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 N002ovPDHLkV1nG11v&r# literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce524883e021b2fdd90ac698f0b2ad0002d06af GIT binary patch literal 4492 zcmV;75p(W|P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$BHmT?0B>(^r=1D|B zRA@u(nRirG_m;=+f3s%In>Uykd%>0%qb8=V_6S!*xu<=lJDXYb#4m*2TE z*&oLr5%?nl|C9)5xGAftyUvQy_IkZ$hwmcj`n(Ap?>9j2vE5?^j5THx-uZuZ!oYutGMTh9@a;hc zcS_la@B&lhR0borIuxhMJrPlK5CJ)Q@XgeQXSycblht68unPOb{sNPb4`39u4BOo2 zVV%{)n7G&*^D8kYRus_|nW_QT@Fb)3{c1f!6 zBDj#eT?oxLfk&E#_@8C$asg|bxCVA)wu!4@6TcD`F<;?e7^cN(FB`^$F3Nx=|@R#02hV(vSd_EDMWoP$=eImej$=`*(|6*yY>nx?;4WF5r zsYIqiCS_%1Np45?wK;_7!y#B7c7Z!!FV_>Vr6UG#3^jyP*iJZy8^JZw817LfFb`gj z1M-z{i#CFPq8U6Bc0qpJ8vaSS3TI7X`p zEeeK1`1Ts&(9Oum`0L3_uu2SETU$HW+uMtQfq~z&`}gnTZ?W!<+i+YpA5P0>AV^Ia zX#~#>oX~p%XLc__>7k{xigU1=l9pFbir+kT|JK%46w^U`FHhj?>};ir7cbU4dGZAR zsG}gt2Ued>h5O2xNZ7sr5nJaWT7CYo114|b^g$}8-fxN|-s%4?`UX2+K&h*%8zj~j zbK%mZOEo|I@WVffU0m1d%LOp|WD0^e&Jh;4K^ZX`^O2(a1`7AT4Qq?p@H?#stLT+D zf92S(vXDZMlaurFO62C|>arBZAH4(Z@QTsHA>XfH?!O!s0V`k`^fj!4SHe1E6>LIR z;qcMbunnim5wRBbQETB4tqLh-9i+JRaExCMr-Th~P9#fGgT2caFnoI=Tvp70*P2;y zroRE}l@YOJ9&#!A7tG&=>Yo3CTY?sJ4C!-8E8%r|v#^Y-e)#_RkOE&>Sy}N|QkR#P zw~asB(s>PPrW3K=;!pV2egZZ-kV&s#i{mTU>hvnqT_!@^bt1HUrobpd8M`8tVH`CF z#?hqTn7P;;I~OK#^Mvh*pND&P}=WFrxoldUClW|UTcXuN%FYg^$K|z61OG}G_clIIQV59Y)Ukbj~ zObHrpuTiqShHV~`pnqg0Okzi2=VMR8eC$nRTY!B@3veLn1GsuP;c|I7GBT5KV8v4G z`(P66RHg|B!ZyzptH3$Iul;FNY+T4``YvCCuf^A7N6t1xk8yIY=I7^|%8H7LR5-)O zAFKBK+Y1rbpola0dTUw%*VnM!b27GjPZq178#o<1!)A*c?N5FkrpMmEf#VBd7WXmS zyO~6W1CD3F@t$p$s_zqeDy`bqhbnI=|W_%1Obq&1zJzol6TUU?v&JGk5=EG$9 zGVFbS684g$Oh1|o`-4m1obwf&a=wIPwhA1wK7)Pcr{bE2(?7zQx*!Dyh+UGEl$5Bn zx3?>tSa1HPF^!K(Mcr*G$>%izzv1vCXnM?s0GE>m&%nOeMRemY;FkUk`~tmy6TYjr z8~sDQNKH+E{$J+8+;A~GPppP_;Rdqx@G4M+NB&y4=dFfo?$>ZRvs_#|w_ec!VwYs4 zrKKtz9UTe|s9F9eNn{eXdkt$`NX1u~W}fNTXg`^%&}3CrbkX za=+gN-`srzZtiaIPBB36`E8J&*Mz)813@L~2rS-;fODJScXktei#7_UJjtp2h7bi# zVwYqWE?juQfsHnQhL$&hGyI6g4TD~XzTaY!)f^hI-lNj^0Su@D*_`+oK80#eT+gZN5Q#9w9GkGQM*5O-xSVz2Chf4(MsbJY=f z*+@9XPKB1~;@r(h1qX;-l3l)hS*5G1OW_1JFI}!Ifdo&yOMvKlKKtFc6K zwFPvX7em|iO(c+m(dEX%5nid1Td@k9H2z33>cT4A)y5y(afcIh2DE&qLEUXK3_@qZ zJo!BYl14*Hw~J-=%K8Rd9H?4R#bWr;2F7KTySIJtR*cD}>ju2My%Cn=j`Zu!0ye4I zoFdLq-z((9(RR;NgL(9qVkhR2wUO?lM=PK&&X+YOC~y+HB)f9u$_ox`b$)d?>Xe}C zEM9?{EdhqjqNuAQl)(8$K4&&V-Ep`h8-~sjO^l5t$KU6XW0Rc{Vl$l3Oz_@5-Ux`b z5y{G$mecBSAdZx23%zqdSSkTU+u(BITiUIu<7lxFqRMxPRfwtBjf<^{171Z%g(SOr z^{PrwPmh9U98reX4V*!xb0Rj{O@V35yCMovbTR)t4QNmw;8B9%M`s>}7jqKHi7Ob( zNmH5*FKTEZi4G*W?IJOM2ByefG7$1$neeqEFB&82+##H)3`J^{9b(G&Ahu#J$>{*f z+fo%ciCvOaRaL3nxpPP11b1Bq+Z9HSH$3KvlIfMbnWA8Vz=G}2be$pq4H$l8aN~U8 z#>dX{h{1CVpW~UzQodFsAprE@9(fINBvqNgJ4YQp zIT}K8SK8AQI4dhFC0TWK^$QMg^WxcNU(8!@PWcuwh1NJ#?F@OLHa)MIN+os}esuEW zd|{_qPF#NXjtpO%2YT+WiKPCs}YNMd`C_;*KX`ebxG&P3j(Rmk*&|Ias z>9L&n9FNb&G*WM&l4>8Ujk24$C~i#0xyI8-tMS9}Drp$H>d-HMZID`f7$<6Nak9=H zr|KP$RxgRC6`a)Z6=taJ&Q{OBgshmXu=WA6tM3c=xDohZg7+nO zw=>;v%IbtedIt`lY=hRQ@J~WkKAr}<@Jc9WO)P?-9gf&ek5G%2kYH6ryI`nS*OfSNF*6fSk}B%O6yqU zxqz_ljTxTQzyWO=tW@Bn;7hVww{E@j%ZFM{Cssi#@Dg;%32lELQE_)kYdIAK}yyGZk+@P?r^$h>|6 z51;+qa34Q@jOONMHQ@kl>SNfW@ke%b0F|$8FbubWQKT((SUc>AlVFcVLeUK)X+)BIVn{ym@F_@yU*Rztk5dqM?j+>JY1EKTBcvn)M@q7A`@LRd@x6|~-~#O-@kXd9?O`~6yUJg7t0g9daBUPt%CM)W+qi9170=>6^%?ta&T zzDKR-e{>uDkK1tXaXSXS?;z{M{U=>`@T8l-x-s~)hwKhTxOc?vV(2+rAD;csV}-!- zo2O5of|yMee(<1YL%KsliVsj<_~yUBKb}8-4%)-N{C6^v5|0&a&z?Q|7eG}+`0>Xd z@$lh8P@sns_ty@3Mx;a@>e4PPoyu$R%Z#d4@!#8i?OyzU3TiQNNo0ThXQto%L)sr7 e{38M)0{;t_n^5#J!;EzR0000Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$BHmT?0B>(^r{z*hZ zRA@uRns-!{=a$Cr{55OV+?mm6>`{!G7-PAn+^pngQtcI^C>BaU1OyeOqrgX(dVoWb z-ce9Nnp6cLDkw-53(`RpK|l#=GRZT0zZmX0NvZ&ayJB^AcA}%BL#+1pcC@v%p|!PDEV?F| zo14+p)C9T*?%cV9($doA?CfmqSF`X1@1`4Qlc9Y-{qz%U@*nfXn{?^YrOM3A%yIt| z2<^}p0|NtpjMcxo%MU;NfQuI|R%T>mj17WZJdR}1{QqM8^P3J04S@ipF?oTss{Qoo zQziQ|%4Kjoxe7V~YlfG6HNN$y<+lpjzO-bYLepm|G`yx@m-}SwaGQkfE)%iMX#%!7 zyoN1y^k&A>tPsv14a?FB9mbdF&p|}D%cY;3wpsb zp&R%HfzBYv=>#|pn%)HHIR!i2ClTQ5P-j5L2~d+>!zOD2Gnt64o|chYb3!11FJ9RT zlxYeT0Zd|cLc_Nj+GMHy4|z<+&ZFcZSAuY!C_JQQKOP$_{tS;OosnB}#v_1Nmyses$HRK) zh1v+?HDz8TmubQ%-M|@QceQ9|cepNuMSKvWuAC}p3FR;u^y}woh7*iZ50yNw&gMRoCd@Iiv5@5r32fZN{%S0z&2JQ58 zXnD1UJQ*zjj?IK#$V~CG(74BR1QuxH^ff1VWU9d=>b>E=2b0J6e*#pX z=l>Q-PlceSVw*F^!t-E%?gb0qfuaZQbYFpSj6?<`2$4DB9Hx`JUdL+F z@mOauUMUtV{Z}Xh1n6R&)r41z14V$w2jwt{cZPm&x{wg>I)kumSks(g7=W`6LkM}e zO@&|HE<}_XBKW&+;a8*%my}Jgj9Ny<&c-IY$yjGO0V_?$Vb#HL1Tz6^&BlpXunJhI z1Yqm;EjHM^UieBfqH;cxg_<5z!1TBq_DA2M%&|xq&$}*yl4Qe~g)hGXo7!fmil z{2cp3KNJDJ(QPRNX7N5KCoBk?s3A6q@* z0dDN1pxsclos4hnr;I+36(!XAum-j%{xCm&2R0|05SZTyr$}9~!|Vk^GMJ^rvfPy}dySO@7$5G-l;kDP9Xl-7z{ErXE4bi@t|*+k72yDus%wF$htMlo~5VhAo) zYPJ*Ll(Gt5`KmY=yGY3koDhtn=ZI_BhOJcsa17Z)S!)`l+?k`#L`ndC*Wr{A0_)@^ z*rl|OF{AD@5t|Q>hyBT~ z;g++SlEMO!j@b*G6d0DhX&0dk;1sIQ#?v)tj}4%szaB1G;W&J%8TMyd;hfoyoXTEw zb`2rAS3E)xhGh|fsBIQaCECaMe zQ^p4Hu5*wx6u-t0`{L(ef5JRyy3IuX`E2;gec+n<4UVLJ4D*wVaUk(60l~p9MXgr? zaEmaa3QyJBYyQ{(?hf37M@}pSGRY^sjbJ)(zP1m8ea}#KYXIpLJ*aJbj3a?sq7WI9 z5&Os(?sZr;JP&ZTVSPtu+oR`62QHVD!pF}OQt}#Do>~f%<8KQuu?(e{4N3s!0UPkG zH_6TC-LV05J-Q9Aym;89woojz6HF%xY93;U0IKdh!c~H})jB93Y~-5QN-|+Xc-J|o zMW;!v@?Pm{6qgmEW8lsRgs03MHi=*1;EDO-{VYL;SY?2N@|D=_y9m2wi^c|U@6jFj z?9P{fZ@yfT0+ z-VA#KKV*o?F#&WxZi3(WQzHQW1$XHz=n1|j302dsUm$N>Yj`9U0~FS$iZ0Yrz7`&| zyAAC(&^^%gQV5r$j?`wn52plGB@ejA8Q@^pe-p$9EF+asK`7RN?!jir3sXiUlyIqA z=zs9xGn8EK7jh~ikCfjYz>Vg|IA4DTVVCwGxI`O)@%Hfa@*EvRX(>z&Y=)ilmr4Ng z6V^BqzZxc?pN>8b6agL#wjiMJj3{DGRK(&gcH=P_|ETw=s0W1vP*UG7AUFY_3mvUZkR_PI;lxJjWY=*V z^l5p{fB7keB0$ggtq3eigYD_zG#YTO3j<_)U(ZtW4U2(}(W}qJq3|qC!F> z%>khob*YWkfc(M^ge17Z-NWM_LL{7s#lhu^VfW>9I4_?8vrneL>eH!kSTz@}zUrb4 z_ekA=L*bu6%kyoMm&!;PpbbGq8KM$%ALNqNfws;e(GSI5ypPOly*Nvr;M!1J--@{M zgJK#Bqd6eBL<{~!+mU+R3G!$M9Cdg94Mcu^0Zi6W7W#0KFxq3yOayG24Y!qVz;W3O zSnik!v&b(Im}3CPq)l88UOpo$0`v~GBj`ew=tMaaaVq8X$=N5e_&$-M#9!o_KXI~3OSe_~O zMlY@jiU562Itd_$P8RNnmYTiLes>62qMpYV2^L(hBkAhY($6{5+j% z34jv<;DCq?p3cnm7GfXio+Tq&PdiSAXBsX*w$Zyt(taB!b%s}o*<#3~_h1>l45v%o zkx?cWz0nIjpm-|L_v9{ui*j)&zG1`*Egjz@y7->xOuY$0P7q1g;&8gwUPvXO!VEDA zalnO*!D6oN7ehX0Cijz++dmqXPtfLJ&8O+VgYV3jApgJ;oF$O6dl#Va;3A|+AHXJV z6~YP*A@5o^jkWKL9-#ke7XjqKB=$DU$O}9dH?@C{V3H5l1%}}MD2eo+Qs;o=>cb)q zc(;e+Kt~wOfy_`0Bd5&dnZFTshZf=R=hNV_;te68O>Z5kTEnStMEJ#Ym0?41vi9GW+z$xo%*qP3U+p0Gpqu|}5F%GVA8t^%z18vWD zcnag9b1Qq6sBXmB6W+`#k$??EL4yRTgbdsw=aOS%6 zNE{@U+acn-DV$GkfqCRt&~jP`S?-RJBNmUmbu^WI1)J2r!Xk13Y@DeRHCBO^9#!JV zm2juRwKw1ck%734;C6yv^U2VrgX4Ll2N-yE4}s_NVL;CUj3aLfh)QbQ*b|&uIWuu! zAHNobw0f84abS&{Iyugk2UGe}$AOT)LDS_OcxS7N;^uo^4M%g=!XfhuSf_l5LrDup z+G*#6mAG)_IQGci6Kyn&lGq>e32b6l!Yxr1615e(+~&Ucpi41`2cF%hOj95pXc&YI zLu6ikAUwgDiPNhMfh1N$BfZ`gDYeo_ASYMY;#i?Rj%IA4)Jl?~;>PWT&$-QFu(!|n z3|6P#R~l$M&ZvoI?tWhzq*yg*kX(#{$V*XQi$J!DS#j69Vw zBnYd-265ELF=0jrUKZqy(2`WRr)?KE;cDrbrH-glV+!Qq#!mD{&r_&(!6vw5uYg_p zr@t8~e*s_!e!yWLx~tMa{vKWPbKyy|h%a7#R!R@}l%CLBXv(JZoyrji_5{ZS2ewJf zZ5$$yfWk~TCT|jY=K;hkYdh6~eZp|A$h`Z*0n8a_1Dww;`^`|#b935NpI<+r(bknM zl-LVKbX`M=i}ltMUp!vYQ%dQ_AAcOV(8DL~NWXp(cBhJmA%g3~^Rd13e2gW<-f&30 zgv^`nh%GatWh&C;z51Ey|I9C^mAqC_4=7se2OS)9Go2PuKbhwbg_M+(6lP^*y_%6PrJy%7G&HEv$8DsWH*ZQeZrqUS z>+7ZK*RM-;b#+p0ZLLJRCRJ5cNtKnAQbk3DR9;>#UA=l$Dl03K=u;>XeSkxv&p$|H zpj2F3EEN?MNhERU+_`g7K|z6(o11Hrlan)M!~Yi!om>&I?|6Cu0000Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$BHmT?0B>(^s9!W$& zRA@uJns-#x*S5z~{? z0@6Xm0@4HlrCC5JBG?OE1q-4CHF;UzxAzf{F-DPlb6M-Gfnnx1`*Zg9yU#x7H?O}o z#GkypypLah{dLKkZ@#HSkFUM)#v88<=5gR_p8cKw?i;<=J3VdMv;#v7@%eAd$;tV+ ztgNi4wY3#JJw5oVet!S`cXW4mqobpv^Xk>B7Ow=c&}!Jn&wE35cD7z^ZS7wb^PgV# z;lqb$Zf=ep6vP6nVJb@cdcQE&@j`>_qXU zIFwyZ#IdU>C~w$mF=&VFj zR}Jnxx~VW<_wL<8Q&W@53n5f(hf57*v#>s7HdeZg?_BLMK`A36LxptMf3aUEc-MUk zupw?T%#)|Va?ea`P5%_wPH zpNDZ2LF_myAdJFmP;xC-Aq(y8?L{xlz!Ha%MOM)gY>N0Nw(R^4#_~_#9H~_^5Wx4q zN-_HzlcvHVPTZ{U&p69Nh;u#z>1JZ>Zc-*HqQ(dEX7EjNQ-jyhfQTR0@n zhfjtEBFoZYlX3-C$(OO2KsXzAyDr0I0EE1-5Rd+^yB~t$crn1zZKI0p;^&GFv5Ear zWI@~aT}TsFqP??OT!;Zo%-o@XA|&z{ATCR;n##Ke5sR-dW4A zqi8+$R5>EK$_lBc9gtQhMdmqA?5c``!=7uf-F+3-yRKkM(q&|yx+Nslmx<8Bh3I%Ioq5r{Qq zqvrB`Y>I#43uE#`*pUJPcxvXCW_f@Wa@`GTLbi;tLDOpz^!(mO-~oMjCTe4awi0AZRNyuL9XMG|hg;5%y#`hn297&vhF#S* z@XAy}P~jTvJZ2&!l~QAay|vqrUhhhoki#RV1+G~Hai9sI`E9t|+$}P}o?v5dFUlu? z8-tgSuHSn&R1<-q9DT~bLd5!ijiSvTqSSI04s0R0*i3|~+5cd!?pughIT;>5y@Rda zjfK;e4+&r?{k*GBd+m}y*)A!?G@uf0+_AY?DL{kJEf683Qg<)7yY-)z;Gcx-iwK@^htT=(`rtFLHed#_D&*K-?gQJnIgm*|L7CMo?A3oyj8wh% zkV_!hCNmJVY6@hFRp2&vJT`tl3f4w5MG1`}0G{pLWY{TaetA)Fu?XQ9mh37|K3`x#tgk$ZvNNYfI zTMw1iR!B3R$Y^_U7H<)HwcsrH(!%AKya=8_>TsDqRRqm5?oJtC>1>`m z3(30^us=N=wP))70O8~7i-=?|QJJ{Ci0p0bc2`M-){maMCuCDldlxAuI?#Fh5xVX? z5~db1+TVz<;tT?4dR2hwO0;-&vWZ=&t&k;KqqXT8@}vD>_ro+8eKZ2*-%LhE<}S2$ zT|sF@(Vs&2`uQO!&Vj0v)|1BWgfY@;0!b!QID5Jk}xB z1t;=BXwd=O>TY~B0G1JHU&?I+w-fT+_ME!@i#WM|4~tF9aiY8&x2ZzB5TfNg{QUh8 zmgL;OM>uls0M0i&KqX~?A&Lp0?Cd>sQ}8{VkCA+w0LTYU>5Y&VrJycwvKq`IKZS?4D^64l4#GFU6Sne2Vqq&fmySzK-KeIxgMUcT-xg^0^=g{E{I zmf8OU`d;s%>_V;p;F4K??Llw#d4QgKk5Nt;;YF{8#Xy+5NLjIEAjpaz`c6dYjTFXr=QoIECtnu9JOmzVQLBPy@&1 zlL1&x+#mHxD6k*}H}78=S_aq$hCv@g$<3vt{>nh^Z5hB2I-F?;MK0f zq2;SAHbA_STP1xP4sspT5x_;t1lNDg2J64@%w72A5kS@x5BTRN;l}+-Lj$1oK+3(5 zb?6cW0BQV^KWr(bdln)v*smWVF4tM?n{{PlvD$4o)ZIov%a0&vA8islSwL+I(-jbz zRku+=5Zwg8YlC-gYyWEOo0ov=T^EN2pzA+f%KHPaXj4Ui*u~gDK|H&u_e}p8LGnNp z9La@_*90LOo^`#Tu~2s(0S%84(DoZG{9_U`Njzs8s*ALfw~c{jSg>e zymMpGcJIQ_0B9>I)%2pCf2WB8fOCwh2*501s(@G@p#sa4kHoQxf0hO|IjdnM$;4>K z1hMhw*D!>J=SbQZjf76XXdyw9=t%-mnwK;PgYr(W$}=v9WjF`y-Zb9VTSM5DdVxt`|I(07hYr z_bBKDjuA36-Z@D?nFMO%#QA$DB@^=wjTbR)sok<7(9(H!XaE$vbcM@UxJIl~$be(i zBB5{7I1Xx@(D_<=)DInx%?TgEzd#LcY4fqtak!Xaqwom=mIuFXjn61yYF*hF^1~!? zEryat>5G1d`yiH&E$z&t2ezZ-ZvD^zR=AE;``LL6T*8eM0JcRg#QG=|7;JwB+Ww=V zOS37mARh;Vuy?47{7Rh8d1freD(4Ymh6M!8IM4c8$`%7?ld1Ixp0ml<Ip{%s1<2 zsJo05uQenHHoq|i%(Kte;P)~-XJK9BL}7A0e=V^uwxk0uhkY_M-g$Z={z?lOFKBeo z1?Nx$3_O{02%isik_OMLmX9(?LYdA{m7(c95k_=^VIKK8?00?Ff5hT{a3wV8|2)GC z!3BT==D>9V#)u5Ev^Wdw83r@i5hYG0Y*PKuaJyz`8DIc9YV359>ni}*hY4fo4lC3a)H$(QA6K+|KikPSm{7C2xwHfMvS#M0uT zz%pFpO&cjXYP3x8!nIpf{}MovWAIu90K3q6Vj)^&rGzE+!!due66RSb35aD*$^Th9r?+9C5k5V(0*z5zigw4FgSVEt?~nw1HW8Zbg!hCn#m8 zZ5x4Qj-!RaV+-t&U%LY#1=`T{A1`FXL35d903Hm$5?U)S!1|rr{&fJlKPDXrU>Wcu zRyYlNCJRq0k|>S6>jFzcJ76pp+q_NkqGrx}3fxjxAUIbC*1KoJCTTk~J!gs%tWU5U zI7>%VCz(I=44U|Pg{wX9_~Kx?g!nWQ2_9b)yEQ>x1OH`DwR6CxN&8n3iBi| z3MzO!j3cJOJoW=oLb;S~ir*(rp$&oqNP5~-q2>}WWhN+51g{-bOLuS9^vj2T87hF} z#*L>Z#5Zm?Ld}9?K|8EIFZ8Vo+$Qj1#1astktNa#!7^dPa`oXdY8tag9HE=^-5=|{ zwWQ0z2Ooz)xIP`Z1StTtwY8T$+KV!bx->}Hy?@-soQl=36 zqeqYUesTYu(^mpvAN-Yf<`p9SlRxMNUjyBxRC=Yr`(8`{O2>{JtNHcUUkCG9|Mu5( zb#(;GKx=TMa={%1(H#b+Wyu7^O z%9ShN8{pTjUE{9-@C@;dXfa5uXlZEye<_3qnGe^mUl)T5!p)mE#UNSm7dphCK*iva z&6C7m^q_0T(r3K*?)*^GlAoWiR9ILjIehrAguaO&DK0LSl$MrCjvhTKA-PFToH!vN zP|3-YCncv&osv{lRY|I=t0grxH4-Wc68i3iq^_<`QeR&$IeYf3;D1ovJ1((IrkF)0000KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000MBNklenXjwyW6>H@jih z|Mtr@8e`OGG@7b0#`+QcPsXTmHyUNT)-}4jPTe)8wXSsQf@LT}TcDB_I!F;Z@7;6! zDseg(5#6hh?v;3xih<7P0T0Kx#r0qnfv z>Nh9yeXif(B3lIV1@QQL+d8U44Y4(K8&MQoh^d(r4kZ7PN*mMdcV4sWzZU5~tTeQ3VcoHqbF{(kL-vc=V1ZEJ5t@39Xt zqffygU5zwGQ%Q`B_o21vx(E@)&MN>9?cUlD2rP)VG;Aq9n0(*%yfqAI0vR4VgkYc; z7p`dA{?P8No#zFB2jAKfDhd{NUAgwB5@9E zs9GC+;BT8d3J!o+#@DU7Dl&Ak7hjw@Y#J_g7|LMF`}SO>@!4P;P0L%cq@*%-|E^8j z@>xHxEOg&ruk37Xx;`pNM{=|qfODTU^FEznF2@LHMcCMU1NI%-l}b&Gwm-c6qXXwO zjo#bU*4b3s8m%m=N6*oJyG$1F-_4$P2AIJBN*7k3X?ZI??t3ex%jw9DpL~4eoB+7{ zjg1{Em#vF6RJY)h{IY!W7*%Df5Uy^)-a}p8X=A$m(VPA|F&6;AxpMBV z*DvX)D6Nf!t6Q)?@iq)fdjW_{5;^w!qrf;mo&dmTuD?8TAo;H@09(E@4cz(K`VD0z z%evQJuoe3gyCJ0x2+Qxnw%JP}c67k(&`HhB^$E@OmqQal96a)V?1`U!_M3U9(CvS@ zctc5XS^To*AC-3xyobr@ann#?nVSoM3qno+3}(i`_C?1S7UQ_=0&_|e@9)o~z{Z1$_@MwX3GB)YYo@~U*c?ZbsD zu0U~cao4S{tl99bMSSZkYdTlgT^dcFIfK5VpD1rD#tT4b7U@Ms5NryGY&(NDSQ*=& z02VI{p`qpn=o{LXlB9>9`BneKoGA3imsfXIg;qvO7gXZ&;2Ri4ka8099r6k>AJA0pP{60tf~cl%Gj| zg__EhX85gP=Y3&Q=*!b%m^gjX1qOgnCNsbmzx;q$pm@O|R8`b__5$xtO<-mOv>-H1 z12czb6@jVgi5N3SEzS%0#cIA+hU&mvfz;$lWvt^lA%rrN9o@JAfl(AJM%m&@44+82 zN{-CU4$RPvbP7P%th3PXVvP;vkx0(89;vAe@02=Wc=WJKq*)3&eYiuxC!i+;h=^BLH%ix4(U%5kwM1(iExiBu_;pwb{9&;;J3G*K_nFbb{S}8 zmCQ)E1rC@145^#x_uK;jBuS8zrU3#FER^?Ic^}}cnaO$vL6U)dLXc+!3|9n{*S{eW zLO3bZ6M;fd2nmWUvw4lYOp$P%$hA)z*3bBD_`+yh8Sf{0)g zR>TIRbW_L_heMSdfRrwnBn+7@lm<)@OOj55!mh2rRYG_G!O?}i4-gkFjS@Lo2yU-i zUiCHx-V8+yVk(q~*(|B;vfAtQ3_uyWQ1=oSO2n>~kl6NmCjYYlQqgewg91^AUCoPa zo<2fsGpoaz;(7D9?7IawrI6T_}<9$7#UKn4NCg9Z5?+08qaC50x!q)U)16Nwy0 zh~6~-EvSKsQ-BD+de4c8*{1I~9qyjxY1>IsTxbG;A`O9{hCon2a}O)9dR203Uj9kC7v?@c;k-07*qoM6N<$g3J82Bme*a literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml new file mode 100644 index 000000000..0e21a2eb9 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml @@ -0,0 +1,10 @@ + + ovqt_plugin_tile_editor + TileEditor + 1.0 + Ryzom Core + Tile bank editing plugin. + + + + \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc new file mode 100644 index 000000000..55950d217 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc @@ -0,0 +1,29 @@ + + + images/add_tile.png + images/delete_image.png + images/delete_tile.png + images/replace_image.png + + + images/ic_nel_add_item.png + images/ic_nel_new.png + images/ic_nel_open.png + images/ic_nel_save.png + images/ic_nel_save_as.png + images/down.png + images/left.png + images/reset.png + images/right.png + images/up.png + + + images/rotation0.png + images/rotation90.png + images/rotation180.png + images/rotation270.png + + + images/empty_image.png + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp new file mode 100644 index 000000000..a0faa03f8 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -0,0 +1,171 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "tile_editor_main_window.h" + +#include "nel/misc/path.h" + +#include +#include +#include +#include +#include + +#include "../core/icore.h" +#include "../core/core_constants.h" +#include "../core/menu_manager.h" + +#include "tile_model.h" +#include "tile_item.h" + +TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) + : QMainWindow(parent), + m_ui(new Ui::TileEditorMainWindow) +{ + m_ui->setupUi(this); + m_undoStack = new QUndoStack(this); + + // Retrieve the menu manager + Core::ICore *core = Core::ICore::instance(); + Core::MenuManager *menuManager = core->menuManager(); + + QMenu *m_tileEditorMenu; + // Create tile rotation drop down toolbar menu. + m_rotationMenu = new QMenu(tr("Rotate Tile"), m_ui->toolBar); + m_rotationMenu->setIcon(QIcon(":/tileRotation/images/rotation0.png")); + QList rotateActions; + rotateActions.push_back(m_ui->actionRotateTile0); + rotateActions.push_back(m_ui->actionRotateTile90); + rotateActions.push_back(m_ui->actionRotateTile180); + rotateActions.push_back(m_ui->actionRotateTile270); + m_rotationMenu->addActions(rotateActions); + m_ui->toolBar->addAction(m_rotationMenu->menuAction()); + + // Create the tile zoom menu. + m_zoomMenu = new QMenu(tr("Zoom"), m_ui->toolBar); + QList zoomActions; + + m_tileEditorMenu = new QMenu(tr("Tile Editor"), core->menuManager()->menuBar()); + m_tileDisplayMenu = new QMenu(tr("Tile Display"), m_ui->toolBar); + QList displayActions; + displayActions.push_back(m_ui->actionTileDisplayFilename); + displayActions.push_back(m_ui->actionTileDisplayIndex); + m_ui->actionTileDisplayIndex->setChecked(true); + m_tileDisplayMenu->addActions(displayActions); + m_tileEditorMenu->addMenu(m_tileDisplayMenu); + core->menuManager()->menuBar()->addMenu(m_tileEditorMenu); + + // Set up the list views. + QStringList headers; + headers << "Tile Set"; + m_model = new TileModel(headers, this); + + // Set up the tile set list view. + m_ui->tileSetLV->setModel(m_model); + m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); + connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); + + // 128x128 List View + m_ui->listView128->setModel(m_model); + m_ui->listView128->addAction(m_ui->actionAddTile); + m_ui->listView128->addAction(m_ui->actionDeleteTile); + m_ui->listView128->addAction(m_ui->actionReplaceImage); + m_ui->listView128->addAction(m_ui->actionDeleteImage); + + // Connect context menu actions up. + connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); + connect(m_ui->actionDeleteTile, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteTile(bool))); + connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); + connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); +} + +TileEditorMainWindow::~TileEditorMainWindow() +{ + delete m_ui; + delete m_undoStack; + delete m_rotationMenu; + delete m_zoomMenu; +} + +void TileEditorMainWindow::onActionAddTile(bool triggered) +{ + onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); +} + +void TileEditorMainWindow::onActionDeleteTile(bool triggered) +{ +} + +void TileEditorMainWindow::onActionReplaceImage(bool triggered) +{ +} + +void TileEditorMainWindow::onActionDeleteImage(bool triggered) +{ +} + +void TileEditorMainWindow::onTileSetAdd() +{ + bool ok; + QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); + if (ok && !text.isEmpty()) + { + //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) + //{ + // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); + //} + //else + //{ + + QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); + TileModel *model = static_cast(m_ui->tileSetLV->model()); + + if(index.isValid()) + { + if(!model->insertRow(index.row()+1, index.parent())) + return; + + //updateActions() + + for(int column=0; columncolumnCount(index.parent()); column++) + { + QModelIndex child = model->index(index.row()+1, column, index.parent()); + model->setData(child, QVariant(text), Qt::EditRole); + } + } + else + { + QVector items; + items.push_back(QVariant(text)); + TileItem *item = new TileItem(items, 0); + model->appendRow(item); + //updateActions() + } + + // tileBank.addTileSet( text.toStdString() ); + + // ui.tileSetListWidget->addItem(text); + // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); + //} + } +} + +void TileEditorMainWindow::onActionAddTile(int tabId) +{ + QFileDialog::Options options; + QString selectedFilter; + QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "PNG Bitmap(*.png);;All Files (*.*);;", &selectedFilter, options); +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h new file mode 100644 index 000000000..2f5ce3731 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -0,0 +1,63 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_EDITOR_MAIN_WINDOW_H +#define TILE_EDITOR_MAIN_WINDOW_H + +#include "ui_tile_editor_main_window.h" + +#include "nel/misc/types_nl.h" +#include "nel/misc/sheet_id.h" + +#include + +namespace Ui { + class TileEditorMainWindow; +} + +class TileModel; + +class TileEditorMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit TileEditorMainWindow(QWidget *parent = 0); + ~TileEditorMainWindow(); + + QUndoStack *getUndoStack() { return m_undoStack; } + +public Q_SLOTS: + void onActionAddTile(bool triggered); + void onActionDeleteTile(bool triggered); + void onActionReplaceImage(bool triggered); + void onActionDeleteImage(bool triggered); + void onTileSetAdd(); + +private: + void onActionAddTile(int tabId); + + Ui::TileEditorMainWindow *m_ui; + QUndoStack *m_undoStack; + QMenu *m_rotationMenu; + QMenu *m_zoomMenu; + QMenu *m_tileDisplayMenu; + QMenu *m_tileEditorMenu; + + TileModel *m_model; +}; + +#endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui new file mode 100644 index 000000000..7b76e6aaa --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -0,0 +1,663 @@ + + + TileEditorMainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + 0 + + + + 128x128 + + + + + + Qt::ActionsContextMenu + + + + + + + Edit Channel + + + + + + Diffuse + + + true + + + + + + + Additive + + + + + + + + + + + 256x256 + + + + + + + + + Edit Channel + + + + + + Diffuse + + + true + + + true + + + + + + + Additive + + + + + + + + + + + Transition + + + + + + + + + Edit Channel + + + + + + Diffuse + + + true + + + + + + + Additive + + + + + + + Alpha + + + + + + + + + + + Displacement + + + + + + + + + + Tile Set Details + + + + + + Qt::LeftToRight + + + Oriented + + + + + + + + + + Surface Data: + + + + + + + Vegetation Set: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + + :/newPrefix/reset.png:/newPrefix/reset.png + + + + + + + + + + + + + Tile Editor Tool Bar + + + TopToolBarArea + + + false + + + + + + + + + Tile Bank + + + 1 + + + + + + + Lands + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + + :/movementIcons/images/ic_nel_add_item.png:/movementIcons/images/ic_nel_add_item.png + + + + + + + ... + + + + :/movementIcons/images/reset.png:/movementIcons/images/reset.png + + + + + + + ... + + + + :/movementIcons/images/ic_nel_open.png:/movementIcons/images/ic_nel_open.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Tile Sets + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + :/movementIcons/images/up.png:/movementIcons/images/up.png + + + + + + + ... + + + + :/movementIcons/images/down.png:/movementIcons/images/down.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + + :/movementIcons/images/ic_nel_add_item.png:/movementIcons/images/ic_nel_add_item.png + + + + + + + ... + + + + :/movementIcons/images/reset.png:/movementIcons/images/reset.png + + + + + + + ... + + + + :/movementIcons/images/ic_nel_open.png:/movementIcons/images/ic_nel_open.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + ... + + + + + + + ... + + + + + + + + + Tile Bank Texture Path + + + + + + + + + + + + + + + + :/movementIcons/images/ic_nel_open.png:/movementIcons/images/ic_nel_open.png + + + Open Tile Bank + + + Open Tile Bank + + + + + + :/tileRotation/images/rotation0.png:/tileRotation/images/rotation0.png + + + 0 + + + Rotate Tile 0 Degrees + + + + + + :/movementIcons/images/ic_nel_save.png:/movementIcons/images/ic_nel_save.png + + + Save Tile Bank + + + Save Tile Bank + + + + + + :/movementIcons/images/ic_nel_save_as.png:/movementIcons/images/ic_nel_save_as.png + + + Save Tile Bank As... + + + Save Tile Bank As... + + + + + + :/tileRotation/images/rotation90.png:/tileRotation/images/rotation90.png + + + 90 + + + Rotate Tile 90 Degrees + + + + + + :/tileRotation/images/rotation180.png:/tileRotation/images/rotation180.png + + + 180 + + + Rotate Tile180 Degrees + + + + + + :/tileRotation/images/rotation270.png:/tileRotation/images/rotation270.png + + + 270 + + + Rotate Tile 270 Degrees + + + + + Batch Load + + + Batch Load + + + + + Import Border + + + Import Border + + + + + Export Border + + + Export Border + + + + + true + + + Index + + + Display Tile Index + + + + + true + + + Filename + + + Display Tile Filename + + + + + + :/tileTools/images/add_tile.png:/tileTools/images/add_tile.png + + + Add Tile + + + Add Tile + + + + + + :/tileTools/images/delete_tile.png:/tileTools/images/delete_tile.png + + + Delete Tile + + + Delete Tile + + + + + + :/tileTools/images/replace_image.png:/tileTools/images/replace_image.png + + + Replace Image + + + Replace Image + + + + + + :/tileTools/images/delete_image.png:/tileTools/images/delete_image.png + + + Delete Image + + + Delete Image + + + + + + + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp new file mode 100644 index 000000000..ac12766b8 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp @@ -0,0 +1,75 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "tile_editor_plugin.h" +#include "tile_editor_main_window.h" +#include "../core/icore.h" +#include "../core/menu_manager.h" +#include "../core/core_constants.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +// NeL includes +#include "nel/misc/debug.h" + +using namespace TileEditorPluginQt; + +TileEditorPlugin::~TileEditorPlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); +} + +bool TileEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + addAutoReleasedObject(new TileEditorContext()); + return true; +} + +void TileEditorPlugin::extensionsInitialized() +{ +} + +void TileEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_LibContext = new NLMISC::CLibraryContext(*nelContext); +} + +void TileEditorPlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +Q_EXPORT_PLUGIN(TileEditorPlugin) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h new file mode 100644 index 000000000..2398be2c4 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h @@ -0,0 +1,109 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_EDITOR_PLUGIN_H +#define TILE_EDITOR_PLUGIN_H + +#include "../../extension_system/iplugin.h" +#include "../core/icontext.h" + +#include "nel/misc/app_context.h" + +#include "tile_editor_main_window.h" + +#include + +namespace NLMISC +{ +class CLibraryContext; +} + +namespace TileEditorPluginQt +{ + +class TileEditorPlugin : public QObject, public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_INTERFACES(ExtensionSystem::IPlugin) +public: + + ~TileEditorPlugin(); + + bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); + void extensionsInitialized(); + void setNelContext(NLMISC::INelContext *nelContext); + + void addAutoReleasedObject(QObject *obj); + +protected: + NLMISC::CLibraryContext *m_LibContext; + +private: + ExtensionSystem::IPluginManager *m_plugMan; + QList m_autoReleaseObjects; + +}; + +class TileEditorContext: public Core::IContext +{ + Q_OBJECT +public: + TileEditorContext(QObject *parent = 0) : IContext(parent) + { + m_tileEditorMainWindow = new TileEditorMainWindow(); + } + + virtual ~TileEditorContext() + { + delete m_tileEditorMainWindow; + } + + virtual QString id() const + { + return QLatin1String("TileEditor"); + } + + virtual QString trName() const + { + return tr("Tile Editor"); + } + + virtual QIcon icon() const + { + return QIcon(":/tileRotation/images/rotation0.png"); + } + + virtual QUndoStack *undoStack() + { + return m_tileEditorMainWindow->getUndoStack(); + } + + virtual void open() + { + } + + virtual QWidget *widget() + { + return m_tileEditorMainWindow; + } + +private: + TileEditorMainWindow *m_tileEditorMainWindow; +}; + +} // namespace TileEditorPluginQt + +#endif // TILE_EDITOR_PLUGIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp new file mode 100644 index 000000000..d6c87017d --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -0,0 +1,138 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "tile_item.h" + +TileItem::TileItem(const QVector &data, TileItem *parent) +{ + parentItem = parent; + itemData = data; +} + +TileItem::~TileItem() +{ + qDeleteAll(childItems); +} + +void TileItem::appendChild(TileItem *item) +{ + childItems.append(item); +} + +TileItem *TileItem::child(int row) +{ + return childItems.value(row); +} + +int TileItem::childCount() const +{ + return childItems.count(); +} + +int TileItem::childNumber() const +{ + if(parentItem) + return parentItem->childItems.indexOf(const_cast(this)); + return 0; +} + +bool TileItem::insertChildren(int position, int count, int columns) +{ + if(position<0 || position>childItems.size()) + return false; + + for(int row = 0; row < count; row++) + { + QVector data(columns); + TileItem *item = new TileItem(data, this); + childItems.insert(position, item); + } + + return true; +} + +bool TileItem::removeChildren(int position, int count) +{ + if(position<0 || position+count>childItems.size()) + return false; + + for(int row=0; row itemData.size()) + return false; + + for(int column=0; columninsertColumns(position, columns); + + return true; +} + +int TileItem::row() const +{ + if(parentItem) + return parentItem->childItems.indexOf(const_cast(this)); + + return 0; +} + +int TileItem::columnCount() const +{ + return itemData.count(); +} + +QVariant TileItem::data(int column) const +{ + return itemData.value(column); +} + +bool TileItem::setData(int column, const QVariant &value) +{ + if(column < 0 || column >= itemData.size()) + return false; + + itemData[column] = value; + return true; +} + +TileItem *TileItem::parent() +{ + return parentItem; +} + +void TileItem::appendRow(const QList &items) +{ + Q_FOREACH(TileItem *item, items) + appendRow(item); +} + +void TileItem::appendRow(TileItem *item) +{ + childItems.append(item); +} +//QImage *TileItem::getTileImageFromChannel(int channel) +//{ +// return m_tileChannels[channel]; +//} + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h new file mode 100644 index 000000000..4d9f13e0f --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -0,0 +1,66 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_ITEM_H +#define TILE_ITEM_H + +#include "nel/misc/types_nl.h" + +#include +#include + +class TileItem +{ +public: + + TileItem(const QVector &data, TileItem *parent=0); + ~TileItem(); + + void appendChild(TileItem *child); + + TileItem *child(int row); + int childCount() const; + int childNumber() const; + int columnCount() const; + bool setData(int column, const QVariant &value); + QVariant data(int column) const; + + bool insertChildren(int position, int count, int columns); + bool removeChildren(int position, int count); + bool insertColumns(int position, int columns); + + int row() const; + TileItem *parent(); + + void appendRow(const QList &items); + void appendRow(TileItem *item); + + //QImage *getTileImageFromChannel(int channel); + + //int getTileIndex() { return m_tileIndex; } + //QString getTileFilename() { return m_tileFilename; } + +private: + QList childItems; + QVector itemData; + TileItem *parentItem; + + //QMap m_tileChannels; + //int m_tileIndex; + //QString m_tileFilename; +}; + +#endif // TILE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp new file mode 100644 index 000000000..20911310c --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -0,0 +1,123 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "tile_model.h" +#include "tile_item.h" + +#include + +TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) +{ + QVector rootData; + Q_FOREACH(QString header, headers) + rootData << header; + + rootItem = new TileItem(rootData); +} + +TileModel::~TileModel() +{ + delete rootItem; +} + +TileItem *TileModel::getItem(const QModelIndex &index) const +{ + if(index.isValid()) + { + TileItem *item = static_cast(index.internalPointer()); + if(item) return item; + } + return rootItem; +} + +QModelIndex TileModel::index(int row, int column, const QModelIndex &parent) const +{ + if(parent.isValid() && parent.column() != 0) + return QModelIndex(); + + TileItem *parentItem = getItem(parent); + + TileItem *childItem = parentItem->child(row); + if(childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} + +QModelIndex TileModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + TileItem *childItem = getItem(index); + TileItem *parentItem = childItem->parent(); + + if(parentItem == rootItem) + return QModelIndex(); + + return createIndex(parentItem->childNumber(), 0, parentItem); +} + +int TileModel::rowCount(const QModelIndex &parent) const +{ + TileItem *parentItem = getItem(parent); + return parentItem->childCount(); +} + +int TileModel::columnCount(const QModelIndex &parent) const +{ + TileItem *parentItem = getItem(parent); + return parentItem->columnCount(); +} + +QVariant TileModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if(role != Qt::DisplayRole) + return QVariant(); + + TileItem *item = static_cast(index.internalPointer()); + return item->data(index.column()); +} + +Qt::ItemFlags TileModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return Qt::ItemIsEnabled; + + return Qt::ItemIsEnabled|Qt::ItemIsSelectable; +} + +QVariant TileModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal && role == Qt::DisplayRole) + return rootItem->data(section); + + return QVariant(); +} + +void TileModel::appendRow(const QList &items) +{ + rootItem->appendRow(items); +} + + +void TileModel::appendRow(TileItem *item) +{ + rootItem->appendRow(item); +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h new file mode 100644 index 000000000..692d1ee65 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -0,0 +1,54 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_MODEL_H +#define TILE_MODEL_H + +#include "nel/misc/types_nl.h" + +#include + +class TileItem; + +class TileModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + TileModel::TileModel(const QStringList &headers, QObject *parent); + ~TileModel(); + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent= QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + // Tile Model specific functions + void appendRow(const QList &items); + void appendRow(TileItem *item); + +private: + TileItem *getItem(const QModelIndex &index) const; + + //QList m_tiles; + //int m_activeEditChannel; + TileItem *rootItem; +}; + +#endif // TILE_128_MODEL_H From f57c47af5471107642a3d42b7b100b9b0a45b5c3 Mon Sep 17 00:00:00 2001 From: sfb Date: Wed, 7 Dec 2011 13:46:27 -0600 Subject: [PATCH 002/282] Changed: #1409 Tile Edit Qt - Adding some of the hierarchy logic to the list views. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 96 +++++++++++++++---- .../tile_editor/tile_editor_main_window.h | 1 + .../tile_editor/tile_editor_main_window.ui | 2 +- .../src/plugins/tile_editor/tile_item.cpp | 30 ++++++ .../src/plugins/tile_editor/tile_item.h | 13 ++- 5 files changed, 121 insertions(+), 21 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index a0faa03f8..afeaadb1d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -75,8 +75,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Set up the tile set list view. m_ui->tileSetLV->setModel(m_model); - m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); + //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); + connect(m_ui->tileSetLV->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View m_ui->listView128->setModel(m_model); @@ -130,30 +133,71 @@ void TileEditorMainWindow::onTileSetAdd() //else //{ - QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); + //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); TileModel *model = static_cast(m_ui->tileSetLV->model()); - if(index.isValid()) - { - if(!model->insertRow(index.row()+1, index.parent())) - return; + //if(index.isValid()) + //{ + // if(!model->insertRow(index.row()+1, index.parent())) + // return; - //updateActions() + // //updateActions() + + // for(int column=0; columncolumnCount(index.parent()); column++) + // { + // QModelIndex child = model->index(index.row()+1, column, index.parent()); + // model->setData(child, QVariant(text), Qt::EditRole); + // } + //} + //else + //{ + // Create the new tile set. + QVector items; + items.push_back(text); + TileItem *tileSet = new TileItem(items); + + // child for 128x128 tiles + QVector tiles128; + tiles128.push_back(QString("128")); + TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); + + // child for 256x256 tiles + QVector tiles256; + tiles256.push_back(QString("256")); + TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); + - for(int column=0; columncolumnCount(index.parent()); column++) + // child for transition tiles. + QVector tilesTrans; + tilesTrans.push_back(QString("Transition")); + TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); + + // Add the default transition tiles. + // TODO tie this to CTileSet::count from NeL + for(int transPos=0; transPos < 48; transPos++) { - QModelIndex child = model->index(index.row()+1, column, index.parent()); - model->setData(child, QVariant(text), Qt::EditRole); + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); + TileItem *transTile= new TileItem(tileInfo); + tileTrans->appendRow(transTile); } - } - else - { - QVector items; - items.push_back(QVariant(text)); - TileItem *item = new TileItem(items, 0); - model->appendRow(item); + + // child for displacement tiles + QVector tilesDisp; + tilesDisp.push_back(QString("Displacement")); + TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); + + // Append them in the correct order to the tile set. + tileSet->appendRow(tile128); + tileSet->appendRow(tile256); + tileSet->appendRow(tileTrans); + tileSet->appendRow(tileDisp); + + model->appendRow(tileSet); + + m_ui->tileSetLV->reset(); //updateActions() - } + //} // tileBank.addTileSet( text.toStdString() ); @@ -168,4 +212,20 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QFileDialog::Options options; QString selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "PNG Bitmap(*.png);;All Files (*.*);;", &selectedFilter, options); +} + +void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) +{ + + QModelIndex tile128Idx = newIndex.child(0,0); + QModelIndex tile256Idx = newIndex.child(1,0); + QModelIndex tileTransIdx = newIndex.child(2,0); + QModelIndex tileDispIdx = newIndex.child(3,0); + + + m_ui->listView128->setRootIndex(newIndex); + m_ui->listView256->setRootIndex(tile256Idx); + m_ui->listViewTransition->setRootIndex(tileTransIdx); + m_ui->listViewDisplacement->setRootIndex(tileDispIdx); +// m_ui->listView128->setModelColumn } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 2f5ce3731..267eff50c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -46,6 +46,7 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); private: void onActionAddTile(int tabId); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index 7b76e6aaa..d9b8d7116 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -468,7 +468,7 @@ - + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index d6c87017d..ee255755b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -16,6 +16,8 @@ #include "tile_item.h" +#include + TileItem::TileItem(const QVector &data, TileItem *parent) { parentItem = parent; @@ -121,6 +123,11 @@ TileItem *TileItem::parent() return parentItem; } +void TileItem::setParent(TileItem *parent) +{ + parentItem = parent; +} + void TileItem::appendRow(const QList &items) { Q_FOREACH(TileItem *item, items) @@ -129,10 +136,33 @@ void TileItem::appendRow(const QList &items) void TileItem::appendRow(TileItem *item) { + nlinfo("number of children: %d", childItems.size()); + item->setParent(this); childItems.append(item); + nlinfo("number of children: %d", childItems.size()); } //QImage *TileItem::getTileImageFromChannel(int channel) //{ // return m_tileChannels[channel]; //} + +/////////////////////////////////////////////////// + +TileTypeTileItem::TileTypeTileItem(const QVector &data, TileItem *parent) : TileItem(data,parent) +{ +} + +TileTypeTileItem::~TileTypeTileItem() +{ + qDeleteAll(childItems); +} + +QVariant TileTypeTileItem::data(int column) const +{ + QVariant val = itemData.value(column); + + nlinfo("the column is %d and the value is '%s'. there are %d values", + column, val.toString().toStdString().c_str(), itemData.size()); + return itemData.value(column); +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h index 4d9f13e0f..8f1c6a61a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -27,7 +27,7 @@ class TileItem public: TileItem(const QVector &data, TileItem *parent=0); - ~TileItem(); + virtual ~TileItem(); void appendChild(TileItem *child); @@ -44,6 +44,7 @@ public: int row() const; TileItem *parent(); + void setParent(TileItem *parent); void appendRow(const QList &items); void appendRow(TileItem *item); @@ -53,7 +54,7 @@ public: //int getTileIndex() { return m_tileIndex; } //QString getTileFilename() { return m_tileFilename; } -private: +protected: QList childItems; QVector itemData; TileItem *parentItem; @@ -63,4 +64,12 @@ private: //QString m_tileFilename; }; +class TileTypeTileItem : public TileItem +{ +public: + TileTypeTileItem(const QVector &data, TileItem *parent=0); + virtual ~TileTypeTileItem(); + QVariant data(int column) const; +}; + #endif // TILE_ITEM_H From dfc1b0ba946b9d0376bd0b0d98550a50a42dfaba Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 9 Dec 2011 07:03:33 -0600 Subject: [PATCH 003/282] Changed: #1409 Made the tile set and tile type tabs connect. Added the context menu to each tab. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 46 +++++++++++++++---- .../tile_editor/tile_editor_main_window.ui | 28 +++++++++-- .../src/plugins/tile_editor/tile_item.cpp | 8 +--- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index afeaadb1d..48e8ff36f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -87,6 +87,27 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView128->addAction(m_ui->actionDeleteTile); m_ui->listView128->addAction(m_ui->actionReplaceImage); m_ui->listView128->addAction(m_ui->actionDeleteImage); + + // 256x256 List View + m_ui->listView256->setModel(m_model); + m_ui->listView256->addAction(m_ui->actionAddTile); + m_ui->listView256->addAction(m_ui->actionDeleteTile); + m_ui->listView256->addAction(m_ui->actionReplaceImage); + m_ui->listView256->addAction(m_ui->actionDeleteImage); + + // Transition List View + m_ui->listViewTransition->setModel(m_model); + //m_ui->listViewTransition->addAction(m_ui->actionAddTile); + //m_ui->listViewTransition->addAction(m_ui->actionDeleteTile); + m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); + m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); + + // Displacement List View + m_ui->listViewDisplacement->setModel(m_model); + //m_ui->listViewDisplacement->addAction(m_ui->actionAddTile); + //m_ui->listViewDisplacement->addAction(m_ui->actionDeleteTile); + m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); + m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); // Connect context menu actions up. connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); @@ -174,7 +195,7 @@ void TileEditorMainWindow::onTileSetAdd() // Add the default transition tiles. // TODO tie this to CTileSet::count from NeL - for(int transPos=0; transPos < 48; transPos++) + for(int transPos=0; transPos<48; transPos++) { QVector tileInfo; tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); @@ -187,6 +208,16 @@ void TileEditorMainWindow::onTileSetAdd() tilesDisp.push_back(QString("Displacement")); TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); + // Add the default displacement tiles. + // TODO tie this to CTileSet::CountDisplace from NeL + for(int dispPos=0; dispPos<16; dispPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); + TileItem *dispTile= new TileItem(tileInfo); + tileDisp->appendRow(dispTile); + } + // Append them in the correct order to the tile set. tileSet->appendRow(tile128); tileSet->appendRow(tile256); @@ -216,16 +247,13 @@ void TileEditorMainWindow::onActionAddTile(int tabId) void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { - - QModelIndex tile128Idx = newIndex.child(0,0); - QModelIndex tile256Idx = newIndex.child(1,0); - QModelIndex tileTransIdx = newIndex.child(2,0); - QModelIndex tileDispIdx = newIndex.child(3,0); - + QModelIndex &tile128Idx = newIndex.child(0,0); + QModelIndex &tile256Idx = newIndex.child(1,0); + QModelIndex &tileTransIdx = newIndex.child(2,0); + QModelIndex &tileDispIdx = newIndex.child(3,0); - m_ui->listView128->setRootIndex(newIndex); + m_ui->listView128->setRootIndex(tile128Idx); m_ui->listView256->setRootIndex(tile256Idx); m_ui->listViewTransition->setRootIndex(tileTransIdx); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); -// m_ui->listView128->setModelColumn } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index d9b8d7116..5897d29be 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -18,7 +18,7 @@ - 0 + 2 @@ -66,7 +66,11 @@ - + + + Qt::ActionsContextMenu + + @@ -105,7 +109,17 @@ - + + + Qt::ActionsContextMenu + + + QListView::LeftToRight + + + QListView::Batched + + @@ -148,7 +162,11 @@ - + + + Qt::ActionsContextMenu + + @@ -468,7 +486,7 @@ - + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index ee255755b..5758b9280 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -36,6 +36,7 @@ void TileItem::appendChild(TileItem *item) TileItem *TileItem::child(int row) { + //nlinfo("row %d and size %d", row, childItems.size()); return childItems.value(row); } @@ -136,16 +137,9 @@ void TileItem::appendRow(const QList &items) void TileItem::appendRow(TileItem *item) { - nlinfo("number of children: %d", childItems.size()); item->setParent(this); childItems.append(item); - nlinfo("number of children: %d", childItems.size()); } -//QImage *TileItem::getTileImageFromChannel(int channel) -//{ -// return m_tileChannels[channel]; -//} - /////////////////////////////////////////////////// From 17f1a286e2f1492b127dbb56c7d469091bb1f9ec Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 9 Dec 2011 08:10:02 -0600 Subject: [PATCH 004/282] Changed: #1409 Fixed some things for a sane compiler (Linux/gcc) --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 200 +++++++++--------- .../src/plugins/tile_editor/tile_model.h | 4 +- 2 files changed, 102 insertions(+), 102 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 48e8ff36f..12596e1bb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -39,7 +39,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_undoStack = new QUndoStack(this); // Retrieve the menu manager - Core::ICore *core = Core::ICore::instance(); + Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); QMenu *m_tileEditorMenu; @@ -77,8 +77,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); - connect(m_ui->tileSetLV->selectionModel(), - SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + connect(m_ui->tileSetLV->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View @@ -143,98 +143,98 @@ void TileEditorMainWindow::onActionDeleteImage(bool triggered) void TileEditorMainWindow::onTileSetAdd() { - bool ok; - QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); - if (ok && !text.isEmpty()) - { - //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) - //{ - // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); - //} - //else - //{ - - //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); - TileModel *model = static_cast(m_ui->tileSetLV->model()); - - //if(index.isValid()) - //{ - // if(!model->insertRow(index.row()+1, index.parent())) - // return; - - // //updateActions() - - // for(int column=0; columncolumnCount(index.parent()); column++) - // { - // QModelIndex child = model->index(index.row()+1, column, index.parent()); - // model->setData(child, QVariant(text), Qt::EditRole); - // } - //} - //else - //{ - // Create the new tile set. - QVector items; - items.push_back(text); - TileItem *tileSet = new TileItem(items); - - // child for 128x128 tiles - QVector tiles128; - tiles128.push_back(QString("128")); - TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); - - // child for 256x256 tiles - QVector tiles256; - tiles256.push_back(QString("256")); - TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); - - - // child for transition tiles. - QVector tilesTrans; - tilesTrans.push_back(QString("Transition")); - TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); - - // Add the default transition tiles. - // TODO tie this to CTileSet::count from NeL - for(int transPos=0; transPos<48; transPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); - TileItem *transTile= new TileItem(tileInfo); - tileTrans->appendRow(transTile); - } - - // child for displacement tiles - QVector tilesDisp; - tilesDisp.push_back(QString("Displacement")); - TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); - - // Add the default displacement tiles. - // TODO tie this to CTileSet::CountDisplace from NeL - for(int dispPos=0; dispPos<16; dispPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); - TileItem *dispTile= new TileItem(tileInfo); - tileDisp->appendRow(dispTile); - } - - // Append them in the correct order to the tile set. - tileSet->appendRow(tile128); - tileSet->appendRow(tile256); - tileSet->appendRow(tileTrans); - tileSet->appendRow(tileDisp); - - model->appendRow(tileSet); - - m_ui->tileSetLV->reset(); - //updateActions() - //} - - // tileBank.addTileSet( text.toStdString() ); - - // ui.tileSetListWidget->addItem(text); - // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); - //} + bool ok; + QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); + if (ok && !text.isEmpty()) + { + //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) + //{ + // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); + //} + //else + //{ + + //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); + TileModel *model = static_cast(m_ui->tileSetLV->model()); + + //if(index.isValid()) + //{ + // if(!model->insertRow(index.row()+1, index.parent())) + // return; + + // //updateActions() + + // for(int column=0; columncolumnCount(index.parent()); column++) + // { + // QModelIndex child = model->index(index.row()+1, column, index.parent()); + // model->setData(child, QVariant(text), Qt::EditRole); + // } + //} + //else + //{ + // Create the new tile set. + QVector items; + items.push_back(text); + TileItem *tileSet = new TileItem(items); + + // child for 128x128 tiles + QVector tiles128; + tiles128.push_back(QString("128")); + TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); + + // child for 256x256 tiles + QVector tiles256; + tiles256.push_back(QString("256")); + TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); + + + // child for transition tiles. + QVector tilesTrans; + tilesTrans.push_back(QString("Transition")); + TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); + + // Add the default transition tiles. + // TODO tie this to CTileSet::count from NeL + for(int transPos=0; transPos<48; transPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); + TileItem *transTile= new TileItem(tileInfo); + tileTrans->appendRow(transTile); + } + + // child for displacement tiles + QVector tilesDisp; + tilesDisp.push_back(QString("Displacement")); + TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); + + // Add the default displacement tiles. + // TODO tie this to CTileSet::CountDisplace from NeL + for(int dispPos=0; dispPos<16; dispPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); + TileItem *dispTile= new TileItem(tileInfo); + tileDisp->appendRow(dispTile); + } + + // Append them in the correct order to the tile set. + tileSet->appendRow(tile128); + tileSet->appendRow(tile256); + tileSet->appendRow(tileTrans); + tileSet->appendRow(tileDisp); + + model->appendRow(tileSet); + + m_ui->tileSetLV->reset(); + //updateActions() + //} + + // tileBank.addTileSet( text.toStdString() ); + + // ui.tileSetListWidget->addItem(text); + // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); + //} } } @@ -247,13 +247,13 @@ void TileEditorMainWindow::onActionAddTile(int tabId) void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { - QModelIndex &tile128Idx = newIndex.child(0,0); - QModelIndex &tile256Idx = newIndex.child(1,0); - QModelIndex &tileTransIdx = newIndex.child(2,0); - QModelIndex &tileDispIdx = newIndex.child(3,0); + const QModelIndex &tile128Idx = newIndex.child(0,0); + const QModelIndex &tile256Idx = newIndex.child(1,0); + const QModelIndex &tileTransIdx = newIndex.child(2,0); + const QModelIndex &tileDispIdx = newIndex.child(3,0); m_ui->listView128->setRootIndex(tile128Idx); m_ui->listView256->setRootIndex(tile256Idx); m_ui->listViewTransition->setRootIndex(tileTransIdx); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); -} \ No newline at end of file +} diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index 692d1ee65..140f60555 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -28,8 +28,8 @@ class TileModel : public QAbstractItemModel Q_OBJECT public: - TileModel::TileModel(const QStringList &headers, QObject *parent); - ~TileModel(); + TileModel(const QStringList &headers, QObject *parent); + ~TileModel(); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Qt::ItemFlags flags(const QModelIndex &index) const; From 04c6c1b48ad572d49593b6967260e711ce2dcbcd Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 22 Dec 2011 19:58:59 -0600 Subject: [PATCH 005/282] Changed: #1409 Added hierarchy to the tile model, renamed the base class to 'Node' --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 71 +------- .../src/plugins/tile_editor/tile_item.cpp | 172 ++++++++++++------ .../src/plugins/tile_editor/tile_item.h | 84 ++++++--- .../src/plugins/tile_editor/tile_model.cpp | 68 +++++-- .../src/plugins/tile_editor/tile_model.h | 15 +- 5 files changed, 252 insertions(+), 158 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 12596e1bb..427fda7a9 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -97,15 +97,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Transition List View m_ui->listViewTransition->setModel(m_model); - //m_ui->listViewTransition->addAction(m_ui->actionAddTile); - //m_ui->listViewTransition->addAction(m_ui->actionDeleteTile); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View m_ui->listViewDisplacement->setModel(m_model); - //m_ui->listViewDisplacement->addAction(m_ui->actionAddTile); - //m_ui->listViewDisplacement->addAction(m_ui->actionDeleteTile); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -172,69 +168,11 @@ void TileEditorMainWindow::onTileSetAdd() //} //else //{ - // Create the new tile set. - QVector items; - items.push_back(text); - TileItem *tileSet = new TileItem(items); - // child for 128x128 tiles - QVector tiles128; - tiles128.push_back(QString("128")); - TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); - - // child for 256x256 tiles - QVector tiles256; - tiles256.push_back(QString("256")); - TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); - - - // child for transition tiles. - QVector tilesTrans; - tilesTrans.push_back(QString("Transition")); - TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); - - // Add the default transition tiles. - // TODO tie this to CTileSet::count from NeL - for(int transPos=0; transPos<48; transPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); - TileItem *transTile= new TileItem(tileInfo); - tileTrans->appendRow(transTile); - } - - // child for displacement tiles - QVector tilesDisp; - tilesDisp.push_back(QString("Displacement")); - TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); - - // Add the default displacement tiles. - // TODO tie this to CTileSet::CountDisplace from NeL - for(int dispPos=0; dispPos<16; dispPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); - TileItem *dispTile= new TileItem(tileInfo); - tileDisp->appendRow(dispTile); - } - - // Append them in the correct order to the tile set. - tileSet->appendRow(tile128); - tileSet->appendRow(tile256); - tileSet->appendRow(tileTrans); - tileSet->appendRow(tileDisp); - model->appendRow(tileSet); - - m_ui->tileSetLV->reset(); - //updateActions() - //} + TileSetNode *tileSet = model->createTileSetNode(text); - // tileBank.addTileSet( text.toStdString() ); - - // ui.tileSetListWidget->addItem(text); - // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); - //} + m_ui->tileSetLV->reset(); } } @@ -256,4 +194,9 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->listView256->setRootIndex(tile256Idx); m_ui->listViewTransition->setRootIndex(tileTransIdx); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); + + m_ui->listView128->reset(); + m_ui->listView256->reset(); + m_ui->listViewTransition->reset(); + m_ui->listViewDisplacement->reset(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index 5758b9280..289bc4a83 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -18,145 +18,213 @@ #include -TileItem::TileItem(const QVector &data, TileItem *parent) +Node::Node() : m_parentItem(0) { - parentItem = parent; - itemData = data; } -TileItem::~TileItem() +Node::Node(const QVector &data, Node *parent) { - qDeleteAll(childItems); + m_parentItem = parent; + m_itemData = data; } -void TileItem::appendChild(TileItem *item) +Node::~Node() { - childItems.append(item); + qDeleteAll(m_childItems); } -TileItem *TileItem::child(int row) +void Node::appendChild(Node *item) +{ + m_childItems.append(item); +} + +Node *Node::child(int row) { //nlinfo("row %d and size %d", row, childItems.size()); - return childItems.value(row); + return m_childItems.value(row); } -int TileItem::childCount() const +int Node::childCount() const { - return childItems.count(); + return m_childItems.count(); } -int TileItem::childNumber() const +int Node::childNumber() const { - if(parentItem) - return parentItem->childItems.indexOf(const_cast(this)); + if(m_parentItem) + return m_parentItem->m_childItems.indexOf(const_cast(this)); return 0; } -bool TileItem::insertChildren(int position, int count, int columns) +bool Node::insertChildren(int position, int count, int columns) { - if(position<0 || position>childItems.size()) + if(position<0 || position>m_childItems.size()) return false; for(int row = 0; row < count; row++) { QVector data(columns); - TileItem *item = new TileItem(data, this); - childItems.insert(position, item); + Node *item = new Node(data, this); + m_childItems.insert(position, item); } return true; } -bool TileItem::removeChildren(int position, int count) +bool Node::removeChildren(int position, int count) { - if(position<0 || position+count>childItems.size()) + if(position<0 || position+count>m_childItems.size()) return false; for(int row=0; row itemData.size()) + if(position<0 || position > m_itemData.size()) return false; for(int column=0; columninsertColumns(position, columns); return true; } -int TileItem::row() const +int Node::row() const { - if(parentItem) - return parentItem->childItems.indexOf(const_cast(this)); + if(m_parentItem) + return m_parentItem->m_childItems.indexOf(const_cast(this)); return 0; } -int TileItem::columnCount() const +int Node::columnCount() const { - return itemData.count(); + return m_itemData.count(); } -QVariant TileItem::data(int column) const +QVariant Node::data(int column) const { - return itemData.value(column); + return m_itemData.value(column); } -bool TileItem::setData(int column, const QVariant &value) +bool Node::setData(int column, const QVariant &value) { - if(column < 0 || column >= itemData.size()) + if(column < 0 || column >= m_itemData.size()) return false; - itemData[column] = value; + m_itemData[column] = value; return true; } -TileItem *TileItem::parent() +Node *Node::parent() { - return parentItem; + return m_parentItem; } -void TileItem::setParent(TileItem *parent) +void Node::setParent(Node *parent) { - parentItem = parent; + m_parentItem = parent; } -void TileItem::appendRow(const QList &items) +void Node::appendRow(const QList &items) { - Q_FOREACH(TileItem *item, items) + Q_FOREACH(Node *item, items) appendRow(item); } -void TileItem::appendRow(TileItem *item) +void Node::appendRow(Node *item) { item->setParent(this); - childItems.append(item); + m_childItems.append(item); } /////////////////////////////////////////////////// -TileTypeTileItem::TileTypeTileItem(const QVector &data, TileItem *parent) : TileItem(data,parent) +TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) +{ + m_parentItem = parent; +} + +TileSetNode::~TileSetNode() { + qDeleteAll(m_childItems); } -TileTypeTileItem::~TileTypeTileItem() +QVariant TileSetNode::data(int column) const { - qDeleteAll(childItems); + return QVariant(m_tileSetName); } -QVariant TileTypeTileItem::data(int column) const +/////////////////////////////////////////////////// + +TileTypeNode::TileTypeNode(TNodeTileType type, Node *parent) : m_nodeTileType(type) { - QVariant val = itemData.value(column); + m_parentItem = parent; +} + +TileTypeNode::~TileTypeNode() +{ + qDeleteAll(m_childItems); +} + +QVariant TileTypeNode::data(int column) const +{ + return QVariant(getTileTypeName(m_nodeTileType)); +} + +TileTypeNode::TNodeTileType TileTypeNode::getTileType() +{ + return m_nodeTileType; +} + - nlinfo("the column is %d and the value is '%s'. there are %d values", - column, val.toString().toStdString().c_str(), itemData.size()); - return itemData.value(column); -} \ No newline at end of file +const char *TileTypeNode::getTileTypeName(TNodeTileType type) +{ + switch(type) + { + case Tile128: + return "128"; + case Tile256: + return "256"; + case TileTransition: + return "Transition"; + case TileDisplacement: + return "Displacement"; + default: + break; + } + return "UNKNOWN"; +} + +/////////////////////////////////////////////////// + +TileItemNode::TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) +{ + m_tileFilename[channel] = filename; + m_parentItem = parent; + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); +} + +TileItemNode::~TileItemNode() +{ + qDeleteAll(m_childItems); +} + +void TileItemNode::setTileFilename(TTileChannel channel, QString filename) +{ + m_tileFilename[channel] = filename; +} + +QVariant TileItemNode::data(int column) const +{ + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); + // find some way to know which file/bitmap to display + return QVariant(m_tileFilename[TileDiffuse]); +} diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h index 8f1c6a61a..eceb38a79 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -22,54 +22,90 @@ #include #include -class TileItem +class Node { public: + Node(); + Node(const QVector &data, Node *parent=0); + virtual ~Node(); - TileItem(const QVector &data, TileItem *parent=0); - virtual ~TileItem(); + void appendChild(Node *child); - void appendChild(TileItem *child); - - TileItem *child(int row); + Node *child(int row); int childCount() const; int childNumber() const; int columnCount() const; bool setData(int column, const QVariant &value); - QVariant data(int column) const; + virtual QVariant data(int column) const; bool insertChildren(int position, int count, int columns); bool removeChildren(int position, int count); bool insertColumns(int position, int columns); int row() const; - TileItem *parent(); - void setParent(TileItem *parent); + Node *parent(); + void setParent(Node *parent); - void appendRow(const QList &items); - void appendRow(TileItem *item); + void appendRow(const QList &items); + void appendRow(Node *item); + +protected: + QList m_childItems; + QVector m_itemData; + Node *m_parentItem; +}; + +class TileSetNode : public Node +{ +public: + TileSetNode(QString tileSetName, Node *parent=0); + virtual ~TileSetNode(); + QVariant data(int column) const; - //QImage *getTileImageFromChannel(int channel); + const QString &getTileSetName(); +private: + QString m_tileSetName; +}; - //int getTileIndex() { return m_tileIndex; } - //QString getTileFilename() { return m_tileFilename; } +class TileTypeNode : public Node +{ +public: + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3 + }; + + TileTypeNode(TNodeTileType type, Node *parent=0); + virtual ~TileTypeNode(); + QVariant data(int column) const; -protected: - QList childItems; - QVector itemData; - TileItem *parentItem; + TNodeTileType getTileType(); - //QMap m_tileChannels; - //int m_tileIndex; - //QString m_tileFilename; + static const char *getTileTypeName(TNodeTileType type); +private: + TNodeTileType m_nodeTileType; }; -class TileTypeTileItem : public TileItem +class TileItemNode : public Node { public: - TileTypeTileItem(const QVector &data, TileItem *parent=0); - virtual ~TileTypeTileItem(); + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + }; + + TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent=0); + virtual ~TileItemNode(); QVariant data(int column) const; + void setTileFilename(TTileChannel channel, QString filename); +private: + int m_tileId; + QMap m_tileFilename; }; #endif // TILE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index 20911310c..d31289c21 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -25,7 +25,7 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte Q_FOREACH(QString header, headers) rootData << header; - rootItem = new TileItem(rootData); + rootItem = new Node(rootData); } TileModel::~TileModel() @@ -33,11 +33,11 @@ TileModel::~TileModel() delete rootItem; } -TileItem *TileModel::getItem(const QModelIndex &index) const +Node *TileModel::getItem(const QModelIndex &index) const { if(index.isValid()) { - TileItem *item = static_cast(index.internalPointer()); + Node *item = static_cast(index.internalPointer()); if(item) return item; } return rootItem; @@ -48,9 +48,9 @@ QModelIndex TileModel::index(int row, int column, const QModelIndex &parent) con if(parent.isValid() && parent.column() != 0) return QModelIndex(); - TileItem *parentItem = getItem(parent); + Node *parentItem = getItem(parent); - TileItem *childItem = parentItem->child(row); + Node *childItem = parentItem->child(row); if(childItem) return createIndex(row, column, childItem); else @@ -62,8 +62,8 @@ QModelIndex TileModel::parent(const QModelIndex &index) const if(!index.isValid()) return QModelIndex(); - TileItem *childItem = getItem(index); - TileItem *parentItem = childItem->parent(); + Node *childItem = getItem(index); + Node *parentItem = childItem->parent(); if(parentItem == rootItem) return QModelIndex(); @@ -73,13 +73,13 @@ QModelIndex TileModel::parent(const QModelIndex &index) const int TileModel::rowCount(const QModelIndex &parent) const { - TileItem *parentItem = getItem(parent); + Node *parentItem = getItem(parent); return parentItem->childCount(); } int TileModel::columnCount(const QModelIndex &parent) const { - TileItem *parentItem = getItem(parent); + Node *parentItem = getItem(parent); return parentItem->columnCount(); } @@ -91,7 +91,7 @@ QVariant TileModel::data(const QModelIndex &index, int role) const if(role != Qt::DisplayRole) return QVariant(); - TileItem *item = static_cast(index.internalPointer()); + Node *item = static_cast(index.internalPointer()); return item->data(index.column()); } @@ -111,13 +111,57 @@ QVariant TileModel::headerData(int section, Qt::Orientation orientation, int rol return QVariant(); } -void TileModel::appendRow(const QList &items) +void TileModel::appendRow(const QList &items) { rootItem->appendRow(items); } -void TileModel::appendRow(TileItem *item) +void TileModel::appendRow(Node *item) { rootItem->appendRow(item); +} + +TileSetNode *TileModel::createTileSetNode(QString tileSetName) +{ + // Create the new tile set. + TileSetNode *tileSet = new TileSetNode(tileSetName); + + // child for 128x128 tiles + TileTypeNode *tile128= new TileTypeNode(TileTypeNode::Tile128); + + // child for 256x256 tiles + TileTypeNode *tile256= new TileTypeNode(TileTypeNode::Tile256); + + // child for transition tiles. + TileTypeNode *tileTrans= new TileTypeNode(TileTypeNode::TileTransition); + + // Add the default transition tiles. + // TODO tie this to CTileSet::count from NeL + for(int transPos=0; transPos<48; transPos++) + { + TileItemNode *transTile= new TileItemNode(transPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(transPos+1))); + tileTrans->appendRow(transTile); + } + + // child for displacement tiles + TileTypeNode *tileDisp= new TileTypeNode(TileTypeNode::TileDisplacement); + + // Add the default displacement tiles. + // TODO tie this to CTileSet::CountDisplace from NeL + for(int dispPos=0; dispPos<16; dispPos++) + { + TileItemNode *dispTile= new TileItemNode(dispPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(dispPos+1))); + tileDisp->appendRow(dispTile); + } + + // Append them in the correct order to the tile set. + tileSet->appendRow(tile128); + tileSet->appendRow(tile256); + tileSet->appendRow(tileTrans); + tileSet->appendRow(tileDisp); + + this->appendRow(tileSet); + + return tileSet; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index 140f60555..fba135812 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -21,7 +21,8 @@ #include -class TileItem; +class Node; +class TileSetNode; class TileModel : public QAbstractItemModel { @@ -40,15 +41,17 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const; // Tile Model specific functions - void appendRow(const QList &items); - void appendRow(TileItem *item); + void appendRow(const QList &items); + void appendRow(Node *item); + + TileSetNode *createTileSetNode(QString tileSetName); private: - TileItem *getItem(const QModelIndex &index) const; + Node *getItem(const QModelIndex &index) const; //QList m_tiles; //int m_activeEditChannel; - TileItem *rootItem; + Node *rootItem; }; -#endif // TILE_128_MODEL_H +#endif // TILE_MODEL_H From 99ec1aab27429cf584bc849633a89ee0b277f5b4 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 30 Dec 2011 14:36:51 -0600 Subject: [PATCH 006/282] Changed: #1409 Added TileItemDelegate for rendering the icons at the correct size, adding tile set auto selects newest tile set, converted model items to accept role in their data for special handling, fixed column count bug, moved important enums centrally to TileModel. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 43 ++++-- .../tile_editor/tile_editor_main_window.h | 2 + .../tile_editor/tile_editor_main_window.ui | 72 ++++++++++ .../src/plugins/tile_editor/tile_item.cpp | 124 +++++++++++++----- .../src/plugins/tile_editor/tile_item.h | 48 +++---- .../tile_editor/tile_item_delegate.cpp | 98 ++++++++++++++ .../plugins/tile_editor/tile_item_delegate.h | 53 ++++++++ .../src/plugins/tile_editor/tile_model.cpp | 66 +++++++--- .../src/plugins/tile_editor/tile_model.h | 26 ++++ 9 files changed, 444 insertions(+), 88 deletions(-) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 427fda7a9..301f3564a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -30,6 +30,7 @@ #include "tile_model.h" #include "tile_item.h" +#include "tile_item_delegate.h" TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), @@ -72,6 +73,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) QStringList headers; headers << "Tile Set"; m_model = new TileModel(headers, this); + m_tileItemDelegate = new TileItemDelegate(); // Set up the tile set list view. m_ui->tileSetLV->setModel(m_model); @@ -82,6 +84,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View + m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->setModel(m_model); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); @@ -89,6 +92,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView128->addAction(m_ui->actionDeleteImage); // 256x256 List View + m_ui->listView256->setItemDelegate(m_tileItemDelegate); m_ui->listView256->setModel(m_model); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); @@ -96,14 +100,17 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView256->addAction(m_ui->actionDeleteImage); // Transition List View + m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); m_ui->listViewTransition->setModel(m_model); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View + m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); m_ui->listViewDisplacement->setModel(m_model); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); + // Connect context menu actions up. connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); @@ -168,11 +175,15 @@ void TileEditorMainWindow::onTileSetAdd() //} //else //{ - - + + + // Create and append the new tile set to the model. TileSetNode *tileSet = model->createTileSetNode(text); - + + // Retrieve how many rows there currently are and set the current index using that. m_ui->tileSetLV->reset(); + uint32 rows = model->rowCount(); + m_ui->tileSetLV->setCurrentIndex(model->index(rows-1, 0)); } } @@ -180,23 +191,31 @@ void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; QString selectedFilter; - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "PNG Bitmap(*.png);;All Files (*.*);;", &selectedFilter, options); + QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); } void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { - const QModelIndex &tile128Idx = newIndex.child(0,0); - const QModelIndex &tile256Idx = newIndex.child(1,0); - const QModelIndex &tileTransIdx = newIndex.child(2,0); - const QModelIndex &tileDispIdx = newIndex.child(3,0); + TileModel *model = static_cast(m_ui->tileSetLV->model()); + + QModelIndex tile128Idx = model->index(0, 0, newIndex); + QModelIndex tile256Idx = model->index(1, 0, newIndex); + QModelIndex tileTransIdx = model->index(2, 0, newIndex); + QModelIndex tileDispIdx = model->index(3, 0, newIndex); m_ui->listView128->setRootIndex(tile128Idx); + m_ui->listView128->setCurrentIndex(m_ui->listView128->model()->index(0, 0, m_ui->listView128->rootIndex())); m_ui->listView256->setRootIndex(tile256Idx); + m_ui->listView256->setCurrentIndex(m_ui->listView256->model()->index(0, 0, m_ui->listView256->rootIndex())); m_ui->listViewTransition->setRootIndex(tileTransIdx); + m_ui->listViewTransition->setCurrentIndex(m_ui->listViewTransition->model()->index(0, 0, m_ui->listViewTransition->rootIndex())); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); + m_ui->listViewDisplacement->setCurrentIndex(m_ui->listViewDisplacement->model()->index(0, 0, m_ui->listViewDisplacement->rootIndex())); + + //nlinfo("number of rows in displacement: %d", tileDispIdx.model()->rowCount(tileDispIdx)); - m_ui->listView128->reset(); - m_ui->listView256->reset(); - m_ui->listViewTransition->reset(); - m_ui->listViewDisplacement->reset(); + //m_ui->listView128->reset(); + //m_ui->listView256->reset(); + //m_ui->listViewTransition->reset(); + //m_ui->listViewDisplacement->reset(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 267eff50c..93cde3d8f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -29,6 +29,7 @@ namespace Ui { } class TileModel; +class TileItemDelegate; class TileEditorMainWindow : public QMainWindow { @@ -59,6 +60,7 @@ private: QMenu *m_tileEditorMenu; TileModel *m_model; + TileItemDelegate *m_tileItemDelegate; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index 5897d29be..a7130bf9d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -30,6 +30,24 @@ Qt::ActionsContextMenu + + + 128 + 128 + + + + QListView::LeftToRight + + + true + + + QListView::IconMode + + + true + @@ -70,6 +88,24 @@ Qt::ActionsContextMenu + + + 256 + 256 + + + + QListView::LeftToRight + + + true + + + QListView::IconMode + + + true + @@ -113,12 +149,27 @@ Qt::ActionsContextMenu + + + 64 + 64 + + QListView::LeftToRight + + true + QListView::Batched + + QListView::IconMode + + + false + @@ -166,6 +217,27 @@ Qt::ActionsContextMenu + + + 32 + 32 + + + + QListView::LeftToRight + + + true + + + QListView::Fixed + + + QListView::IconMode + + + false + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index 289bc4a83..04b044382 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -14,8 +14,12 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +#include + #include "tile_item.h" +//#include "tile_widget.h" + #include Node::Node() : m_parentItem(0) @@ -109,9 +113,11 @@ int Node::columnCount() const return m_itemData.count(); } -QVariant Node::data(int column) const +QVariant Node::data(int column, int role) const { - return m_itemData.value(column); + if(role == Qt::DisplayRole) + return m_itemData.value(column); + return QVariant(); } bool Node::setData(int column, const QVariant &value) @@ -157,14 +163,21 @@ TileSetNode::~TileSetNode() qDeleteAll(m_childItems); } -QVariant TileSetNode::data(int column) const +QVariant TileSetNode::data(int column, int role) const +{ + if(role == Qt::DisplayRole) + return QVariant(m_tileSetName); + return QVariant(); +} + +int TileSetNode::columnCount() const { - return QVariant(m_tileSetName); + return 1; } /////////////////////////////////////////////////// -TileTypeNode::TileTypeNode(TNodeTileType type, Node *parent) : m_nodeTileType(type) +TileTypeNode::TileTypeNode(TileModel::TNodeTileType type, Node *parent) : m_nodeTileType(type) { m_parentItem = parent; } @@ -174,42 +187,34 @@ TileTypeNode::~TileTypeNode() qDeleteAll(m_childItems); } -QVariant TileTypeNode::data(int column) const +QVariant TileTypeNode::data(int column, int role) const { - return QVariant(getTileTypeName(m_nodeTileType)); + if(role == Qt::DisplayRole) + return QVariant(TileModel::getTileTypeName(m_nodeTileType)); + return QVariant(); + } -TileTypeNode::TNodeTileType TileTypeNode::getTileType() +int TileTypeNode::columnCount() const { - return m_nodeTileType; + return 1; } - -const char *TileTypeNode::getTileTypeName(TNodeTileType type) +TileModel::TNodeTileType TileTypeNode::getTileType() { - switch(type) - { - case Tile128: - return "128"; - case Tile256: - return "256"; - case TileTransition: - return "Transition"; - case TileDisplacement: - return "Displacement"; - default: - break; - } - return "UNKNOWN"; + return m_nodeTileType; } + + + /////////////////////////////////////////////////// -TileItemNode::TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) +TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) { m_tileFilename[channel] = filename; m_parentItem = parent; - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); } TileItemNode::~TileItemNode() @@ -217,14 +222,71 @@ TileItemNode::~TileItemNode() qDeleteAll(m_childItems); } -void TileItemNode::setTileFilename(TTileChannel channel, QString filename) +void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) { m_tileFilename[channel] = filename; } -QVariant TileItemNode::data(int column) const +QVariant TileItemNode::data(int column, int role) const { - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); + + + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); // find some way to know which file/bitmap to display - return QVariant(m_tileFilename[TileDiffuse]); + QString tileFilename = m_tileFilename[TileModel::TileDiffuse]; + //TileWidget *tile = m_tileWidget[TileModel::TileDiffuse]; + + // + // + // return QVariant(); + + //if(tile == NULL) + //{ + // + // + + // // Create a new tile widget. + // tile = new TileWidget(); + // tile->initWidget(tileFilename, tileFilename, tileSize); + //} + + if(role == TileModel::TilePixmapRole) + { + TileTypeNode *parent = dynamic_cast(m_parentItem); + if(parent == NULL) + return QVariant(); + + // Retrieve the target tile size. + uint32 tileSize = TileModel::getTileTypeSize(parent->getTileType()); + + if(tileFilename.isEmpty() || tileFilename == "empty") + tileFilename = ":/placeHolder/images/empty_image.png"; + + QPixmap pixmap;// = new QPixmap(); + if(!pixmap.load(tileFilename)) + nlinfo("failed to load %s", tileFilename.toStdString().c_str()); + + //pixmap.scaled(tileSize*100, tileSize*100); + + return pixmap; + } + else if(role == TileModel::TileFilenameRole) + { + return QVariant(tileFilename); + } + else if(role == TileModel::TileIndexRole) + { + return QVariant(tileFilename); + } + /*else if(role == Qt::TextAlignmentRole) + { + return QVariant(Qt::AlignHCenter|Qt::AlignVCenter); + }*/ + + return QVariant(); } + +int TileItemNode::columnCount() const +{ + return 1; +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h index eceb38a79..f89b20ab7 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -22,6 +22,10 @@ #include #include +#include "tile_model.h" + +class TileWidget; + class Node { public: @@ -34,9 +38,9 @@ public: Node *child(int row); int childCount() const; int childNumber() const; - int columnCount() const; + virtual int columnCount() const; bool setData(int column, const QVariant &value); - virtual QVariant data(int column) const; + virtual QVariant data(int column, int role) const; bool insertChildren(int position, int count, int columns); bool removeChildren(int position, int count); @@ -60,7 +64,8 @@ class TileSetNode : public Node public: TileSetNode(QString tileSetName, Node *parent=0); virtual ~TileSetNode(); - QVariant data(int column) const; + QVariant data(int column, int role) const; + int columnCount() const; const QString &getTileSetName(); private: @@ -70,42 +75,29 @@ private: class TileTypeNode : public Node { public: - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3 - }; - - TileTypeNode(TNodeTileType type, Node *parent=0); - virtual ~TileTypeNode(); - QVariant data(int column) const; - TNodeTileType getTileType(); + TileTypeNode(TileModel::TNodeTileType type, Node *parent=0); + virtual ~TileTypeNode(); + QVariant data(int column, int role) const; + int columnCount() const; - static const char *getTileTypeName(TNodeTileType type); + TileModel::TNodeTileType getTileType(); private: - TNodeTileType m_nodeTileType; + TileModel::TNodeTileType m_nodeTileType; }; class TileItemNode : public Node { public: - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - }; - - TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent=0); + TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); virtual ~TileItemNode(); - QVariant data(int column) const; - void setTileFilename(TTileChannel channel, QString filename); + QVariant data(int column, int role) const; + int columnCount() const; + void setTileFilename(TileModel::TTileChannel channel, QString filename); private: int m_tileId; - QMap m_tileFilename; + QMap m_tileFilename; + QMap m_tileWidget; }; #endif // TILE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp new file mode 100644 index 000000000..f689ff83e --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp @@ -0,0 +1,98 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include + +#include + +#include "tile_item_delegate.h" + +#include "tile_model.h" + +TileItemDelegate::TileItemDelegate() +{ + m_zoomFactor = ZoomNormal; +} + +TileItemDelegate::~TileItemDelegate() +{ +} + +void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyledItemDelegate::paint(painter,option,index); + + painter->save(); + + QFont font = QApplication::font(); + QFont SubFont = QApplication::font(); + //font.setPixelSize(font.weight()+); + font.setBold(true); + SubFont.setWeight(SubFont.weight()-2); + QFontMetrics fm(font); + + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + QString headerText = qvariant_cast(index.data(TileModel::TileFilenameRole)); + QString subText = qvariant_cast(index.data(TileModel::TileIndexRole)); + + QSize tileSize = tile.size(); + + QRect headerRect = option.rect; + QRect subheaderRect = option.rect; + QRect tileRect = subheaderRect; + + tileRect.setRight(tileSize.width()+30); + tileRect.setTop(tileRect.top()+5); + headerRect.setLeft(tileRect.right()); + subheaderRect.setLeft(tileRect.right()); + headerRect.setTop(headerRect.top()+5); + headerRect.setBottom(headerRect.top()+fm.height()); + + subheaderRect.setTop(headerRect.bottom()+2); + + + //painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); + painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); + + painter->setFont(font); + painter->drawText(headerRect,headerText); + + + painter->setFont(SubFont); + painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); + + painter->restore(); +} + +QSize TileItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + QSize tileSize = tile.size();//tile.actualSize(option.decorationSize); + QFont font = QApplication::font(); + QFontMetrics fm(font); + + return(QSize(tileSize.width(), tileSize.height()+fm.height()+8 )); +} + +TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() +{ + return m_zoomFactor; +} + +void TileItemDelegate::setZoomFactor(TileItemDelegate::TZoomFactor zoomFactor) +{ + m_zoomFactor = zoomFactor; +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h new file mode 100644 index 000000000..b87a17344 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h @@ -0,0 +1,53 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +#ifndef TILE_ITEM_DELEGATE_H +#define TILE_ITEM_DELEGATE_H + +#include +#include +#include + +#include "ui_tile_widget.h" + +#include + +class TileItemDelegate : public QStyledItemDelegate + { + public: + + enum TZoomFactor + { + ZoomSmall = 0, + ZoomNormal = 1, + ZoomLarge = 2 + }; + + static const int PIXMAP_MARGIN = 5; + + TileItemDelegate(); + virtual ~TileItemDelegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const; + + TZoomFactor getZoomFactor(); + void setZoomFactor(TZoomFactor zoomFactor); + + private: + TZoomFactor m_zoomFactor; + }; + +#endif // TILE_ITEM_DELEGATE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index d31289c21..19fa9409f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -88,11 +88,8 @@ QVariant TileModel::data(const QModelIndex &index, int role) const if(!index.isValid()) return QVariant(); - if(role != Qt::DisplayRole) - return QVariant(); - Node *item = static_cast(index.internalPointer()); - return item->data(index.column()); + return item->data(index.column(), role); } Qt::ItemFlags TileModel::flags(const QModelIndex &index) const @@ -106,7 +103,7 @@ Qt::ItemFlags TileModel::flags(const QModelIndex &index) const QVariant TileModel::headerData(int section, Qt::Orientation orientation, int role) const { if(orientation == Qt::Horizontal && role == Qt::DisplayRole) - return rootItem->data(section); + return rootItem->data(section,role); return QVariant(); } @@ -128,40 +125,75 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) TileSetNode *tileSet = new TileSetNode(tileSetName); // child for 128x128 tiles - TileTypeNode *tile128= new TileTypeNode(TileTypeNode::Tile128); - + TileTypeNode *tile128= new TileTypeNode(Tile128); + tileSet->appendRow(tile128); + // child for 256x256 tiles - TileTypeNode *tile256= new TileTypeNode(TileTypeNode::Tile256); + TileTypeNode *tile256= new TileTypeNode(Tile256); + tileSet->appendRow(tile256); // child for transition tiles. - TileTypeNode *tileTrans= new TileTypeNode(TileTypeNode::TileTransition); + TileTypeNode *tileTrans= new TileTypeNode(TileTransition); + tileSet->appendRow(tileTrans); // Add the default transition tiles. // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode(transPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(transPos+1))); + TileItemNode *transTile= new TileItemNode(transPos, TileDiffuse, QString("empty")); tileTrans->appendRow(transTile); } // child for displacement tiles - TileTypeNode *tileDisp= new TileTypeNode(TileTypeNode::TileDisplacement); + TileTypeNode *tileDisp= new TileTypeNode(TileDisplacement); + tileSet->appendRow(tileDisp); // Add the default displacement tiles. // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode(dispPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(dispPos+1))); + TileItemNode *dispTile= new TileItemNode(dispPos, TileDiffuse, QString("empty")); tileDisp->appendRow(dispTile); } // Append them in the correct order to the tile set. - tileSet->appendRow(tile128); - tileSet->appendRow(tile256); - tileSet->appendRow(tileTrans); - tileSet->appendRow(tileDisp); - this->appendRow(tileSet); return tileSet; +} + +const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) +{ + switch(type) + { + case Tile128: + return "128"; + case Tile256: + return "256"; + case TileTransition: + return "Transition"; + case TileDisplacement: + return "Displacement"; + default: + break; + } + return "UNKNOWN"; +} + +uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) +{ + switch(type) + { + case Tile128: + return 128; + case Tile256: + return 256; + case TileTransition: + return 64; + case TileDisplacement: + return 32; + default: + break; + } + return 0; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index fba135812..aea6461b1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -29,6 +29,29 @@ class TileModel : public QAbstractItemModel Q_OBJECT public: + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3 + }; + + enum TTileItemRole + { + TilePixmapRole = Qt::UserRole+1, + TileFilenameRole = Qt::UserRole+2, + TileIndexRole = Qt::UserRole+3 + }; + + TileModel(const QStringList &headers, QObject *parent); ~TileModel(); @@ -46,6 +69,9 @@ public: TileSetNode *createTileSetNode(QString tileSetName); + static const char *getTileTypeName(TNodeTileType type); + static uint32 getTileTypeSize(TileModel::TNodeTileType type); + private: Node *getItem(const QModelIndex &index) const; From f6f664452dbfb8dff05be01605c074d64480e353 Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 27 Feb 2012 08:40:23 -0600 Subject: [PATCH 007/282] Changed: #1409 Removing the tile item delegate, modifying the model with custom roles for view modes. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 41 +++++++++-- .../tile_editor/tile_editor_main_window.h | 9 ++- .../tile_editor/tile_editor_main_window.ui | 40 ++++++++++- .../src/plugins/tile_editor/tile_item.cpp | 49 ++++++------- .../tile_editor/tile_item_delegate.cpp | 70 +++++++++++++------ .../plugins/tile_editor/tile_item_delegate.h | 4 ++ .../src/plugins/tile_editor/tile_model.cpp | 51 ++++++++++++++ .../src/plugins/tile_editor/tile_model.h | 19 ++++- 8 files changed, 223 insertions(+), 60 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 301f3564a..c367addbe 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -43,7 +43,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - QMenu *m_tileEditorMenu; // Create tile rotation drop down toolbar menu. m_rotationMenu = new QMenu(tr("Rotate Tile"), m_ui->toolBar); m_rotationMenu->setIcon(QIcon(":/tileRotation/images/rotation0.png")); @@ -57,7 +56,17 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Create the tile zoom menu. m_zoomMenu = new QMenu(tr("Zoom"), m_ui->toolBar); + m_zoomActionGroup = new QActionGroup(this); + m_zoomSignalMapper = new QSignalMapper(this); QList zoomActions; + zoomActions.push_back(m_ui->actionZoom50); + zoomActions.push_back(m_ui->actionZoom100); + zoomActions.push_back(m_ui->actionZoom200); + m_zoomActionGroup->addAction(m_ui->actionZoom50); + m_zoomActionGroup->addAction(m_ui->actionZoom100); + m_zoomActionGroup->addAction(m_ui->actionZoom200); + m_zoomMenu->addActions(zoomActions); + m_ui->toolBar->addAction(m_zoomMenu->menuAction()); m_tileEditorMenu = new QMenu(tr("Tile Editor"), core->menuManager()->menuBar()); m_tileDisplayMenu = new QMenu(tr("Tile Display"), m_ui->toolBar); @@ -84,7 +93,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View - m_ui->listView128->setItemDelegate(m_tileItemDelegate); + //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->setModel(m_model); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); @@ -92,7 +101,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView128->addAction(m_ui->actionDeleteImage); // 256x256 List View - m_ui->listView256->setItemDelegate(m_tileItemDelegate); + //m_ui->listView256->setItemDelegate(m_tileItemDelegate); m_ui->listView256->setModel(m_model); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); @@ -100,13 +109,13 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView256->addAction(m_ui->actionDeleteImage); // Transition List View - m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); + //m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); m_ui->listViewTransition->setModel(m_model); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View - m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); + //m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); m_ui->listViewDisplacement->setModel(m_model); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -117,6 +126,20 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionDeleteTile, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteTile(bool))); connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); + + connect(m_ui->actionTileDisplayFilename, SIGNAL(toggled(bool)), m_model, SLOT(selectFilenameDisplay(bool))); + connect(m_ui->actionTileDisplayIndex, SIGNAL(toggled(bool)), m_model, SLOT(selectIndexDisplay(bool))); + + //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); + + // Connect the zoom buttons. + connect(m_ui->actionZoom50, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); + m_zoomSignalMapper->setMapping(m_ui->actionZoom50, 0); + connect(m_ui->actionZoom100, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); + m_zoomSignalMapper->setMapping(m_ui->actionZoom100, 1); + connect(m_ui->actionZoom200, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); + m_zoomSignalMapper->setMapping(m_ui->actionZoom200, 2); + connect(m_zoomSignalMapper, SIGNAL(mapped(int)), m_model, SLOT(onZoomFactor(int))); } TileEditorMainWindow::~TileEditorMainWindow() @@ -125,6 +148,14 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_undoStack; delete m_rotationMenu; delete m_zoomMenu; + + + delete m_tileDisplayMenu; + delete m_tileEditorMenu; + + delete m_zoomMenu; + delete m_zoomActionGroup; + delete m_zoomSignalMapper; } void TileEditorMainWindow::onActionAddTile(bool triggered) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 93cde3d8f..8233d16d3 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -23,6 +23,7 @@ #include "nel/misc/sheet_id.h" #include +#include namespace Ui { class TileEditorMainWindow; @@ -47,7 +48,7 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); - void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); private: void onActionAddTile(int tabId); @@ -55,10 +56,14 @@ private: Ui::TileEditorMainWindow *m_ui; QUndoStack *m_undoStack; QMenu *m_rotationMenu; - QMenu *m_zoomMenu; + QMenu *m_tileDisplayMenu; QMenu *m_tileEditorMenu; + QMenu *m_zoomMenu; + QActionGroup *m_zoomActionGroup; + QSignalMapper *m_zoomSignalMapper; + TileModel *m_model; TileItemDelegate *m_tileItemDelegate; }; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index a7130bf9d..7bf82ca05 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -161,14 +161,17 @@ true + + QListView::Adjust + - QListView::Batched + QListView::SinglePass QListView::IconMode - false + true @@ -678,6 +681,9 @@ true + + true + Index @@ -689,6 +695,9 @@ true + + true + Filename @@ -744,6 +753,33 @@ Delete Image + + + true + + + Zoom 50% + + + + + true + + + true + + + Zoom 100% + + + + + true + + + Zoom 200% + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index 04b044382..adf381dc0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -115,7 +115,10 @@ int Node::columnCount() const QVariant Node::data(int column, int role) const { - if(role == Qt::DisplayRole) + if(role == Qt::DisplayRole || + role == TileModel::TileFilenameIndexRole || + role == TileModel::TileFilenameRole || + role == TileModel::TileIndexRole) return m_itemData.value(column); return QVariant(); } @@ -165,7 +168,10 @@ TileSetNode::~TileSetNode() QVariant TileSetNode::data(int column, int role) const { - if(role == Qt::DisplayRole) + if(role == Qt::DisplayRole || + role == TileModel::TileFilenameIndexRole || + role == TileModel::TileFilenameRole || + role == TileModel::TileIndexRole) return QVariant(m_tileSetName); return QVariant(); } @@ -189,7 +195,10 @@ TileTypeNode::~TileTypeNode() QVariant TileTypeNode::data(int column, int role) const { - if(role == Qt::DisplayRole) + if(role == Qt::DisplayRole || + role == TileModel::TileFilenameIndexRole || + role == TileModel::TileFilenameRole || + role == TileModel::TileIndexRole) return QVariant(TileModel::getTileTypeName(m_nodeTileType)); return QVariant(); @@ -228,29 +237,11 @@ void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file } QVariant TileItemNode::data(int column, int role) const -{ - - - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); +{ // find some way to know which file/bitmap to display QString tileFilename = m_tileFilename[TileModel::TileDiffuse]; - //TileWidget *tile = m_tileWidget[TileModel::TileDiffuse]; - - // - // - // return QVariant(); - - //if(tile == NULL) - //{ - // - // - // // Create a new tile widget. - // tile = new TileWidget(); - // tile->initWidget(tileFilename, tileFilename, tileSize); - //} - - if(role == TileModel::TilePixmapRole) + if(role == TileModel::TilePixmapRole || role == Qt::DecorationRole) { TileTypeNode *parent = dynamic_cast(m_parentItem); if(parent == NULL) @@ -270,18 +261,22 @@ QVariant TileItemNode::data(int column, int role) const return pixmap; } + else if(role == Qt::DisplayRole) + { + return QVariant(tileFilename); + } else if(role == TileModel::TileFilenameRole) { return QVariant(tileFilename); } else if(role == TileModel::TileIndexRole) { - return QVariant(tileFilename); + return QVariant("("+QString::number(m_tileId)+")"); } - /*else if(role == Qt::TextAlignmentRole) + else if(role == TileModel::TileFilenameIndexRole) { - return QVariant(Qt::AlignHCenter|Qt::AlignVCenter); - }*/ + return QVariant(tileFilename + " ("+QString::number(m_tileId)+")"); + } return QVariant(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp index f689ff83e..43751d612 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp @@ -25,6 +25,7 @@ TileItemDelegate::TileItemDelegate() { m_zoomFactor = ZoomNormal; + m_imageHint = 128; } TileItemDelegate::~TileItemDelegate() @@ -38,41 +39,48 @@ void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti painter->save(); QFont font = QApplication::font(); - QFont SubFont = QApplication::font(); - //font.setPixelSize(font.weight()+); - font.setBold(true); - SubFont.setWeight(SubFont.weight()-2); + + //font.setBold(true); + //SubFont.setWeight(SubFont.weight()-2); QFontMetrics fm(font); QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - QString headerText = qvariant_cast(index.data(TileModel::TileFilenameRole)); - QString subText = qvariant_cast(index.data(TileModel::TileIndexRole)); + QString tileFileText = qvariant_cast(index.data(TileModel::TileFilenameRole)); + QString tileIdText = qvariant_cast(index.data(TileModel::TileIndexRole)); QSize tileSize = tile.size(); - QRect headerRect = option.rect; - QRect subheaderRect = option.rect; - QRect tileRect = subheaderRect; + //QRect headerRect = option.rect; + QRect rect(option.rect); + //QRect tileRect(option.rect); + int textHeight = fm.height(); + int iconPosModX = PIXMAP_MARGIN + (tile.width() / 2); + int iconPosModY = (option.rect.height() - tile.height()) / 2; + + painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); + - tileRect.setRight(tileSize.width()+30); - tileRect.setTop(tileRect.top()+5); - headerRect.setLeft(tileRect.right()); - subheaderRect.setLeft(tileRect.right()); - headerRect.setTop(headerRect.top()+5); - headerRect.setBottom(headerRect.top()+fm.height()); - subheaderRect.setTop(headerRect.bottom()+2); + //tileRect.setRight(tileSize.width()+30); + //tileRect.setTop(tileRect.top()+5); + //headerRect.setLeft(tileRect.right()); + //subheaderRect.setLeft(tileRect.right()); + //headerRect.setTop(headerRect.top()+5); + //headerRect.setBottom(headerRect.top()+fm.height()); + + //subheaderRect.setTop(headerRect.bottom()+2); + //painter->drawPixmap(targetrect, pixmap, sourcerect) //painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); - painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); + //painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); - painter->setFont(font); - painter->drawText(headerRect,headerText); + //painter->setFont(font); + //painter->drawText(headerRect,headerText); - painter->setFont(SubFont); - painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); + //painter->setFont(SubFont); + //painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); painter->restore(); } @@ -80,11 +88,11 @@ void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti QSize TileItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const { QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - QSize tileSize = tile.size();//tile.actualSize(option.decorationSize); + QSize tileSize = tile.size(); QFont font = QApplication::font(); QFontMetrics fm(font); - return(QSize(tileSize.width(), tileSize.height()+fm.height()+8 )); + return(QSize(tileSize.width()+(2*PIXMAP_MARGIN), tileSize.height()+fm.height()+(2*PIXMAP_MARGIN))); } TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() @@ -95,4 +103,20 @@ TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() void TileItemDelegate::setZoomFactor(TileItemDelegate::TZoomFactor zoomFactor) { m_zoomFactor = zoomFactor; +} + +// SLOTS + +void TileItemDelegate::currentTab(int index) +{ + if(index == 1) + { + nlinfo("switching delegate to 1 or 256"); + m_imageHint = 256; + } + else + { + nlinfo("switching delegate to 0,2,3 or 128"); + m_imageHint = 128; + } } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h index b87a17344..1b7058b48 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h @@ -46,8 +46,12 @@ class TileItemDelegate : public QStyledItemDelegate TZoomFactor getZoomFactor(); void setZoomFactor(TZoomFactor zoomFactor); +public Q_SLOTS: + void currentTab(int index); + private: TZoomFactor m_zoomFactor; + int m_imageHint; }; #endif // TILE_ITEM_DELEGATE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index 19fa9409f..cd5c1c4ce 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -19,6 +19,8 @@ #include +#include + TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) { QVector rootData; @@ -26,6 +28,10 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte rootData << header; rootItem = new Node(rootData); + + m_tileZoomFactor = TileZoom100; + m_indexDisplay = true; + m_fileDisplay = true; } TileModel::~TileModel() @@ -89,6 +95,18 @@ QVariant TileModel::data(const QModelIndex &index, int role) const return QVariant(); Node *item = static_cast(index.internalPointer()); + + // Translate the display role to the settings-specific role. + + if(role == Qt::DisplayRole) + { + if(m_indexDisplay && m_fileDisplay) + role = TileFilenameIndexRole; + else if(m_fileDisplay) + role = TileFilenameRole; + else if(m_indexDisplay) + role = TileIndexRole; + } return item->data(index.column(), role); } @@ -196,4 +214,37 @@ uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) break; } return 0; +} + +void TileModel::selectFilenameDisplay(bool selected) +{ + m_fileDisplay = selected; +} + +void TileModel::selectIndexDisplay(bool selected) +{ + m_indexDisplay = selected; +} + +void TileModel::onZoomFactor(int level) +{ + switch(level) + { + // Zoom Level 50% + case 0: + nlinfo("zooming to 50%"); + m_tileZoomFactor = TileZoom50; + break; + case 1: + nlinfo("zooming to 100%"); + m_tileZoomFactor = TileZoom100; + break; + case 2: + nlinfo("zooming to 200%"); + m_tileZoomFactor = TileZoom200; + break; + default: + nlwarning("Invalid Time Zoom Factor passed."); + break; + }; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index aea6461b1..e9884cd61 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -48,7 +48,15 @@ public: { TilePixmapRole = Qt::UserRole+1, TileFilenameRole = Qt::UserRole+2, - TileIndexRole = Qt::UserRole+3 + TileIndexRole = Qt::UserRole+3, + TileFilenameIndexRole = Qt::UserRole+4 + }; + + enum TTileZoomFactor + { + TileZoom50 = 0, + TileZoom100 = 1, + TileZoom200 = 2 }; @@ -72,9 +80,18 @@ public: static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); +public Q_SLOTS: + void selectFilenameDisplay(bool selected); + void selectIndexDisplay(bool selected); + void onZoomFactor(int level); + private: Node *getItem(const QModelIndex &index) const; + bool m_fileDisplay; + bool m_indexDisplay; + TTileZoomFactor m_tileZoomFactor; + //QList m_tiles; //int m_activeEditChannel; Node *rootItem; From 5eb9d2f2a0984b404f8708bb1bab242f9fda7893 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 2 Mar 2012 14:17:38 -0600 Subject: [PATCH 008/282] Changed: #1409 Adding zoom functionality to views, trying to fix icon size problem. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 49 ++++++++++++++++++- .../tile_editor/tile_editor_main_window.h | 5 +- .../tile_editor/tile_editor_main_window.ui | 6 +++ .../src/plugins/tile_editor/tile_item.cpp | 9 +++- .../src/plugins/tile_editor/tile_model.cpp | 28 ++--------- .../src/plugins/tile_editor/tile_model.h | 12 +++-- 6 files changed, 77 insertions(+), 32 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index c367addbe..930ae9d8b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -139,7 +139,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_zoomSignalMapper->setMapping(m_ui->actionZoom100, 1); connect(m_ui->actionZoom200, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); m_zoomSignalMapper->setMapping(m_ui->actionZoom200, 2); - connect(m_zoomSignalMapper, SIGNAL(mapped(int)), m_model, SLOT(onZoomFactor(int))); + connect(m_zoomSignalMapper, SIGNAL(mapped(int)), this, SLOT(onZoomFactor(int))); } TileEditorMainWindow::~TileEditorMainWindow() @@ -158,6 +158,53 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_zoomSignalMapper; } +void TileEditorMainWindow::onZoomFactor(int level) +{ + int tile128Scaled=TileModel::TILE_128_BASE_SIZE; + int tile256Scaled=TileModel::TILE_256_BASE_SIZE; + int tileTransScaled=TileModel::TILE_TRANSITION_BASE_SIZE; + int tileDispScaled=TileModel::TILE_DISPLACE_BASE_SIZE; + switch(level) + { + // Zoom Level 50% + case 0: + nlinfo("zooming to 50%"); + TileModel::CurrentZoomFactor = TileModel::TileZoom50; + tile128Scaled /= 2; + tile256Scaled /= 2; + tileTransScaled /= 2; + tileDispScaled /= 2; + break; + case 1: + nlinfo("zooming to 100%"); + TileModel::CurrentZoomFactor = TileModel::TileZoom100; + break; + case 2: + nlinfo("zooming to 200%"); + TileModel::CurrentZoomFactor = TileModel::TileZoom200; + tile128Scaled *= 2; + tile256Scaled *= 2; + tileTransScaled *= 2; + tileDispScaled *= 2; + break; + default: + nlwarning("Invalid Time Zoom Factor passed."); + break; + }; + + nlinfo("resizing transition view. base size: %d factor %d to: %d", TileModel::TILE_TRANSITION_BASE_SIZE, level, tileTransScaled); + + m_ui->listView128->setIconSize(QSize(tile128Scaled, tile128Scaled)); + m_ui->listView128->setCurrentIndex(m_ui->listView128->model()->index(0, 0, m_ui->listView128->rootIndex())); + m_ui->listView256->setIconSize(QSize(tile256Scaled, tile256Scaled)); + m_ui->listView256->setCurrentIndex(m_ui->listView256->model()->index(0, 0, m_ui->listView256->rootIndex())); + m_ui->listViewTransition->setIconSize(QSize(tileTransScaled, tileTransScaled)); + m_ui->listViewTransition->setCurrentIndex(m_ui->listViewTransition->model()->index(0, 0, m_ui->listViewTransition->rootIndex())); + m_ui->listViewDisplacement->setIconSize(QSize(tileDispScaled, tileDispScaled)); + m_ui->listViewDisplacement->setCurrentIndex(m_ui->listViewDisplacement->model()->index(0, 0, m_ui->listViewDisplacement->rootIndex())); + m_ui->listViewTransition->repaint(); +} + void TileEditorMainWindow::onActionAddTile(bool triggered) { onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 8233d16d3..ae3520465 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -40,7 +40,7 @@ public: explicit TileEditorMainWindow(QWidget *parent = 0); ~TileEditorMainWindow(); - QUndoStack *getUndoStack() { return m_undoStack; } + QUndoStack *getUndoStack() { return m_undoStack; } public Q_SLOTS: void onActionAddTile(bool triggered); @@ -48,7 +48,8 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); - void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); + void onZoomFactor(int level); private: void onActionAddTile(int tabId); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index 7bf82ca05..66a086179 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -155,6 +155,9 @@ 64 + + QListView::Static + QListView::LeftToRight @@ -226,6 +229,9 @@ 32 + + QListView::Static + QListView::LeftToRight diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index adf381dc0..fcd14a61b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -223,7 +223,7 @@ TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString { m_tileFilename[channel] = filename; m_parentItem = parent; - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); + //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); } TileItemNode::~TileItemNode() @@ -257,7 +257,12 @@ QVariant TileItemNode::data(int column, int role) const if(!pixmap.load(tileFilename)) nlinfo("failed to load %s", tileFilename.toStdString().c_str()); - //pixmap.scaled(tileSize*100, tileSize*100); + if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) + tileSize *= 2; + else if(TileModel::CurrentZoomFactor == TileModel::TileZoom50) + tileSize /= 2; + + pixmap.scaled(tileSize, tileSize); return pixmap; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index cd5c1c4ce..c167dbd44 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -21,6 +21,9 @@ #include +// Initialize the static members +TileModel::TTileZoomFactor TileModel::CurrentZoomFactor; + TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) { QVector rootData; @@ -29,7 +32,7 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte rootItem = new Node(rootData); - m_tileZoomFactor = TileZoom100; + TileModel::CurrentZoomFactor = TileModel::TileZoom100; m_indexDisplay = true; m_fileDisplay = true; } @@ -224,27 +227,4 @@ void TileModel::selectFilenameDisplay(bool selected) void TileModel::selectIndexDisplay(bool selected) { m_indexDisplay = selected; -} - -void TileModel::onZoomFactor(int level) -{ - switch(level) - { - // Zoom Level 50% - case 0: - nlinfo("zooming to 50%"); - m_tileZoomFactor = TileZoom50; - break; - case 1: - nlinfo("zooming to 100%"); - m_tileZoomFactor = TileZoom100; - break; - case 2: - nlinfo("zooming to 200%"); - m_tileZoomFactor = TileZoom200; - break; - default: - nlwarning("Invalid Time Zoom Factor passed."); - break; - }; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index e9884cd61..bd7d808fb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -59,6 +59,11 @@ public: TileZoom200 = 2 }; + static const int TILE_DISPLACE_BASE_SIZE = 32; + static const int TILE_TRANSITION_BASE_SIZE = 64; + static const int TILE_128_BASE_SIZE = 128; + static const int TILE_256_BASE_SIZE = 256; + TileModel(const QStringList &headers, QObject *parent); ~TileModel(); @@ -80,17 +85,18 @@ public: static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); + static TTileZoomFactor CurrentZoomFactor; + public Q_SLOTS: void selectFilenameDisplay(bool selected); - void selectIndexDisplay(bool selected); - void onZoomFactor(int level); + void selectIndexDisplay(bool selected); private: Node *getItem(const QModelIndex &index) const; bool m_fileDisplay; bool m_indexDisplay; - TTileZoomFactor m_tileZoomFactor; + //TTileZoomFactor m_tileZoomFactor; //QList m_tiles; //int m_activeEditChannel; From df07598a45718dabb5823a0b27982329032f8bcd Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 17 Sep 2012 15:12:01 -0500 Subject: [PATCH 010/282] merging legacy dfn-based method into geqt. Warning: broke the build. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/formitem.cpp | 198 ++- .../src/plugins/georges_editor/formitem.h | 17 +- .../georges_treeview_dialog.cpp | 132 +- .../georges_editor/georges_treeview_dialog.h | 12 +- .../georges_editor/georgesform_model.cpp | 1494 ++++++++++------- .../georges_editor/georgesform_model.h | 17 +- .../src/plugins/object_viewer/main_window.cpp | 2 +- 7 files changed, 1144 insertions(+), 728 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index e6e526631..014338a2d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -23,11 +23,13 @@ #include #include +using namespace NLGEORGES; + namespace GeorgesQt { CFormItem::CFormItem(NLGEORGES::UFormElm* elm, const QList &data, CFormItem *parent, - NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN) + NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN) { parentItem = parent; itemData = data; @@ -159,4 +161,198 @@ namespace GeorgesQt //formElm->setValueByName(); return true; } + +// CFormItem *CFormItem::add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot) +// { + // Add at the end +// uint index = _Children.size(); +// _Children.push_back (new CGeorgesEditDocSub); + +// _Children[index]->_Type = type; +// _Children[index]->_Name = name; +// _Children[index]->_Parent = this; +// _Children[index]->_StructId = structId; +// _Children[index]->_FormName = formName; +// _Children[index]->_Slot = slot; +// return _Children[index]; +// CFormItem *newNode = new CFormItem(); +// appendChild(newNode); +// return NULL; +// } + + CFormItem *CFormItem::add(NLGEORGES::UFormElm* root, std::string elmName) + { + CFormItem *newItem = NULL; + UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; + UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; + // Append a new item to the current parent's list of children. +// std::string elmName; +// if(root->getStructNodeName(num, elmName)) +// { + QList columnData; + //QVariant value; + std::string value; + //NLMISC::CRGBA value_color; + //uint value_uint; + //sint value_sint; + //double value_double; + QString elmtType = ""; + UFormElm *elmt = 0; + if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) + { + if (elmt) + { + if (elmt->isArray()) + elmtType = "Array"; + if (elmt->isStruct()) + elmtType = "Struct"; + if (elmt->isAtom()) + { + elmtType = "Atom"; + uint numDefinitions = 0; + const UType *type = elmt->getType(); + if (type) + { + numDefinitions = type->getNumDefinition(); + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (type->getType()) + { + case UType::UnsignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_uint");break; + case UType::SignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_sint");break; + case UType::Double: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); + elmtType.append("_double");break; + case UType::String: + elmtType.append("_string");break; + case UType::Color: + elmtType.append("_color");break; + default: + elmtType.append("_unknownType"); + } + } + else + { + elmtType.append("_noType"); + } + + if (numDefinitions) + { + std::string l, v; + QString tmpLabel, tmpValue; + for (uint i = 0; i < numDefinitions; i++) + { + type->getDefinition(i,l,v); + tmpLabel = l.c_str(); + tmpValue = v.c_str(); + if (type->getType() == UType::SignedInt) + { + if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { + value = l; + break; + } + } + if (type->getType() == UType::String) + { + if (QString(value.c_str()) == tmpValue) + { + value = l; + break; + } + } + } + } + } + if (elmt->isVirtualStruct()) + { + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + elmtType = "VirtualStruct"; + } + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + + newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); + this->appendChild(newItem); + + return newItem; + //if (parents.last()->childCount() > 0) { + // parents << parents.last()->child(parents.last()->childCount()-1); + //} + + // The building of the tree should be haoppening in the mode,. + //loadFormData(elmt, parent->child(parent->childCount()-1)); + } + else + { + // add Defaults + // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes + bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); + this->appendChild(newItem); + return newItem; + } +// } +// else +// { +// nlinfo("getNodeByName returned false"); +// } + } + } + } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index f440d1cf4..c56422caf 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -33,11 +33,13 @@ namespace GeorgesQt public: CFormItem(NLGEORGES::UFormElm *elm, const QList &data, CFormItem *parent = 0, - NLGEORGES::UFormElm::TWhereIsValue = NLGEORGES::UFormElm::ValueForm, - NLGEORGES::UFormElm::TWhereIsNode = NLGEORGES::UFormElm::NodeForm); + NLGEORGES::UFormElm::TWhereIsValue wV = NLGEORGES::UFormElm::ValueForm, + NLGEORGES::UFormElm::TWhereIsNode wN = NLGEORGES::UFormElm::NodeForm); ~CFormItem(); void appendChild(CFormItem *child); + //CFormItem *add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot); + CFormItem *add(NLGEORGES::UFormElm* root, std::string elmName); CFormItem *child(int row); int childCount() const; @@ -56,13 +58,18 @@ namespace GeorgesQt return whereN; } - private: + void setValueFrom(NLGEORGES::UFormElm::TWhereIsValue wV) { whereV = wV; } + void setNodeFrom(NLGEORGES::UFormElm::TWhereIsNode wN) { whereN = wN; } + + + private: + //CFormItem() { whereV = NLGEORGES::UFormElm::ValueForm; whereN = NLGEORGES::UFormElm::NodeForm; } QList childItems; QList itemData; CFormItem *parentItem; NLGEORGES::UFormElm* formElm; - NLGEORGES::UFormElm::TWhereIsValue whereV; - NLGEORGES::UFormElm::TWhereIsNode whereN; + NLGEORGES::UFormElm::TWhereIsValue whereV; + NLGEORGES::UFormElm::TWhereIsNode whereN; }; // CFormItem } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index 3bdc680ff..92da6e8a0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -61,7 +61,7 @@ namespace GeorgesQt // Set the default sheet dir dir to the level design path. m_lastSheetDir = "."; QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); m_lastSheetDir = settings->value(Core::Constants::LEVELDESIGN_PATH, "l:/leveldesign").toString(); settings->endGroup(); @@ -102,12 +102,12 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::headerClicked(int section) { if (section == 0) - { + { if (*(m_header->expanded())) m_ui.treeView->expandAll(); else m_ui.treeView->collapseAll(); - } + } } void CGeorgesTreeViewDialog::setForm(const CForm *form) @@ -119,8 +119,8 @@ namespace GeorgesQt { if(NLMISC::CPath::exists(formName.toStdString())) { - //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toStdString())); - return (NLGEORGES::CForm *)m_georges->loadForm(formName.toStdString()); + //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toStdString())); + return (NLGEORGES::CForm *)m_georges->loadForm(formName.toStdString()); } //else //{ @@ -156,56 +156,56 @@ namespace GeorgesQt // } // return form; //} - nlinfo("File '%s' does not exist!", formName.toStdString().c_str()); + nlinfo("File '%s' does not exist!", formName.toStdString().c_str()); return 0; } NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByDfnName(const QString dfnName) { - if(NLMISC::CPath::exists(dfnName.toStdString())) - { - // Create a new form object. - NLGEORGES::CForm *form = new NLGEORGES::CForm(); - m_form = form; - - // Retrieve a copy of the root definition. - NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toStdString())); - - // Next we'll use the root node to build a new form. - NLGEORGES::CFormElmStruct *fes = dynamic_cast(getRootNode(0)); - fes->build(formDfn); - - // And then initialize the held elements; - for(uint i = 0; i(getRootNode(i+1)); - fes->build(formDfn); - } - - return form; - } - nlinfo("File '%s' does not exist!", dfnName.toStdString().c_str()); - return NULL; + if(NLMISC::CPath::exists(dfnName.toStdString())) + { + // Create a new form object. + NLGEORGES::CForm *form = new NLGEORGES::CForm(); + m_form = form; + + // Retrieve a copy of the root definition. + NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toStdString())); + + // Next we'll use the root node to build a new form. + NLGEORGES::CFormElmStruct *fes = dynamic_cast(getRootNode(0)); + fes->build(formDfn); + + // And then initialize the held elements; + for(uint i = 0; i(getRootNode(i+1)); + fes->build(formDfn); + } + + return form; + } + nlinfo("File '%s' does not exist!", dfnName.toStdString().c_str()); + return NULL; } NLGEORGES::CFormElm *CGeorgesTreeViewDialog::getRootNode(uint slot) { - NLGEORGES::CForm *form = getFormPtr(); + NLGEORGES::CForm *form = getFormPtr(); - if(slot == 0) - { - const NLGEORGES::UFormElm &formElm = form->getRootNode(); - return (NLGEORGES::CFormElm *)&formElm; - } + if(slot == 0) + { + const NLGEORGES::UFormElm &formElm = form->getRootNode(); + return (NLGEORGES::CFormElm *)&formElm; + } - // Make sure the slot value is valid and then return the corresponding element. - nlassert(slot < NLGEORGES::CForm::HeldElementCount+1); - return getFormPtr()->HeldElements[slot-1]; + // Make sure the slot value is valid and then return the corresponding element. + nlassert(slot < NLGEORGES::CForm::HeldElementCount+1); + return getFormPtr()->HeldElements[slot-1]; } NLGEORGES::CForm *CGeorgesTreeViewDialog::getFormPtr() { - return dynamic_cast(m_form); + return dynamic_cast(m_form); } void CGeorgesTreeViewDialog::loadFormIntoDialog(CForm *form) @@ -219,14 +219,16 @@ namespace GeorgesQt UFormElm *root = 0; root = &m_form->getRootNode(); + // Extract the parent forms into the list of parents in the dialog. QStringList parents; - uint cnt = form->getParentCount(); - for (uint i = 0; i < cnt /*form->getParentCount()*/; i++) + uint cnt = form->getParentCount(); + for (uint i = 0; i < cnt /*form->getParentCount()*/; i++) { UForm *u = m_form->getParentForm(i); parents << u->getFilename().c_str(); } + // Exact the comment box for the dialog. QString comments; comments = m_form->getComment().c_str(); @@ -255,7 +257,7 @@ namespace GeorgesQt { loadedForm = m_form->getFilename().c_str(); - CGeorgesFormModel *model = new CGeorgesFormModel(root,deps,comments,parents,m_header->expanded()); + CGeorgesFormModel *model = new CGeorgesFormModel(m_form,deps,comments,parents,m_header->expanded()); CGeorgesFormProxyModel *proxyModel = new CGeorgesFormProxyModel(); proxyModel->setSourceModel(model); m_ui.treeView->setModel(proxyModel); @@ -317,12 +319,12 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::write( ) { - NLMISC::COFile file; - std::string s = NLMISC::CPath::lookup(loadedForm.toStdString(), false); - if(file.open (s)) - { - try - { + NLMISC::COFile file; + std::string s = NLMISC::CPath::lookup(loadedForm.toStdString(), false); + if(file.open (s)) + { + try + { // if (loadedForm.contains(".typ")) // { // //nlassert (Type != NULL); @@ -335,7 +337,7 @@ namespace GeorgesQt // // flushValueChange (); // //} // //Type->write (xmlStream.getDocument (), theApp.Georges4CVS); - // //modify (NULL, NULL, false); + // //modify (NULL, NULL, false); // //flushValueChange (); // //UpdateAllViews (NULL); // //return TRUE; @@ -357,17 +359,17 @@ namespace GeorgesQt // } // else // { - nlassert (m_form != NULL); + nlassert (m_form != NULL); - // Write the file + // Write the file // /*if (IsModified ()) // { // ((CForm*)(UForm*)Form)->Header.MinorVersion++; // }*/ // //((CForm*)(UForm*)Form)->write (xmlStream.getDocument (), lpszPathName, theApp.Georges4CVS); - m_form->write(file, false); - setWindowTitle(windowTitle().remove("*")); - m_modified = false; + m_form->write(file, false); + setWindowTitle(windowTitle().remove("*")); + m_modified = false; // //if (strcmp (xmlStream.getErrorString (), "") != 0) // //{ // // char message[512]; @@ -381,16 +383,16 @@ namespace GeorgesQt // // Get the left view // //CView* pView = getLeftView (); // } - } - catch (Exception &e) - { - nlerror("Error while loading file: %s", e.what()); - } - } - else - { - nlerror("Can't open the file %s for writing.", s.c_str()); - } + } + catch (Exception &e) + { + nlerror("Error while loading file: %s", e.what()); + } + } + else + { + nlerror("Can't open the file %s for writing.", s.c_str()); + } } void CGeorgesTreeViewDialog::doubleClicked ( const QModelIndex & index ) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h index e34ab572b..6f7b57acc 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h @@ -57,14 +57,14 @@ namespace GeorgesQt bool isModified() {return m_modified;} void setModified(bool m) {m_modified = m;} - NLGEORGES::CForm* getFormByName(const QString formName); - NLGEORGES::CForm* getFormByDfnName(const QString dfnName); + NLGEORGES::CForm* getFormByName(const QString formName); + NLGEORGES::CForm* getFormByDfnName(const QString dfnName); - /// Retrieves the root element based on the slot (document or held elements.) - NLGEORGES::CFormElm *getRootNode(uint slot); + /// Retrieves the root element based on the slot (document or held elements.) + NLGEORGES::CFormElm *getRootNode(uint slot); - /// Returns the form as a CForm pointer. - NLGEORGES::CForm *getFormPtr(); + /// Returns the form as a CForm pointer. + NLGEORGES::CForm *getFormPtr(); void addParentForm(QString parentFormNm); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index 9e3f97c48..b8c9f56ff 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -16,13 +16,18 @@ #include "georgesform_model.h" +// System Includes +#include + // NeL includes #include #include #include +#include #include #include #include +#include // Qt includes #include @@ -43,653 +48,848 @@ using namespace NLGEORGES; namespace GeorgesQt { - CGeorgesFormModel::CGeorgesFormModel(UFormElm *rootElm, QMap< QString, QStringList> deps, - QString comment, QStringList parents, bool *expanded, QObject *parent) : QAbstractItemModel(parent) - { - - m_rootData << "Value" << "Data" << "Extra";// << "Type"; - m_rootElm = rootElm; - m_rootItem = new CFormItem(m_rootElm, m_rootData); - m_dependencies = deps; - m_comments = comment; - m_parents = parents; - m_parentRows = new QList; - m_expanded = expanded; - - setupModelData(); - } - - CGeorgesFormModel::~CGeorgesFormModel() - { - delete m_rootItem; - } - - /******************************************************************************/ - - QVariant CGeorgesFormModel::data(const QModelIndex &p_index, int p_role) const - { - if (!p_index.isValid()) - return QVariant(); - - switch (p_role) - { - case Qt::DisplayRole: - { - return getItem(p_index)->data(p_index.column()); - } - case Qt::BackgroundRole: - { - QBrush defaultBrush = QBrush(QColor(255,0,0,30)); - QBrush parentBrush = QBrush(QColor(0,255,0,30)); - - // if elm not existing it must be some kind of default or type value - if(!getItem(p_index)->getFormElm()) - { - return defaultBrush; - } - - // else it might be some parent elm - switch (getItem(p_index)->nodeFrom()) - { - case NLGEORGES::UFormElm::NodeParentForm: - { - return parentBrush; - } - case NLGEORGES::UFormElm::NodeForm: - { - switch (getItem(p_index)->valueFrom()) - { - case NLGEORGES::UFormElm::ValueParentForm: - { - return parentBrush; - } - default: - { - // parent status test kindof ugly, testing only 2 steps deep - // only needed for colorization as treeview default hides childs - // when parent is hidden - CFormItem *parent = getItem(p_index)->parent(); - if (parent) - { - if (parent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - - CFormItem *parentParent = parent->parent(); - if (parentParent) - { - if (parentParent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - } // endif parentParent - } // endif parent - } // end default - } // end switch valueFrom - } // end case nodeForm - } // end switch nodeFrom - return QVariant(); - } - case Qt::DecorationRole: - { - if (p_index.column() == 2) - { - //p_index. - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - - QString value = item->data(1).toString(); - //QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - return QIcon(path); - } - } - return QVariant(); - break; - } - case Qt::ToolTipRole: - { - if (p_index.column() == 2) - { - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - QString value = item->data(1).toString(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - - QString imageTooltip = QString("").arg(path); - - return imageTooltip; - } - } - return QVariant(); - break; - } - default: - return QVariant(); - } - } - - /******************************************************************************/ - - CFormItem *CGeorgesFormModel::getItem(const QModelIndex &index) const - { - if (index.isValid()) - { - CFormItem *item = static_cast(index.internalPointer()); - if (item) - return item; - } - return m_rootItem; - } - - /******************************************************************************/ - - bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, - int role) - { - - if (role != Qt::EditRole) - return false; - - CFormItem *item = getItem(index); - bool result = item->setData(index.column(), value); - - Q_EMIT dataChanged(index, index); - - //setupModelData(); - return result; - } - - /******************************************************************************/ - - Qt::ItemFlags CGeorgesFormModel::flags(const QModelIndex& index) const { - - if (!index.isValid()) - return 0; - - Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - - if(index.column() == 1) - returnValue |= Qt::ItemIsEditable; - - return returnValue; - - } - - /******************************************************************************/ - - QVariant CGeorgesFormModel::headerData(int section, - Qt::Orientation orientation, int role) const - { - if (orientation == Qt::Horizontal) - { - if (role == Qt::DisplayRole) - return m_rootItem->data(section); - if (role == Qt::TextAlignmentRole) - return Qt::AlignLeft; - if (section == 0 && role == Qt::DecorationRole) - { - // transparent pixmap as we paint it ourself with tree brach - // if we extend the HeaderView::paintSection for the CE_HeaderLabel - // we could drop this - QPixmap pixmap = QPixmap( - QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize), - QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize)); - // Create new picture for transparent - QPixmap transparent(pixmap.size()); - - // Do transparency - transparent.fill(Qt::transparent); - QPainter p(&transparent); - p.setCompositionMode(QPainter::CompositionMode_Source); - p.drawPixmap(0, 0, pixmap); - p.setCompositionMode(QPainter::CompositionMode_DestinationIn); - // Set transparency level to 150 (possible values are 0-255) - // The alpha channel of a color specifies the transparency effect, - // 0 represents a fully transparent color, while 255 represents - // a fully opaque color. - p.fillRect(transparent.rect(), QColor(0, 0, 0, 0)); - p.end(); - - // Set original picture's reference to new transparent one - pixmap = transparent; - return pixmap; - } - } - return QVariant(); - } - - /******************************************************************************/ - - QModelIndex CGeorgesFormModel::index(int row, int column, const QModelIndex &parent) - const - { - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - CFormItem *parentItem; - - if (!parent.isValid()) - parentItem = m_rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - CFormItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); - } - - /******************************************************************************/ - - QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const - { - if (!index.isValid()) - return QModelIndex(); - - CFormItem *childItem = static_cast(index.internalPointer()); - CFormItem *parentItem = childItem->parent(); - - if (parentItem == m_rootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); - } - - /******************************************************************************/ - - int CGeorgesFormModel::rowCount(const QModelIndex &parent) const { - - CFormItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = m_rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); - - } - - /******************************************************************************/ - - int CGeorgesFormModel::columnCount(const QModelIndex &parent) const { - - if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return m_rootItem->columnCount(); - - } - - /******************************************************************************/ - - void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) { - - if (!root) - return; - - uint num = 0; - - - if (root->isStruct()) - { - //((CFormElm*)root)->getForm()->getComment(); - uint structSize = 0; - root->getStructSize(structSize); - while (num < structSize) - { - UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - // Append a new item to the current parent's list of children. - std::string elmName; - if(root->getStructNodeName(num, elmName)) - { - QList columnData; - //QVariant value; - std::string value; - //NLMISC::CRGBA value_color; - //uint value_uint; - //sint value_sint; - //double value_double; - QString elmtType = ""; - UFormElm *elmt = 0; - if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) - { - if (elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) - elmtType = "Struct"; - if (elmt->isAtom()) - { - elmtType = "Atom"; - uint numDefinitions = 0; - const UType *type = elmt->getType(); - if (type) - { - numDefinitions = type->getNumDefinition(); - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (type->getType()) - { - case UType::UnsignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_uint");break; - case UType::SignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_sint");break; - case UType::Double: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); - elmtType.append("_double");break; - case UType::String: - elmtType.append("_string");break; - case UType::Color: - elmtType.append("_color");break; - default: - elmtType.append("_unknownType"); - } - } - else - { - elmtType.append("_noType"); - } - - if (numDefinitions) - { - std::string l, v; - QString tmpLabel, tmpValue; - for (uint i = 0; i < numDefinitions; i++) - { - type->getDefinition(i,l,v); - tmpLabel = l.c_str(); - tmpValue = v.c_str(); - if (type->getType() == UType::SignedInt) - { - if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { - value = l; - break; - } - } - if (type->getType() == UType::String) - { - if (QString(value.c_str()) == tmpValue) - { - value = l; - break; - } - } - } - } - } - if (elmt->isVirtualStruct()) - { - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - elmtType = "VirtualStruct"; - } - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - //if (parents.last()->childCount() > 0) { - // parents << parents.last()->child(parents.last()->childCount()-1); - //} - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - else - { - // add Defaults - // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes - bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - } - } - else - { - nlinfo("getNodeByName returned false"); - } - } - num++; - } - } - if (root->isArray()) - { - uint arraySize = 0; - root->getArraySize(arraySize); - while (num < arraySize) - { - std::string elmName; - if(root->getArrayNodeName(elmName, num)) - { - QList columnData; - std::string value; - QString elmtType = ""; - - UFormElm *elmt = 0; - if(root->getArrayNode(&elmt,0) && elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) { - elmtType = "Struct"; - } - if (elmt->isAtom()) - { - elmt->getValue(value); - elmtType = "Atom"; - } - if (elmt->isVirtualStruct()) - elmtType = "VirtualStruct"; - - elmtType.append("_arrayValue"); - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent)); - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - } - num++; - } - } - } - - /******************************************************************************/ - - void CGeorgesFormModel::loadFormHeader() - { - - if (m_parents.size()) - { - CFormItem *fi_pars = new CFormItem(m_rootElm, QList() << "parents" << "" << "", m_rootItem); - m_rootItem->appendChild(fi_pars); - - Q_FOREACH(QString str, m_parents) - { - fi_pars->appendChild(new CFormItem(m_rootElm, QList() << str << "" << "", fi_pars)); - } - } - - /*QStringList dfns = _dependencies["dfn"]; - QStringList typs = _dependencies["typ"]; - - _dependencies.remove("dfn"); - _dependencies.remove("typ"); - - CFormItem *fi_dep = new CFormItem(_rootElm, QList() << "dependencies", _rootItem); - _rootItem->appendChild(fi_dep); - - if (!dfns.isEmpty()) { - CFormItem *fi_dfn = new CFormItem(_rootElm, QList() << "dfn", fi_dep); - fi_dep->appendChild(fi_dfn); - foreach(QString str, dfns) { - fi_dfn->appendChild(new CFormItem(_rootElm, QList() << str, fi_dfn)); - } - } - if (!typs.isEmpty()) { - CFormItem *fi_typ = new CFormItem(_rootElm, QList() << "typ", fi_dep); - fi_dep->appendChild(fi_typ); - foreach(QString str, typs) { - fi_typ->appendChild(new CFormItem(_rootElm, QList() << str, fi_typ)); - } - } - if (!_dependencies.isEmpty()) { - CFormItem *fi_other = new CFormItem(_rootElm, QList() << "other", fi_dep); - fi_dep->appendChild(fi_other); - foreach(QStringList list, _dependencies) { - foreach(QString str, list) { - fi_other->appendChild(new CFormItem(_rootElm, QList() << str, fi_other)); - } - } - }*/ - } - - /******************************************************************************/ - - void CGeorgesFormModel::setupModelData() - { - loadFormHeader(); - loadFormData(m_rootElm, m_rootItem); - } - - /******************************************************************************/ - - void CGeorgesFormModel::setShowParents( bool show ) { - m_showParents = show; - Q_EMIT layoutAboutToBeChanged(); - Q_EMIT layoutChanged(); - } - void CGeorgesFormModel::setShowDefaults( bool show ) - { - m_showDefaults = show; - Q_EMIT layoutAboutToBeChanged(); - Q_EMIT layoutChanged(); - } - - void CGeorgesFormModel::addParentForm(QString parentForm) - { - beginResetModel(); - m_parents.push_back(parentForm); - delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); - setupModelData(); - endResetModel(); - } - - void CGeorgesFormModel::removeParentForm(QString parentForm) - { - beginResetModel(); - m_parents.removeOne(parentForm); - - delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); - setupModelData(); - endResetModel(); - } + CGeorgesFormModel::CGeorgesFormModel(UForm *form, QMap< QString, QStringList> deps, + QString comment, QStringList parents, bool *expanded, QObject *parent) : QAbstractItemModel(parent) + { + m_form = form; + m_rootData << "Value" << "Data" << "Extra";// << "Type"; + m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_dependencies = deps; + m_comments = comment; + m_parents = parents; + m_parentRows = new QList; + m_expanded = expanded; + + setupModelData(); + } + + CGeorgesFormModel::~CGeorgesFormModel() + { + delete m_rootItem; + } + + /******************************************************************************/ + + QVariant CGeorgesFormModel::data(const QModelIndex &p_index, int p_role) const + { + if (!p_index.isValid()) + return QVariant(); + + switch (p_role) + { + case Qt::DisplayRole: + { + return getItem(p_index)->data(p_index.column()); + } + case Qt::BackgroundRole: + { + QBrush defaultBrush = QBrush(QColor(255,0,0,30)); + QBrush parentBrush = QBrush(QColor(0,255,0,30)); + + // if elm not existing it must be some kind of default or type value + if(!getItem(p_index)->getFormElm()) + { + return defaultBrush; + } + + // else it might be some parent elm + switch (getItem(p_index)->nodeFrom()) + { + case NLGEORGES::UFormElm::NodeParentForm: + { + return parentBrush; + } + case NLGEORGES::UFormElm::NodeForm: + { + switch (getItem(p_index)->valueFrom()) + { + case NLGEORGES::UFormElm::ValueParentForm: + { + return parentBrush; + } + default: + { + // parent status test kindof ugly, testing only 2 steps deep + // only needed for colorization as treeview default hides childs + // when parent is hidden + CFormItem *parent = getItem(p_index)->parent(); + if (parent) + { + if (parent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) + { + return parentBrush; + } + + CFormItem *parentParent = parent->parent(); + if (parentParent) + { + if (parentParent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) + { + return parentBrush; + } + } // endif parentParent + } // endif parent + } // end default + } // end switch valueFrom + } // end case nodeForm + } // end switch nodeFrom + return QVariant(); + } + case Qt::DecorationRole: + { + if (p_index.column() == 2) + { + //p_index. + QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); + CFormItem *item = getItem(in); + + QString value = item->data(1).toString(); + //QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); + + /*if (value.contains(".shape")) + { + if (Modules::objViewInt()) + { + QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); + if (icon) + { + if(icon->isNull()) + return QIcon(":/images/pqrticles.png"); + else + return QIcon(*icon); + } + else + { + return QIcon(); + } + } + }*/ + if(value.contains(".tga") || value.contains(".png")) + { + QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); + if(path.isEmpty()) + { + path = ":/images/pqrticles.png"; + } + return QIcon(path); + } + } + return QVariant(); + break; + } + case Qt::ToolTipRole: + { + if (p_index.column() == 2) + { + QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); + CFormItem *item = getItem(in); + QString value = item->data(1).toString(); + + /*if (value.contains(".shape")) + { + if (Modules::objViewInt()) + { + QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); + if (icon) + { + if(icon->isNull()) + return QIcon(":/images/pqrticles.png"); + else + return QIcon(*icon); + } + else + { + return QIcon(); + } + } + }*/ + if(value.contains(".tga") || value.contains(".png")) + { + QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); + if(path.isEmpty()) + { + path = ":/images/pqrticles.png"; + } + + QString imageTooltip = QString("").arg(path); + + return imageTooltip; + } + } + return QVariant(); + break; + } + default: + return QVariant(); + } + } + + /******************************************************************************/ + + CFormItem *CGeorgesFormModel::getItem(const QModelIndex &index) const + { + if (index.isValid()) + { + CFormItem *item = static_cast(index.internalPointer()); + if (item) + return item; + } + return m_rootItem; + } + + /******************************************************************************/ + + bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, + int role) + { + + if (role != Qt::EditRole) + return false; + + CFormItem *item = getItem(index); + bool result = item->setData(index.column(), value); + + Q_EMIT dataChanged(index, index); + + //setupModelData(); + return result; + } + + /******************************************************************************/ + + Qt::ItemFlags CGeorgesFormModel::flags(const QModelIndex& index) const { + + if (!index.isValid()) + return 0; + + Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + if(index.column() == 1) + returnValue |= Qt::ItemIsEditable; + + return returnValue; + + } + + /******************************************************************************/ + + QVariant CGeorgesFormModel::headerData(int section, + Qt::Orientation orientation, int role) const + { + if (orientation == Qt::Horizontal) + { + if (role == Qt::DisplayRole) + return m_rootItem->data(section); + if (role == Qt::TextAlignmentRole) + return Qt::AlignLeft; + if (section == 0 && role == Qt::DecorationRole) + { + // transparent pixmap as we paint it ourself with tree brach + // if we extend the HeaderView::paintSection for the CE_HeaderLabel + // we could drop this + QPixmap pixmap = QPixmap( + QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize), + QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize)); + // Create new picture for transparent + QPixmap transparent(pixmap.size()); + + // Do transparency + transparent.fill(Qt::transparent); + QPainter p(&transparent); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.drawPixmap(0, 0, pixmap); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + // Set transparency level to 150 (possible values are 0-255) + // The alpha channel of a color specifies the transparency effect, + // 0 represents a fully transparent color, while 255 represents + // a fully opaque color. + p.fillRect(transparent.rect(), QColor(0, 0, 0, 0)); + p.end(); + + // Set original picture's reference to new transparent one + pixmap = transparent; + return pixmap; + } + } + return QVariant(); + } + + /******************************************************************************/ + + QModelIndex CGeorgesFormModel::index(int row, int column, const QModelIndex &parent) + const + { + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + CFormItem *parentItem; + + if (!parent.isValid()) + parentItem = m_rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + CFormItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); + } + + /******************************************************************************/ + + QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const + { + if (!index.isValid()) + return QModelIndex(); + + CFormItem *childItem = static_cast(index.internalPointer()); + CFormItem *parentItem = childItem->parent(); + + if (parentItem == m_rootItem) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); + } + + /******************************************************************************/ + + int CGeorgesFormModel::rowCount(const QModelIndex &parent) const { + + CFormItem *parentItem; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parentItem = m_rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + return parentItem->childCount(); + + } + + /******************************************************************************/ + + int CGeorgesFormModel::columnCount(const QModelIndex &parent) const { + + if (parent.isValid()) + return static_cast(parent.internalPointer())->columnCount(); + else + return m_rootItem->columnCount(); + + } + + /******************************************************************************/ + + void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) { + + if (!root) + return; + + uint num = 0; + + + if (root->isStruct()) + { + //((CFormElm*)root)->getForm()->getComment(); + uint structSize = 0; + root->getStructSize(structSize); + while (num < structSize) + { + UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; + UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; + // Append a new item to the current parent's list of children. + std::string elmName; + if(root->getStructNodeName(num, elmName)) + { + QList columnData; + //QVariant value; + std::string value; + //NLMISC::CRGBA value_color; + //uint value_uint; + //sint value_sint; + //double value_double; + QString elmtType = ""; + UFormElm *elmt = 0; + if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) + { + if (elmt) + { + if (elmt->isArray()) + elmtType = "Array"; + if (elmt->isStruct()) + elmtType = "Struct"; + if (elmt->isAtom()) + { + elmtType = "Atom"; + uint numDefinitions = 0; + const UType *type = elmt->getType(); + if (type) + { + numDefinitions = type->getNumDefinition(); + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (type->getType()) + { + case UType::UnsignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_uint");break; + case UType::SignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_sint");break; + case UType::Double: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); + elmtType.append("_double");break; + case UType::String: + elmtType.append("_string");break; + case UType::Color: + elmtType.append("_color");break; + default: + elmtType.append("_unknownType"); + } + } + else + { + elmtType.append("_noType"); + } + + if (numDefinitions) + { + std::string l, v; + QString tmpLabel, tmpValue; + for (uint i = 0; i < numDefinitions; i++) + { + type->getDefinition(i,l,v); + tmpLabel = l.c_str(); + tmpValue = v.c_str(); + if (type->getType() == UType::SignedInt) + { + if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { + value = l; + break; + } + } + if (type->getType() == UType::String) + { + if (QString(value.c_str()) == tmpValue) + { + value = l; + break; + } + } + } + } + } + if (elmt->isVirtualStruct()) + { + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + elmtType = "VirtualStruct"; + } + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); + //if (parents.last()->childCount() > 0) { + // parents << parents.last()->child(parents.last()->childCount()-1); + //} + loadFormData(elmt, parent->child(parent->childCount()-1)); + } + else + { + // add Defaults + // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes + bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); + } + } + else + { + nlinfo("getNodeByName returned false"); + } + } + num++; + } + } + if (root->isArray()) + { + uint arraySize = 0; + root->getArraySize(arraySize); + while (num < arraySize) + { + std::string elmName; + if(root->getArrayNodeName(elmName, num)) + { + QList columnData; + std::string value; + QString elmtType = ""; + + UFormElm *elmt = 0; + if(root->getArrayNode(&elmt,0) && elmt) + { + if (elmt->isArray()) + elmtType = "Array"; + if (elmt->isStruct()) { + elmtType = "Struct"; + } + if (elmt->isAtom()) + { + elmt->getValue(value); + elmtType = "Atom"; + } + if (elmt->isVirtualStruct()) + elmtType = "VirtualStruct"; + + elmtType.append("_arrayValue"); + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + parent->appendChild(new CFormItem(elmt, columnData, parent)); + loadFormData(elmt, parent->child(parent->childCount()-1)); + } + } + num++; + } + } + } + + CFormItem *CGeorgesFormModel::addStruct (CFormItem *parent, + NLGEORGES::CFormElmStruct *_struct, + NLGEORGES::CFormDfn *parentDfn, + const char *name, + uint structId, + const char *formName, + uint slot) +{ + // The form pointer + NLGEORGES::CForm *formPtr = static_cast(m_form); + + // Add the new node +// CFormItem *newNode = parent->add(/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); + CFormItem *newNode = parent->add(_struct, name); + + // Can be NULL in virtual DFN + if (parentDfn) + { + // Get the parents + std::vector arrayDfn; + arrayDfn.reserve (parentDfn->countParentDfn ()); + parentDfn->getParentDfn (arrayDfn); + + // For each child + uint elm=0; + for (uint dfn=0; dfngetNumEntry (); i++) + { + // Get the entry ref + NLGEORGES::CFormDfn::CEntry &entry = arrayDfn[dfn]->getEntry (i); + + // Form entry name + std::string entryName = (std::string (formName)+"."+entry.getName ()); + + // Is a struct ? + if ( (entry.getType () == NLGEORGES::UFormDfn::EntryDfn) || (entry.getType () == NLGEORGES::UFormDfn::EntryVirtualDfn) ) + { + // Is an array of struct ? + if (entry.getArrayFlag ()) + { + // Get it from the form + CFormElmArray *nextArray = NULL; + if (_struct && _struct->Elements[elm].Element) + nextArray = NLMISC::safe_cast (_struct->Elements[elm].Element); + + // Else, get it from the parent if we are not a virtual DFN (don't inheritate) + + // todo array of virtual struct + if (!nextArray && (entry.getType () != NLGEORGES::UFormDfn::EntryVirtualDfn) ) + { + // For each parent form + for (uint parent=0; parentgetParentCount (); parent++) + { + // Get the node by name + NLGEORGES::UFormElm *uNode; + if (formPtr->getParent (parent)->getRootNode ().getNodeByName (&uNode, entryName.c_str(), NULL, false) && uNode) + { + nextArray = NLMISC::safe_cast (uNode); + } + } + } + + // Add the new struct + addArray (newNode, nextArray, entry.getDfnPtr (), entry.getName().c_str(), elm, entryName.c_str (), slot); + } + else + { + // Add it + NLGEORGES::CFormElmStruct *nextForm = NULL; + + // Get it from the form + if (_struct && _struct->Elements[elm].Element) + nextForm = NLMISC::safe_cast (_struct->Elements[elm].Element); + + // Else, get it from the parent + if (!nextForm) + { + // For each parent form + for (uint parent=0; parentgetParentCount (); parent++) + { + // Get the node by name + NLGEORGES::UFormElm *uNode; + if (formPtr->getParent (parent)->getRootNode ().getNodeByName (&uNode, entryName.c_str(), NULL, false) && uNode) + { + nextForm = NLMISC::safe_cast (uNode); + } + } + } + + // Virtual Dfn pointer + NLGEORGES::CFormElmVirtualStruct *vStruct = ((entry.getType () == NLGEORGES::UFormDfn::EntryVirtualDfn) && nextForm) ? + NLMISC::safe_cast (nextForm) : NULL; + + NLGEORGES::CFormDfn *tmpDfn = vStruct ? + ((NLGEORGES::CFormDfn*)vStruct->FormDfn) : entry.getDfnPtr(); + // Add the new struct + addStruct (newNode, nextForm, tmpDfn, entry.getName().c_str(), elm, entryName.c_str(), slot); + } + } + // Array of type ? + else if ( entry.getArrayFlag () ) + { + NLGEORGES::CFormElmArray *nextArray = NULL; + + // Get it from the form + if (_struct && _struct->Elements[elm].Element) + nextArray = NLMISC::safe_cast (_struct->Elements[elm].Element); + + // Else, get it from the parent + if (!nextArray) + { + // For each parent form + for (uint parent=0; parentgetParentCount (); parent++) + { + // Get the node by name + NLGEORGES::UFormElm *uNode; + if (formPtr->getParent (parent)->getRootNode ().getNodeByName (&uNode, entryName.c_str(), NULL, false) && uNode) + { + nextArray = NLMISC::safe_cast (uNode); + } + } + } + + // Add the new array + addArray ( newNode, nextArray, NULL, entry.getName().c_str(), elm, entryName.c_str(), slot ); + } + + // Next element + elm++; + } + } + } + + return newNode; +} + +// *************************************************************************** + +CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, + NLGEORGES::CFormElmArray *array, + NLGEORGES::CFormDfn *rootDfn, + const char *name, + uint structId, + const char *formName, + uint slot) +{ + // Add the new node + //CFormItem *newNode = parent->add (/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); + CFormItem *newNode = parent->add (array, name); + + // The array exist + if (array) + { + // For each array element + for (uint elm=0; elmElements.size(); elm++) + { + // The form name + char formArrayElmName[512]; + NLMISC::smprintf (formArrayElmName, 512, "%s[%d]", formName, elm); + + // The name + char formArrayName[512]; + if (array->Elements[elm].Name.empty ()) + { + NLMISC::smprintf (formArrayName, 512, "#%d", elm); + } + else + { + NLMISC::smprintf (formArrayName, 512, "%s", array->Elements[elm].Name.c_str()); + } + + // Is a struct + if (rootDfn) + { + // Get struct ptr + NLGEORGES::CFormElmStruct *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; + addStruct (newNode, elmPtr, rootDfn, formArrayName, elm, formArrayElmName, slot); + } + else + { + NLGEORGES::CFormElmArray *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; + newNode->add (elmPtr, formArrayElmName); + //newNode->add (/*CGeorgesEditDocSub::Form,*/ formArrayName, elm, formArrayElmName, slot); + } + } + } + + return newNode; +} + + + + /******************************************************************************/ + + void CGeorgesFormModel::loadFormHeader() + { + + if (m_parents.size()) + { + CFormItem *fi_pars = new CFormItem(m_rootElm, QList() << "parents" << "" << "", m_rootItem); + m_rootItem->appendChild(fi_pars); + + Q_FOREACH(QString str, m_parents) + { + fi_pars->appendChild(new CFormItem(m_rootElm, QList() << str << "" << "", fi_pars)); + } + } + + /*QStringList dfns = _dependencies["dfn"]; + QStringList typs = _dependencies["typ"]; + + _dependencies.remove("dfn"); + _dependencies.remove("typ"); + + CFormItem *fi_dep = new CFormItem(_rootElm, QList() << "dependencies", _rootItem); + _rootItem->appendChild(fi_dep); + + if (!dfns.isEmpty()) { + CFormItem *fi_dfn = new CFormItem(_rootElm, QList() << "dfn", fi_dep); + fi_dep->appendChild(fi_dfn); + foreach(QString str, dfns) { + fi_dfn->appendChild(new CFormItem(_rootElm, QList() << str, fi_dfn)); + } + } + if (!typs.isEmpty()) { + CFormItem *fi_typ = new CFormItem(_rootElm, QList() << "typ", fi_dep); + fi_dep->appendChild(fi_typ); + foreach(QString str, typs) { + fi_typ->appendChild(new CFormItem(_rootElm, QList() << str, fi_typ)); + } + } + if (!_dependencies.isEmpty()) { + CFormItem *fi_other = new CFormItem(_rootElm, QList() << "other", fi_dep); + fi_dep->appendChild(fi_other); + foreach(QStringList list, _dependencies) { + foreach(QString str, list) { + fi_other->appendChild(new CFormItem(_rootElm, QList() << str, fi_other)); + } + } + }*/ + } + + /******************************************************************************/ + + void CGeorgesFormModel::setupModelData() + { + m_rootElm = &((NLGEORGES::CForm*)m_form)->Elements; + NLGEORGES::CFormElmStruct *rootstruct = &((NLGEORGES::CForm*)m_form)->Elements; + loadFormHeader(); + addStruct(m_rootItem, rootstruct, rootstruct->FormDfn, "Content", 0xffffffff, "", 0); + //loadFormData(m_rootElm, m_rootItem); + } + + /******************************************************************************/ + + void CGeorgesFormModel::setShowParents( bool show ) { + m_showParents = show; + Q_EMIT layoutAboutToBeChanged(); + Q_EMIT layoutChanged(); + } + void CGeorgesFormModel::setShowDefaults( bool show ) + { + m_showDefaults = show; + Q_EMIT layoutAboutToBeChanged(); + Q_EMIT layoutChanged(); + } + + void CGeorgesFormModel::addParentForm(QString parentForm) + { + beginResetModel(); + m_parents.push_back(parentForm); + delete m_rootItem; + m_rootItem = new CFormItem(m_rootElm, m_rootData); + setupModelData(); + endResetModel(); + } + + void CGeorgesFormModel::removeParentForm(QString parentForm) + { + beginResetModel(); + m_parents.removeOne(parentForm); + + delete m_rootItem; + m_rootItem = new CFormItem(m_rootElm, m_rootData); + setupModelData(); + endResetModel(); + } } /* namespace GeorgesQt */ /* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h index 710598236..493f672dd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h @@ -27,6 +27,10 @@ namespace NLGEORGES { class UFormElm; + class UForm; + class CFormElmStruct; + class CFormDfn; + class CFormElmArray; } namespace GeorgesQt @@ -38,7 +42,7 @@ namespace GeorgesQt { public: - CGeorgesFormModel(NLGEORGES::UFormElm *root, QMap< QString, QStringList> deps, + CGeorgesFormModel(NLGEORGES::UForm *form, QMap< QString, QStringList> deps, QString comment, QStringList parents, bool* expanded, QObject *parent = 0); ~CGeorgesFormModel(); @@ -58,15 +62,22 @@ namespace GeorgesQt void setShowDefaults( bool show ); void addParentForm(QString parentForm); void removeParentForm(QString parentForm); - NLGEORGES::UFormElm *getRootForm() { return m_rootElm; } + NLGEORGES::UFormElm *getRootForm() { return m_rootElm; } + + CFormItem *addStruct (CFormItem *parent, NLGEORGES::CFormElmStruct *_struct, NLGEORGES::CFormDfn *parentDfn, + const char *name, uint structId, const char *formName, uint slot); + + CFormItem *addArray(CFormItem *parent, NLGEORGES::CFormElmArray *array, NLGEORGES::CFormDfn *rootDfn, + const char *name, uint structId, const char *formName, uint slot); private: void setupModelData(); void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent); void loadFormHeader(); + NLGEORGES::UForm* m_form; CFormItem* m_rootItem; - NLGEORGES::UFormElm* m_rootElm; + NLGEORGES::UFormElm* m_rootElm; QList m_rootData; QMap< QString, QStringList> m_dependencies; QString m_comments; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp index a65f510c4..edbc31275 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp @@ -66,7 +66,7 @@ CMainWindow::CMainWindow(QWidget *parent) _isGraphicsInitialized(false), _isGraphicsEnabled(false), _isSoundInitialized(false), - _isSoundEnabled(true), + _isSoundEnabled(false), // MTR workaround for sheet id nonsense _GraphicsViewport(NULL), _lastDir("."), _mouseMode(NL3D::U3dMouseListener::edit3d) From a42a58590eb7af9e25e3a0761502f15fae0ce4df Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 20 Sep 2012 16:39:21 -0500 Subject: [PATCH 011/282] Changed: #1306 Radically changed the plugin in a new branch to match the way classic GE loads forms. - Refactored the tree view to show only structs, arrays, vstructs and eliminated atoms from its view. - Refactored the form view to have a Qt Properties Browser - Refactored the loader to use the classic GE addStruct/addArray. - Moved some functionality into CFormItem. - Added icons from classic GE and configured model/item to return them appropriately. - Getting read for changes via undo commands. - Eliminating/ignoring the hold/slots business from classic GE code. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/CMakeLists.txt | 8 +- .../src/plugins/georges_editor/actions.cpp | 17 + .../src/plugins/georges_editor/actions.h | 20 + .../plugins/georges_editor/formdelegate.cpp | 4 + .../src/plugins/georges_editor/formdelegate.h | 4 + .../src/plugins/georges_editor/formitem.cpp | 392 ++++++----------- .../src/plugins/georges_editor/formitem.h | 160 +++---- .../plugins/georges_editor/georges_editor.qrc | 7 + .../georges_treeview_dialog.cpp | 265 ++++++------ .../georges_editor/georges_treeview_form.ui | 110 +++-- .../georges_editor/georgesform_model.cpp | 406 ++---------------- .../georgesform_proxy_model.cpp | 3 + .../georges_editor/georgesform_proxy_model.h | 3 +- .../plugins/georges_editor/images/array.ico | Bin 0 -> 1406 bytes .../plugins/georges_editor/images/header.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/hold.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/root.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/struct.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/vstruct.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/zfee51.ico | Bin 0 -> 2238 bytes 20 files changed, 482 insertions(+), 917 deletions(-) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/struct.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt index 3661decef..5aba06740 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt @@ -1,12 +1,14 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) + ${QT_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/qtpropertybrowser) FILE(GLOB SRC *.cpp *.h) SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) SET(OVQT_PLUG_GEORGES_EDITOR_HDR georges_editor_plugin.h georges_editor_form.h @@ -36,7 +38,7 @@ SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) ADD_LIBRARY(ovqt_plugin_georges_editor MODULE ${SRC} ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_GEORGES_EDITOR_UI_HDRS} ${OVQT_PLUGIN_GEORGES_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_georges_editor ovqt_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(ovqt_plugin_georges_editor ovqt_plugin_core nelmisc nelgeorges qt_property_browser ${QT_LIBRARIES}) NL_DEFAULT_PROPS(ovqt_plugin_georges_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Georges Editor") NL_ADD_RUNTIME_FLAGS(ovqt_plugin_georges_editor) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp new file mode 100644 index 000000000..dba45fb96 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -0,0 +1,17 @@ +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "actions.h" \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h new file mode 100644 index 000000000..c646adc72 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -0,0 +1,20 @@ +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ACTIONS_H +#define ACTIONS_H + +#endif // ACTIONS_H \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp index 7f21fa072..ab306bf05 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp @@ -37,6 +37,8 @@ #include "georgesform_proxy_model.h" #include "formitem.h" +#if 0 + namespace GeorgesQt { @@ -276,3 +278,5 @@ namespace GeorgesQt editor->setGeometry(r); } } /* namespace GeorgesQt */ + +#endif // 0 \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h index b6885833e..42b10ef3d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h @@ -19,6 +19,8 @@ #include +#if 0 + namespace GeorgesQt { @@ -38,4 +40,6 @@ namespace GeorgesQt }; } +#endif // 0 + #endif // FORMDELEGATE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index 014338a2d..98bffa7e2 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -17,9 +17,11 @@ #include "formitem.h" // Qt includes +#include // NeL includes #include +#include #include #include @@ -27,15 +29,8 @@ using namespace NLGEORGES; namespace GeorgesQt { - - CFormItem::CFormItem(NLGEORGES::UFormElm* elm, const QList &data, CFormItem *parent, - NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN) + CFormItem::CFormItem() { - parentItem = parent; - itemData = data; - formElm = elm; - whereV = wV; - whereN = wN; } CFormItem::~CFormItem() @@ -61,12 +56,14 @@ namespace GeorgesQt int CFormItem::columnCount() const { //nlinfo("columnCount %d",itemData.count()); - return itemData.count(); + //return itemData.count(); + return 1; } QVariant CFormItem::data(int column) const { - return itemData.value(column); + //return itemData.value(column); + return QVariant(_Name.c_str()); } CFormItem *CFormItem::parent() @@ -84,275 +81,146 @@ namespace GeorgesQt bool CFormItem::setData(int column, const QVariant &value) { - if (column < 0 || column >= itemData.size()) + if (column != 0) return false; - // TODO: default values - if (!formElm) + bool deleteInsert = false; + + + + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *parentNode; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form=static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if (parentItem && parentItem->nodeType () == CFormItem::Form) + { + std::string newName = value.toString().toStdString(); + _Name = newName; + + // Create an action to update the form. + } + return true; + } + + bool CFormItem::isEditable(int column) + { + // Ensure only valid types can be edited. + if(_Type == Null) + return false; + + // Make sure only the first column (name) can be editted. + if (column != 0) return false; - itemData[column] = value; - if (formElm->isAtom()) + CFormItem *parent = this->parent(); + + // If it wasn't a root node then lets check the node type. + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *parentNode; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form = static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (parent->formName ().c_str (), &parentDfn, indexDfn, + &nodeDfn, &nodeType, &parentNode, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(array && parentNode) + return true; + + return false; + + } + + QIcon CFormItem::getItemImage(CFormItem *rootItem) + { + if(_Type == CFormItem::Null) + { + return QIcon(":/images/root.ico"); + } + else if(_Type == CFormItem::Form) { - const NLGEORGES::UType *type = formElm->getType(); - if (type) + // If the parent is the root item then this is the content. + if(parentItem == rootItem) + return QIcon(":/images/root.ico"); + + // If it wasn't a root node then lets check the node type. + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form = static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(array) + { + return QIcon(":/images/array.ico"); + } + else { - switch (type->getType()) + if(type == NLGEORGES::UFormDfn::EntryType) + { + if(parentDfn) + { + // Not sure what the hell to do with this. Gets filename from parent dfn? + } + return QIcon(":/images/zfee51.ico"); + } + else if(type == NLGEORGES::UFormDfn::EntryDfn) { - case NLGEORGES::UType::UnsignedInt: - case NLGEORGES::UType::SignedInt: - case NLGEORGES::UType::Double: - case NLGEORGES::UType::String: - if (parentItem->formElm->isArray()) + if(parentDfn) { - //((NLGEORGES::CFormElm*)parentItem->formElm);//->arrayInsertNodeByName( - //if(parentItem->formElm->getArrayNode(elmName, num)) - //{ - //} - - bool ok; - // TODO: the node can be renamed from eg "#0" to "foobar" - int arrayIndex = itemData[0].toString().remove("#").toInt(&ok); - if(ok) - { - NLGEORGES::UFormElm *elmt = 0; - if(parentItem->formElm->getArrayNode(&elmt, arrayIndex) && elmt) - { - if (elmt->isAtom()) - { - ((NLGEORGES::CFormElmAtom*)elmt)->setValue(value.toString().toStdString().c_str()); - nldebug(QString("array element string %1 %2") - .arg(itemData[0].toString()).arg(value.toString()) - .toStdString().c_str()); - } - } - } + // Not sure what the hell to do with this. Gets filename from parent dfn? } - else + return QIcon(":/images/struct.ico"); + } + else if(type == NLGEORGES::UFormDfn::EntryVirtualDfn) + { + if(node) { - if(parentItem->formElm->setValueByName( - value.toString().toStdString().c_str(), - itemData[0].toString().toStdString().c_str())) - { - nldebug(QString("string %1 %2") - .arg(itemData[0].toString()).arg(value.toString()) - .toStdString().c_str()); - } - else - { - nldebug(QString("FAILED string %1 %2") - .arg(itemData[0].toString()).arg(value.toString()) - .toStdString().c_str()); - } + // Not sure what the hell to do with this. Gets filename from parent dfn? + std::string dfnName; + NLMISC::safe_cast(node)->getDfnName(dfnName); + // return dfnName.c_str() ? } - break; - case NLGEORGES::UType::Color: - nldebug("Color is TODO"); - break; - default: - break; + return QIcon(":/images/vstruct.ico"); } } + //return QIcon(":/images/struct.ico"); } - else - { - nldebug("setting sth other than Atom"); - } - //formElm->setValueByName(); - return true; + return QIcon(); } -// CFormItem *CFormItem::add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot) -// { - // Add at the end -// uint index = _Children.size(); -// _Children.push_back (new CGeorgesEditDocSub); - -// _Children[index]->_Type = type; -// _Children[index]->_Name = name; -// _Children[index]->_Parent = this; -// _Children[index]->_StructId = structId; -// _Children[index]->_FormName = formName; -// _Children[index]->_Slot = slot; -// return _Children[index]; -// CFormItem *newNode = new CFormItem(); -// appendChild(newNode); -// return NULL; -// } - - CFormItem *CFormItem::add(NLGEORGES::UFormElm* root, std::string elmName) + CFormItem *CFormItem::add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr) { - CFormItem *newItem = NULL; - UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - // Append a new item to the current parent's list of children. -// std::string elmName; -// if(root->getStructNodeName(num, elmName)) -// { - QList columnData; - //QVariant value; - std::string value; - //NLMISC::CRGBA value_color; - //uint value_uint; - //sint value_sint; - //double value_double; - QString elmtType = ""; - UFormElm *elmt = 0; - if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) - { - if (elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) - elmtType = "Struct"; - if (elmt->isAtom()) - { - elmtType = "Atom"; - uint numDefinitions = 0; - const UType *type = elmt->getType(); - if (type) - { - numDefinitions = type->getNumDefinition(); - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (type->getType()) - { - case UType::UnsignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_uint");break; - case UType::SignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_sint");break; - case UType::Double: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); - elmtType.append("_double");break; - case UType::String: - elmtType.append("_string");break; - case UType::Color: - elmtType.append("_color");break; - default: - elmtType.append("_unknownType"); - } - } - else - { - elmtType.append("_noType"); - } - - if (numDefinitions) - { - std::string l, v; - QString tmpLabel, tmpValue; - for (uint i = 0; i < numDefinitions; i++) - { - type->getDefinition(i,l,v); - tmpLabel = l.c_str(); - tmpValue = v.c_str(); - if (type->getType() == UType::SignedInt) - { - if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { - value = l; - break; - } - } - if (type->getType() == UType::String) - { - if (QString(value.c_str()) == tmpValue) - { - value = l; - break; - } - } - } - } - } - if (elmt->isVirtualStruct()) - { - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - elmtType = "VirtualStruct"; - } - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - - newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); - this->appendChild(newItem); - - return newItem; - //if (parents.last()->childCount() > 0) { - // parents << parents.last()->child(parents.last()->childCount()-1); - //} - - // The building of the tree should be haoppening in the mode,. - //loadFormData(elmt, parent->child(parent->childCount()-1)); - } - else - { - // add Defaults - // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes - bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); - this->appendChild(newItem); - return newItem; - } -// } -// else -// { -// nlinfo("getNodeByName returned false"); -// } - } + CFormItem *newNode = new CFormItem(); + newNode->_Type = type; + newNode->_Name = name; + newNode->parentItem = this; + newNode->_StructId = structId; + newNode->_FormName = formName; + newNode->_Slot = slot; + newNode->m_form = formPtr; + + appendChild(newNode); + return newNode; } } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index c56422caf..e08a198bd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -1,76 +1,84 @@ -// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework -// Copyright (C) 2011 Adrian Jaekel -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef FORMITEM_H -#define FORMITEM_H - -// NeL includes -#include - -// Qt includes -#include -#include - -namespace GeorgesQt -{ - - class CFormItem - - { - public: - CFormItem(NLGEORGES::UFormElm *elm, const QList &data, - CFormItem *parent = 0, - NLGEORGES::UFormElm::TWhereIsValue wV = NLGEORGES::UFormElm::ValueForm, - NLGEORGES::UFormElm::TWhereIsNode wN = NLGEORGES::UFormElm::NodeForm); - ~CFormItem(); - - void appendChild(CFormItem *child); - //CFormItem *add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot); - CFormItem *add(NLGEORGES::UFormElm* root, std::string elmName); - - CFormItem *child(int row); - int childCount() const; - int columnCount() const; - QVariant data(int column) const; - int row() const; - CFormItem *parent(); - bool setData(int column, const QVariant &value); - NLGEORGES::UFormElm* getFormElm() {return formElm;} - NLGEORGES::UFormElm::TWhereIsValue valueFrom() - { - return whereV; - } - NLGEORGES::UFormElm::TWhereIsNode nodeFrom() - { - return whereN; - } - - void setValueFrom(NLGEORGES::UFormElm::TWhereIsValue wV) { whereV = wV; } - void setNodeFrom(NLGEORGES::UFormElm::TWhereIsNode wN) { whereN = wN; } - - - private: - //CFormItem() { whereV = NLGEORGES::UFormElm::ValueForm; whereN = NLGEORGES::UFormElm::NodeForm; } - QList childItems; - QList itemData; - CFormItem *parentItem; - NLGEORGES::UFormElm* formElm; - NLGEORGES::UFormElm::TWhereIsValue whereV; - NLGEORGES::UFormElm::TWhereIsNode whereN; - }; // CFormItem - -} -#endif // FORMITEM_H +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef FORMITEM_H +#define FORMITEM_H + +// NeL includes +#include +#include + +// Qt includes +#include +#include + +namespace GeorgesQt +{ + + class CFormItem + { + public: + // What is the sub object ? + enum TSub + { + Null, // Nothing in this node (root ?) + Header, // Header node + Type, // This node is a type + Dfn, // This node is a dfn + Form, // This node is a form + }; + + CFormItem(); + ~CFormItem(); + + void appendChild(CFormItem *child); + + CFormItem *add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr); + + CFormItem *child(int row); + int childCount() const; + int columnCount() const; + QVariant data(int column) const; + int row() const; + CFormItem *parent(); + bool setData(int column, const QVariant &value); + + TSub nodeType() { return _Type; } + std::string formName() { return _FormName; } + std::string name() { return _Name; } + uint structId() { return _StructId; } + + bool isEditable(int column); + + QIcon getItemImage(CFormItem *rootItem); + + private: + QList childItems; + QList itemData; + CFormItem *parentItem; + NLGEORGES::UFormElm* formElm; + NLGEORGES::UForm *m_form; + + uint _StructId; + std::string _Name; + std::string _FormName; + TSub _Type; + uint _Slot; + + }; // CFormItem + +} +#endif // FORMITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc index 3d514dbc0..8d71d1438 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc @@ -1,5 +1,12 @@ + images/array.ico + images/header.ico + images/hold.ico + images/root.ico + images/struct.ico + images/vstruct.ico + images/zfee51.ico images/ic_nel_georges_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index 92da6e8a0..aa289a4aa 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -72,23 +72,10 @@ namespace GeorgesQt m_ui.treeView->header()->setStretchLastSection(true); m_ui.treeViewTabWidget->setTabEnabled (2,false); - m_ui.checkBoxParent->setStyleSheet("background-color: rgba(0,255,0,30)"); - m_ui.checkBoxDefaults->setStyleSheet("background-color: rgba(255,0,0,30)"); m_form = 0; - FormDelegate *formdelegate = new FormDelegate(this); - m_ui.treeView->setItemDelegateForColumn(1, formdelegate); - - // Set up custom context menu. - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); - connect(m_ui.treeView, SIGNAL(doubleClicked (QModelIndex)), this, SLOT(doubleClicked (QModelIndex))); - connect(m_ui.checkBoxParent, SIGNAL(toggled(bool)), - this, SLOT(filterRows())); - connect(m_ui.checkBoxDefaults, SIGNAL(toggled(bool)), - this, SLOT(filterRows())); connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); } @@ -258,16 +245,9 @@ namespace GeorgesQt loadedForm = m_form->getFilename().c_str(); CGeorgesFormModel *model = new CGeorgesFormModel(m_form,deps,comments,parents,m_header->expanded()); - CGeorgesFormProxyModel *proxyModel = new CGeorgesFormProxyModel(); - proxyModel->setSourceModel(model); - m_ui.treeView->setModel(proxyModel); + m_ui.treeView->setModel(model); m_ui.treeView->expandAll(); - // this is a debug output row - m_ui.treeView->hideColumn(3); - - filterRows(); - // //_ui.treeView->setRowHidden(0,QModelIndex(),true); connect(model, SIGNAL(dataChanged(const QModelIndex, const QModelIndex)), this, SLOT(modifiedFile())); @@ -283,8 +263,7 @@ namespace GeorgesQt NLGEORGES::CForm *parentForm = dynamic_cast(uParentForm); NLGEORGES::CForm *mainForm = static_cast(m_form); - CGeorgesFormProxyModel * proxyModel = dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *model = dynamic_cast(proxyModel->sourceModel()); + CGeorgesFormModel *model = dynamic_cast(m_ui.treeView->model()); if(parentForm) { @@ -397,19 +376,15 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::doubleClicked ( const QModelIndex & index ) { - // TODO: this is messy :( perhaps this can be done better - CGeorgesFormProxyModel * proxyModel = - dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *model = - dynamic_cast(proxyModel->sourceModel()); - QModelIndex sourceIndex = proxyModel->mapToSource(index); + //CGeorgesFormModel *model = + // dynamic_cast((m_ui.treeView->model()); - CFormItem *item = model->getItem(sourceIndex); + //CFormItem *item = model->getItem(index); - if (item->parent() && item->parent()->data(0) == "parents") - { - Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toStdString(),false).c_str()); - } + //if (item->parent() && item->parent()->data(0) == "parents") + //{ + // Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toStdString(),false).c_str()); + //} //// col containing additional stuff like icons //if (index.column() == 2) @@ -475,129 +450,129 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::filterRows() { - CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); - if (m) { - m->setShowParents(m_ui.checkBoxParent->isChecked()); - m->setShowDefaults(m_ui.checkBoxDefaults->isChecked()); - } + //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); + //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); + //if (m) { + // m->setShowParents(m_ui.checkBoxParent->isChecked()); + // m->setShowDefaults(m_ui.checkBoxDefaults->isChecked()); + //} } void CGeorgesTreeViewDialog::showContextMenu(const QPoint &pos) { - QMenu contextMenu; - QMenu *structContext = NULL; - QPoint globalPos = this->mapToGlobal(pos); - - // Fisrt we're going to see if we've right clicked on a new item and select it. - const QModelIndex &index = this->m_ui.treeView->currentIndex(); - - if(!index.isValid()) - return; + //QMenu contextMenu; + //QMenu *structContext = NULL; + //QPoint globalPos = this->mapToGlobal(pos); + // + //// Fisrt we're going to see if we've right clicked on a new item and select it. + //const QModelIndex &index = this->m_ui.treeView->currentIndex(); - CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); - QModelIndex sourceIndex = mp->mapToSource(index); + //if(!index.isValid()) + // return; - if (m) - { - - CFormItem *item = m->getItem(sourceIndex); - - // Right click on the "parents" item - if (item->data(0) == "parents") - contextMenu.addAction("Add parent..."); - // Right click on a parent item - else if(item->parent() && item->parent()->data(0) == "parents") - { - contextMenu.addAction("Add parent..."); - contextMenu.addAction("Remove parent"); - } - else if(item->getFormElm()->isArray()) - contextMenu.addAction("Add array entry..."); - else if(item->getFormElm()->isStruct()) - { - QMenu *structContext = new QMenu("Add struct element...", this); - contextMenu.addMenu(structContext); + //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); + //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); + //QModelIndex sourceIndex = mp->mapToSource(index); - NLGEORGES::UFormDfn *defn = item->getFormElm()->getStructDfn(); - if(defn) - { - for(uint defnNum=0; defnNum < defn->getNumEntry(); defnNum++) - { - std::string entryName; - std::string dummy; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - bool result = defn->getEntryName(defnNum, entryName); - bool result2 = item->getFormElm()->getValueByName(dummy, entryName.c_str(), NLGEORGES::UFormElm::Eval, whereV); - - - if(result2 && *whereV != UFormElm::ValueForm) - { - structContext->addAction(entryName.c_str()); - } - delete whereV; - } - } - } - else if(item->getFormElm()->isAtom() && item->valueFrom() == NLGEORGES::UFormElm::ValueForm) - contextMenu.addAction("Revert to parent/default..."); + //if (m) + //{ + // + // CFormItem *item = m->getItem(sourceIndex); + + // // Right click on the "parents" item + // if (item->data(0) == "parents") + // contextMenu.addAction("Add parent..."); + // // Right click on a parent item + // else if(item->parent() && item->parent()->data(0) == "parents") + // { + // contextMenu.addAction("Add parent..."); + // contextMenu.addAction("Remove parent"); + // } + // else if(item->getFormElm()->isArray()) + // contextMenu.addAction("Add array entry..."); + // else if(item->getFormElm()->isStruct()) + // { + // QMenu *structContext = new QMenu("Add struct element...", this); + // contextMenu.addMenu(structContext); - QAction *selectedItem = contextMenu.exec(globalPos); - if(selectedItem) - { - if(selectedItem->text() == "Add parent...") - { - // Get the file extension of the form so we can build a dialog pattern. - QString file = m_form->getFilename().c_str(); - file = file.remove(0,file.indexOf(".")+1); - QString filePattern = "Parent Sheets (*."+file+")"; - - nlinfo("parent defn name '%s'", file.toStdString().c_str()); - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select parent sheets..."), m_lastSheetDir, filePattern); - if(!fileNames.isEmpty()) - { - Q_FOREACH(QString fileToParent, fileNames) - { - // Get just the filename. Georges doesn't want the path. - QFileInfo pathInfo( fileToParent ); - QString tmpFileName( pathInfo.fileName() ); - - nlinfo("requesting to add parent form '%s'", tmpFileName.toStdString().c_str()); - - // Call to add the form and load it into the Georges form. - addParentForm(tmpFileName); - - // Save the file lookup path for future dialog boxes. - m_lastSheetDir = pathInfo.absolutePath(); - } - } - m_ui.treeView->expandAll(); - } - else if(selectedItem->text() == "Remove parent") - { - NLGEORGES::CForm *form = static_cast(m_form); - QString parentFileName = item->data(0).toString(); + // NLGEORGES::UFormDfn *defn = item->getFormElm()->getStructDfn(); + // if(defn) + // { + // for(uint defnNum=0; defnNum < defn->getNumEntry(); defnNum++) + // { + // std::string entryName; + // std::string dummy; + // UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; + // bool result = defn->getEntryName(defnNum, entryName); + // bool result2 = item->getFormElm()->getValueByName(dummy, entryName.c_str(), NLGEORGES::UFormElm::Eval, whereV); + + // + // if(result2 && *whereV != UFormElm::ValueForm) + // { + // structContext->addAction(entryName.c_str()); + // } + // delete whereV; + // } + // } + // } + // else if(item->getFormElm()->isAtom() && item->valueFrom() == NLGEORGES::UFormElm::ValueForm) + // contextMenu.addAction("Revert to parent/default..."); - for(uint num = 0; num < form->getParentCount(); num++) - { - QString curParentName = form->getParent(num)->getFilename().c_str(); - if(parentFileName == curParentName) - { - form->removeParent(num); - m->removeParentForm(parentFileName); - break; - } - } + // QAction *selectedItem = contextMenu.exec(globalPos); + // if(selectedItem) + // { + // if(selectedItem->text() == "Add parent...") + // { + // // Get the file extension of the form so we can build a dialog pattern. + // QString file = m_form->getFilename().c_str(); + // file = file.remove(0,file.indexOf(".")+1); + // QString filePattern = "Parent Sheets (*."+file+")"; + // + // nlinfo("parent defn name '%s'", file.toStdString().c_str()); + // QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select parent sheets..."), m_lastSheetDir, filePattern); + // if(!fileNames.isEmpty()) + // { + // Q_FOREACH(QString fileToParent, fileNames) + // { + // // Get just the filename. Georges doesn't want the path. + // QFileInfo pathInfo( fileToParent ); + // QString tmpFileName( pathInfo.fileName() ); + + // nlinfo("requesting to add parent form '%s'", tmpFileName.toStdString().c_str()); + // + // // Call to add the form and load it into the Georges form. + // addParentForm(tmpFileName); + + // // Save the file lookup path for future dialog boxes. + // m_lastSheetDir = pathInfo.absolutePath(); + // } + // } + // m_ui.treeView->expandAll(); + // } + // else if(selectedItem->text() == "Remove parent") + // { + // NLGEORGES::CForm *form = static_cast(m_form); + // QString parentFileName = item->data(0).toString(); - m_ui.treeView->expandAll(); - } + // for(uint num = 0; num < form->getParentCount(); num++) + // { + // QString curParentName = form->getParent(num)->getFilename().c_str(); + // if(parentFileName == curParentName) + // { + // form->removeParent(num); + // m->removeParentForm(parentFileName); + // break; + // } + // } + + // m_ui.treeView->expandAll(); + // } - } // if selected context menu item is valid. - } // if 'm' model valid. + // } // if selected context menu item is valid. + //} // if 'm' model valid. - if(structContext) - delete structContext; + //if(structContext) + // delete structContext; } } /* namespace GeorgesQt */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui index 8d53bfdd6..0bf52a3ea 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 564 + 525 @@ -18,8 +18,8 @@ - 199 - 165 + 280 + 242 @@ -29,9 +29,21 @@ - + + + 0 + 0 + + + + + + 0 + 0 + + QTabWidget::West @@ -39,60 +51,40 @@ 0 - - Qt::NoFocus - Form - - - 0 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - true - - - - - - - Parent - - - - - + + + Qt::Horizontal - - - 40 - 20 - - - - - - - - Defaults - + + + + 0 + 0 + + + + + 0 + 0 + + + + true + + + + + + 0 + 0 + + + @@ -126,8 +118,14 @@ - - - + + + QtTreePropertyBrowser + QWidget +

qttreepropertybrowser.h
+ 1 + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index b8c9f56ff..9a329f396 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -53,7 +53,7 @@ namespace GeorgesQt { m_form = form; m_rootData << "Value" << "Data" << "Extra";// << "Type"; - m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_rootItem = new CFormItem(); m_dependencies = deps; m_comments = comment; m_parents = parents; @@ -81,144 +81,12 @@ namespace GeorgesQt { return getItem(p_index)->data(p_index.column()); } - case Qt::BackgroundRole: - { - QBrush defaultBrush = QBrush(QColor(255,0,0,30)); - QBrush parentBrush = QBrush(QColor(0,255,0,30)); - - // if elm not existing it must be some kind of default or type value - if(!getItem(p_index)->getFormElm()) - { - return defaultBrush; - } - - // else it might be some parent elm - switch (getItem(p_index)->nodeFrom()) - { - case NLGEORGES::UFormElm::NodeParentForm: - { - return parentBrush; - } - case NLGEORGES::UFormElm::NodeForm: - { - switch (getItem(p_index)->valueFrom()) - { - case NLGEORGES::UFormElm::ValueParentForm: - { - return parentBrush; - } - default: - { - // parent status test kindof ugly, testing only 2 steps deep - // only needed for colorization as treeview default hides childs - // when parent is hidden - CFormItem *parent = getItem(p_index)->parent(); - if (parent) - { - if (parent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - - CFormItem *parentParent = parent->parent(); - if (parentParent) - { - if (parentParent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - } // endif parentParent - } // endif parent - } // end default - } // end switch valueFrom - } // end case nodeForm - } // end switch nodeFrom - return QVariant(); - } - case Qt::DecorationRole: - { - if (p_index.column() == 2) - { - //p_index. - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - - QString value = item->data(1).toString(); - //QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - return QIcon(path); - } - } - return QVariant(); - break; - } - case Qt::ToolTipRole: - { - if (p_index.column() == 2) - { - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - QString value = item->data(1).toString(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - - QString imageTooltip = QString("").arg(path); - - return imageTooltip; - } - } - return QVariant(); - break; - } + case Qt::DecorationRole: + { + // Based on the _Type return a QIcon from resources. + CFormItem *item = getItem(p_index); + return item->getItemImage(m_rootItem); + } default: return QVariant(); } @@ -239,14 +107,17 @@ namespace GeorgesQt /******************************************************************************/ - bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, - int role) + bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role != Qt::EditRole) return false; + + CFormItem *item = getItem(index); - CFormItem *item = getItem(index); + if(!item->isEditable(index.column())) + return false; + bool result = item->setData(index.column(), value); Q_EMIT dataChanged(index, index); @@ -264,8 +135,12 @@ namespace GeorgesQt Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if(index.column() == 1) - returnValue |= Qt::ItemIsEditable; + CFormItem *item = getItem(index); + + if(item->isEditable(index.column())) + { + returnValue |= Qt::ItemIsEditable; + } return returnValue; @@ -383,223 +258,7 @@ namespace GeorgesQt /******************************************************************************/ void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) { - - if (!root) - return; - - uint num = 0; - - - if (root->isStruct()) - { - //((CFormElm*)root)->getForm()->getComment(); - uint structSize = 0; - root->getStructSize(structSize); - while (num < structSize) - { - UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - // Append a new item to the current parent's list of children. - std::string elmName; - if(root->getStructNodeName(num, elmName)) - { - QList columnData; - //QVariant value; - std::string value; - //NLMISC::CRGBA value_color; - //uint value_uint; - //sint value_sint; - //double value_double; - QString elmtType = ""; - UFormElm *elmt = 0; - if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) - { - if (elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) - elmtType = "Struct"; - if (elmt->isAtom()) - { - elmtType = "Atom"; - uint numDefinitions = 0; - const UType *type = elmt->getType(); - if (type) - { - numDefinitions = type->getNumDefinition(); - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (type->getType()) - { - case UType::UnsignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_uint");break; - case UType::SignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_sint");break; - case UType::Double: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); - elmtType.append("_double");break; - case UType::String: - elmtType.append("_string");break; - case UType::Color: - elmtType.append("_color");break; - default: - elmtType.append("_unknownType"); - } - } - else - { - elmtType.append("_noType"); - } - - if (numDefinitions) - { - std::string l, v; - QString tmpLabel, tmpValue; - for (uint i = 0; i < numDefinitions; i++) - { - type->getDefinition(i,l,v); - tmpLabel = l.c_str(); - tmpValue = v.c_str(); - if (type->getType() == UType::SignedInt) - { - if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { - value = l; - break; - } - } - if (type->getType() == UType::String) - { - if (QString(value.c_str()) == tmpValue) - { - value = l; - break; - } - } - } - } - } - if (elmt->isVirtualStruct()) - { - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - elmtType = "VirtualStruct"; - } - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - //if (parents.last()->childCount() > 0) { - // parents << parents.last()->child(parents.last()->childCount()-1); - //} - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - else - { - // add Defaults - // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes - bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - } - } - else - { - nlinfo("getNodeByName returned false"); - } - } - num++; - } - } - if (root->isArray()) - { - uint arraySize = 0; - root->getArraySize(arraySize); - while (num < arraySize) - { - std::string elmName; - if(root->getArrayNodeName(elmName, num)) - { - QList columnData; - std::string value; - QString elmtType = ""; - - UFormElm *elmt = 0; - if(root->getArrayNode(&elmt,0) && elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) { - elmtType = "Struct"; - } - if (elmt->isAtom()) - { - elmt->getValue(value); - elmtType = "Atom"; - } - if (elmt->isVirtualStruct()) - elmtType = "VirtualStruct"; - - elmtType.append("_arrayValue"); - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent)); - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - } - num++; - } - } + return; } CFormItem *CGeorgesFormModel::addStruct (CFormItem *parent, @@ -614,8 +273,9 @@ namespace GeorgesQt NLGEORGES::CForm *formPtr = static_cast(m_form); // Add the new node -// CFormItem *newNode = parent->add(/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); - CFormItem *newNode = parent->add(_struct, name); + CFormItem *newNode = parent->add(CFormItem::Form, name, structId, formName, slot, m_form); + + nlinfo("Added form %s : %s", name, formName); // Can be NULL in virtual DFN if (parentDfn) @@ -750,8 +410,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, uint slot) { // Add the new node - //CFormItem *newNode = parent->add (/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); - CFormItem *newNode = parent->add (array, name); + CFormItem *newNode = parent->add (CFormItem::Form, name, structId, formName, slot, m_form); // The array exist if (array) @@ -778,14 +437,13 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, if (rootDfn) { // Get struct ptr - NLGEORGES::CFormElmStruct *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; + NLGEORGES::CFormElmStruct *elmPtr = array->Elements[elm].Element ? static_cast(array->Elements[elm].Element) : NULL; addStruct (newNode, elmPtr, rootDfn, formArrayName, elm, formArrayElmName, slot); } else { - NLGEORGES::CFormElmArray *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; - newNode->add (elmPtr, formArrayElmName); - //newNode->add (/*CGeorgesEditDocSub::Form,*/ formArrayName, elm, formArrayElmName, slot); + NLGEORGES::CFormElmArray *elmPtr = array->Elements[elm].Element ? static_cast(array->Elements[elm].Element) : NULL; + newNode->add (CFormItem::Form, formArrayName, elm, formArrayElmName, slot, m_form); } } } @@ -800,7 +458,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, void CGeorgesFormModel::loadFormHeader() { - if (m_parents.size()) + /* if (m_parents.size()) { CFormItem *fi_pars = new CFormItem(m_rootElm, QList() << "parents" << "" << "", m_rootItem); m_rootItem->appendChild(fi_pars); @@ -809,7 +467,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, { fi_pars->appendChild(new CFormItem(m_rootElm, QList() << str << "" << "", fi_pars)); } - } + }*/ /*QStringList dfns = _dependencies["dfn"]; QStringList typs = _dependencies["typ"]; @@ -851,7 +509,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, { m_rootElm = &((NLGEORGES::CForm*)m_form)->Elements; NLGEORGES::CFormElmStruct *rootstruct = &((NLGEORGES::CForm*)m_form)->Elements; - loadFormHeader(); + //loadFormHeader(); addStruct(m_rootItem, rootstruct, rootstruct->FormDfn, "Content", 0xffffffff, "", 0); //loadFormData(m_rootElm, m_rootItem); } @@ -875,7 +533,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, beginResetModel(); m_parents.push_back(parentForm); delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_rootItem = new CFormItem(); setupModelData(); endResetModel(); } @@ -886,7 +544,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, m_parents.removeOne(parentForm); delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_rootItem = new CFormItem(); setupModelData(); endResetModel(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp index 8b13ca8ba..81179f61c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp @@ -23,6 +23,8 @@ #include "georgesform_proxy_model.h" #include "georgesform_model.h" +#if 0 + namespace GeorgesQt { @@ -78,4 +80,5 @@ namespace GeorgesQt } } /* namespace GeorgesQt */ +#endif // 0 /* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h index cfe7fcca6..f4c968f80 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h @@ -20,6 +20,7 @@ // Qt includes #include +#if 0 namespace GeorgesQt { @@ -41,5 +42,5 @@ namespace GeorgesQt };/* class CGeorgesFormProxyModel */ } /* namespace GeorgesQt */ - +#endif // 0 #endif // GEORGESFORM_PROXY_MODEL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico new file mode 100644 index 0000000000000000000000000000000000000000..923bec0bd09d868ebfdca30d953af70b87b2b084 GIT binary patch literal 1406 zcmd6mp=(@05XQfwDI6stF{dKhs78-ESKw5?6sr2(o87nH+nw+CX5W(roI5+JM68E~W@v_HUCZ?pM|X5b zcXUVZ%Nlw^ZwwlGL#I=q2YR3fLZBz(WSmjXMr-&RiHt?2RN2!Q3E!?a=0U}|_b9yXFRyc^!N9p#OVf5X4w-?ymY->6N4p~29oL*F*4Qg4q!PusVV z8U%g;Tfhq9NWMMMN z$>EG0j;!2$j_Z{^>GbqelgUJ9XJUsMx_2RDwvmTF)a~~hl{}<06o{r*q8a`~`>vfnu`}g<* Dvj*rN literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico new file mode 100644 index 0000000000000000000000000000000000000000..5ebb3632a07b0c55caa0d98e80995f28fed84db5 GIT binary patch literal 318 zcmZvXAr8YZ3`KvnsTrz@h6i`7qH3rL3tZ67m7^3DMulbBb6Qmcv-AJ6>^M@ShV1)Z z7SBey8UdQuTipC5~d;fm14_1Z`02Q7Kj-(pqL`xIjdy((fz>10+K5Q_gvD zZ{NY}f^UrjbK?vrxHzwF8OID;I1TLA3-C66UPFD(Y~#Nx{M9+6h=&q1&4*U@wu|%y D2y;=Y literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico new file mode 100644 index 0000000000000000000000000000000000000000..4b7f115f14d79bc4e7230fe0c3bcb20ef74c1230 GIT binary patch literal 318 zcmbu4p$>vE41~XBBuJ*vNc;?rS3zNa6wLigely1_^{p@@<2sNS!nJqTwQ06NP^6S_ z>;r7wMeppyz)A`>^qW*rQtR8KDls#;5Bf-Y_exZF%jJWZ2Z*H!3vr$_mS4}pALsc5 e8|~l9qpTOmhx;XGzqK`qMLk=8{*}J>Ji-eO5lbil literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico new file mode 100644 index 0000000000000000000000000000000000000000..3fa430766f5ef9080292ee358fc478f056ff4f5f GIT binary patch literal 318 zcmb7dGVc?i*Tas;^FM*`YIpgt6aCa4a z^AHkeF|@(|sDO%6Ld0r?LTgQijl#@3LFp@}-_UZc-ObA6+PQ=-%wt}{?_d8Kehr_= Wbc5Y?Wghd};{_kx-}Nt)({XHRBT$t9 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico new file mode 100644 index 0000000000000000000000000000000000000000..a184d8a37697585d06f3ed0083f5484f969decd1 GIT binary patch literal 318 zcmbV`F%rTs3RQ=mD#m(4qaKsyoTSu{w4ex ZKC|ftyY9*|=FQ^?AKl;eFO<`9ya8ugQ@sEH literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico new file mode 100644 index 0000000000000000000000000000000000000000..ad6bbb7564f9209ac1902598373a757275d144b4 GIT binary patch literal 2238 zcmZ`*3s}?j8h$5(!5GGH?0{o9hYCY(ZeSbAMMY4vU~*9jMNbSx%PVMs!6X5XAeTYJ zxM&?IAW+L;8W>GGqKU_V6wPjG7Uy*6B&VIuuhHS(Z;(8o^zC`~UEcTmewRJ}|1*F^ zKN1N>tkD(_(#VTKLJ>~E0xeS0vPazL7i-krG7aF?Kp(o8E?oJ(hk89)?{=f`UMKWj z4D`bcPTX!qbzd6}_co*US`8|$6r#5&A`KckGqvj~(!M=|l$-JFrd;xc*N}AWAQC$B5Ph)> zQ6H5cwdyL;oARNlszOpnCDf-1k#yn!)>P+1Ue$#s&*fwH`JH&KI|r$Bzp2KxNbKH+ zwHNmw{>m<_>fB1#lVizcPi#8787c2>LB^RF>^Zp<&$lOI+uQMUwg$0{Td=Y{8_Qd_ zV@bh}YnKIezTL<=DwI&r^}}idu&~At3o2v?e$@kkWwQ|aN+3cG`XHpl1FF24m|r*t zf%!AxQ|^tq#Zm-Ui?OhD29)JO1nNWxst_Qc#sLbQ1LQgmLW)FC6p5iIp?sbjX{ZK`0Tyai#zc zbHw1z=FomAL}C&6Vj+Y=S2*$caBks|Ct)=?^01X7kt()6i#x=(X9EX}ZQt2j2GSS^pq6+BzIn|xRHirs6kJM8Nu!={4Trf{o_gXzyF88$TxWaO6^EmE#*vvoy*>ho6WP`BiH7pJfGeDy@jVnC4`W#lb;+3Dma z*Oc+hu7j3?J!U`O?;@(6Ufm}{(!`kZ6AO=ICe@RsZzf%QL`XhY zxqW)P=Z^$LtWp_zLQnM4yLx2sXxeY!e9j3y6~h)x%9EQ0+t40^LC`)qt;xIoZqG@B zVbbZOU*jy)-0bfaU!M{)d4J3@XJPwwBAhZs*#G$c2wTvvSxlEE0yg_`0TIwm_usTM zl9Bk42@}pdA$deNF=ZZDF^rME3be?f;1K$E;SPN_7%8-)U{P;H!7`3=tY2wv(NfG{ tj4Xz^LuZgD80Oa;3hD`mVII(#gyO;Pyw>7rZj|IO2X^EzB^EKm{08(sjoSbK literal 0 HcmV?d00001 From c770c7ac78fb20a5e9147cd3a8b6583f22ace769 Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 27 Sep 2012 08:22:50 -0500 Subject: [PATCH 012/282] Added: #1306 Added undo/redo action for renaming array entry names --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/actions.cpp | 82 ++++++++++++++++++- .../src/plugins/georges_editor/actions.h | 23 ++++++ .../src/plugins/georges_editor/formitem.cpp | 60 ++++++++------ .../src/plugins/georges_editor/formitem.h | 5 ++ .../georges_editor/georges_editor_form.cpp | 7 +- .../georges_editor/georges_editor_form.h | 3 +- 6 files changed, 149 insertions(+), 31 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index dba45fb96..2a7780eb4 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -14,4 +14,84 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -#include "actions.h" \ No newline at end of file +// Project includes +#include "actions.h" +#include "formitem.h" + +// Qt includes + +// NeL includes +#include +#include +#include +#include +#include +#include +#include + +namespace GeorgesQt +{ + + CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent) + : QUndoCommand("Rename Form Array", parent), m_item(item), m_newValue(newValue), m_elementId(elementId) + { } + + void CUndoFormArrayRenameCommand::redo() + { + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool vdfnArray; + NLGEORGES::CForm *form=static_cast(m_item->form()); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + if (node) + { + nlinfo("doing array rename"); + NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); + if(array->Elements[m_elementId].Name.empty()) + { + m_oldValue.append("#"); + m_oldValue.append(QString("%1").arg(m_elementId)); + } + else + { + m_oldValue = array->Elements[m_elementId].Name.c_str(); + } + + array->Elements[m_elementId].Name = m_newValue.toStdString(); + m_item->setName(m_newValue.toStdString()); + } + + } + + void CUndoFormArrayRenameCommand::undo() + { + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool vdfnArray; + NLGEORGES::CForm *form=static_cast(m_item->form()); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + if (node) + { + NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); + //m_oldValue = array->Elements[m_elementId].Name.c_str(); + array->Elements[m_elementId].Name = m_oldValue.toStdString(); + m_item->setName(m_oldValue.toStdString()); + } + + } + +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h index c646adc72..c0e0d3b8e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -17,4 +17,27 @@ #ifndef ACTIONS_H #define ACTIONS_H +#include + +namespace GeorgesQt +{ + class CFormItem; + + class CUndoFormArrayRenameCommand : public QUndoCommand + { + public: + CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent = 0); + ~CUndoFormArrayRenameCommand() {} + + void redo(); + void undo(); + + protected: + CFormItem *m_item; + QString m_newValue; + QString m_oldValue; + uint m_elementId; + }; +} + #endif // ACTIONS_H \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index 98bffa7e2..39545afde 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -14,7 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +// Project includes #include "formitem.h" +#include "actions.h" +#include "georges_editor_form.h" // Qt includes #include @@ -81,34 +84,39 @@ namespace GeorgesQt bool CFormItem::setData(int column, const QVariant &value) { - if (column != 0) - return false; - - bool deleteInsert = false; - - - - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *parentNode; - NLGEORGES::UFormDfn::TEntryType type; - bool array; - bool parentVDfnArray; - NLGEORGES::CForm *form=static_cast(m_form); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); - - if (parentItem && parentItem->nodeType () == CFormItem::Form) + if(isEditable(column)) { - std::string newName = value.toString().toStdString(); - _Name = newName; - - // Create an action to update the form. + nlinfo("form item is editable."); + // Ensure that it is a child. + if (parentItem && parentItem->nodeType () == CFormItem::Form) + { + nlinfo("retrieving node information for data change."); + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *parentNode; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool parentVDfnArray; + NLGEORGES::CForm *form=static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + + // Lets check the parent first, for arrays. + nlverify ( elm->getNodeByName (parentItem->formName().c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, isArray, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(isArray && parentNode) + { + nlinfo( "is array and a child, generate rename command"); + CUndoFormArrayRenameCommand *cmd = new CUndoFormArrayRenameCommand(this,value.toString(), _StructId); + GeorgesEditorForm::UndoStack->push(cmd); + return true; + } + } } - return true; + + return false; } bool CFormItem::isEditable(int column) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index e08a198bd..2acda42bb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -58,9 +58,14 @@ namespace GeorgesQt TSub nodeType() { return _Type; } std::string formName() { return _FormName; } + std::string name() { return _Name; } + void setName(std::string name) { _Name = name; } + uint structId() { return _StructId; } + NLGEORGES::UForm *form() { return m_form; } + bool isEditable(int column); QIcon getItemImage(CFormItem *rootItem); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp index a36f411e0..f42d6bc6b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp @@ -35,6 +35,7 @@ namespace GeorgesQt { + QUndoStack *GeorgesEditorForm::UndoStack = NULL; GeorgesEditorForm::GeorgesEditorForm(QWidget *parent) : QMainWindow(parent), @@ -61,7 +62,7 @@ namespace GeorgesQt m_mainDock->setDockNestingEnabled(true); layout->addWidget(m_mainDock); - m_undoStack = new QUndoStack(this); + UndoStack = new QUndoStack(this); Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); m_openAction = menuManager->action(Core::Constants::OPEN); @@ -114,7 +115,7 @@ namespace GeorgesQt QUndoStack *GeorgesEditorForm::undoStack() const { - return m_undoStack; + return UndoStack; } void GeorgesEditorForm::open() @@ -211,7 +212,7 @@ namespace GeorgesQt } CGeorgesTreeViewDialog *dock = new CGeorgesTreeViewDialog(m_mainDock); - dock->setUndoStack(m_undoStack); + dock->setUndoStack(UndoStack); m_lastActiveDock = dock; m_dockedWidgets.append(dock); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h index 77fdd1ec8..c9cef964c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h @@ -38,6 +38,8 @@ public: QUndoStack *undoStack() const; + static QUndoStack *UndoStack; + public Q_SLOTS: void open(); void loadFile(const QString fileName); @@ -54,7 +56,6 @@ private: void readSettings(); void writeSettings(); - QUndoStack *m_undoStack; Ui::GeorgesEditorForm m_ui; CGeorgesDirTreeDialog *m_georgesDirTreeDialog; From cc5e8c043ef8c9a0d42ce48df3d1e0d778e85f11 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 28 Sep 2012 07:33:51 -0500 Subject: [PATCH 013/282] Changed: #1306 Moved creation of undo command for form array renames to the model. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/actions.cpp | 100 +++++++++++------- .../src/plugins/georges_editor/actions.h | 10 +- .../src/plugins/georges_editor/formitem.cpp | 33 +----- .../georges_editor/georgesform_model.cpp | 7 +- .../georges_editor/georgesform_model.h | 5 +- 5 files changed, 80 insertions(+), 75 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index 2a7780eb4..a55bc389a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -17,9 +17,11 @@ // Project includes #include "actions.h" #include "formitem.h" +#include "georgesform_model.h" // Qt includes + // NeL includes #include #include @@ -32,12 +34,30 @@ namespace GeorgesQt { - CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent) - : QUndoCommand("Rename Form Array", parent), m_item(item), m_newValue(newValue), m_elementId(elementId) - { } + CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent) + : QUndoCommand(parent), m_model(model), m_elementId(elementId) + { + m_row = index.row(); + m_col = index.column(); + + m_newValue = value.toString(); + } void CUndoFormArrayRenameCommand::redo() { + update(true); + } + + void CUndoFormArrayRenameCommand::undo() + { + update(false); + } + + void CUndoFormArrayRenameCommand::update(bool redo) + { + QModelIndex index = m_model->index(m_row, m_col); + CFormItem *item = m_model->getItem(index); + // Get the parent node const NLGEORGES::CFormDfn *parentDfn; uint indexDfn; @@ -47,13 +67,33 @@ namespace GeorgesQt NLGEORGES::UFormDfn::TEntryType type; bool isArray; bool vdfnArray; - NLGEORGES::CForm *form=static_cast(m_item->form()); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + NLGEORGES::CForm *form=static_cast(item->form()); + if(!form) + { + nlinfo("failed to convert form."); + return; + } + + NLGEORGES::CFormElm *elm = static_cast(&form->Elements); + + if(!elm) + nlwarning("Failed to convert elm!"); + + nlverify ( elm->getNodeByName (item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); if (node) { - nlinfo("doing array rename"); - NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); + std::string tmpName; + node->getFormName(tmpName); + nlinfo("doing array rename on '%s'", tmpName.c_str()); + + NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); + if(!array) + nlwarning("the array is invalid."); + + // In the redo stage save the old value, just in case. + if(redo) + { + // If the name of the element is empty then give it a nice default. if(array->Elements[m_elementId].Name.empty()) { m_oldValue.append("#"); @@ -61,37 +101,21 @@ namespace GeorgesQt } else { - m_oldValue = array->Elements[m_elementId].Name.c_str(); + m_oldValue = QString::fromStdString(array->Elements[m_elementId].Name); } + } - array->Elements[m_elementId].Name = m_newValue.toStdString(); - m_item->setName(m_newValue.toStdString()); - } - - } - - void CUndoFormArrayRenameCommand::undo() - { - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *node; - NLGEORGES::UFormDfn::TEntryType type; - bool isArray; - bool vdfnArray; - NLGEORGES::CForm *form=static_cast(m_item->form()); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); - if (node) - { - NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); - //m_oldValue = array->Elements[m_elementId].Name.c_str(); - array->Elements[m_elementId].Name = m_oldValue.toStdString(); - m_item->setName(m_oldValue.toStdString()); - } - + QString value; + if(redo) + value = m_newValue; + else + value = m_oldValue; + + + array->Elements[m_elementId].Name = value.toStdString(); + item->setName(value.toStdString()); + + m_model->emitDataChanged(index); + } } - } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h index c0e0d3b8e..43a19257d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -18,22 +18,28 @@ #define ACTIONS_H #include +#include namespace GeorgesQt { class CFormItem; + class CGeorgesFormModel; class CUndoFormArrayRenameCommand : public QUndoCommand { public: - CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent = 0); + CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent = 0); ~CUndoFormArrayRenameCommand() {} void redo(); void undo(); + void update(bool redo); + protected: - CFormItem *m_item; + int m_row, m_col; + CGeorgesFormModel *m_model; + QString m_newValue; QString m_oldValue; uint m_elementId; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index 39545afde..f053719c2 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -84,38 +84,7 @@ namespace GeorgesQt bool CFormItem::setData(int column, const QVariant &value) { - if(isEditable(column)) - { - nlinfo("form item is editable."); - // Ensure that it is a child. - if (parentItem && parentItem->nodeType () == CFormItem::Form) - { - nlinfo("retrieving node information for data change."); - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *parentNode; - NLGEORGES::UFormDfn::TEntryType type; - bool isArray; - bool parentVDfnArray; - NLGEORGES::CForm *form=static_cast(m_form); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - - // Lets check the parent first, for arrays. - nlverify ( elm->getNodeByName (parentItem->formName().c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, isArray, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); - - if(isArray && parentNode) - { - nlinfo( "is array and a child, generate rename command"); - CUndoFormArrayRenameCommand *cmd = new CUndoFormArrayRenameCommand(this,value.toString(), _StructId); - GeorgesEditorForm::UndoStack->push(cmd); - return true; - } - } - } - + nlwarning("This should not be called anymore."); return false; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index 9a329f396..b9511231b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -42,6 +42,8 @@ // project includes #include "formitem.h" +#include "georges_editor_form.h" +#include "actions.h" using namespace NLGEORGES; @@ -118,12 +120,13 @@ namespace GeorgesQt if(!item->isEditable(index.column())) return false; - bool result = item->setData(index.column(), value); + //bool result = item->setData(index.column(), value); + GeorgesEditorForm::UndoStack->push(new CUndoFormArrayRenameCommand(this,index,value,item->structId())); Q_EMIT dataChanged(index, index); //setupModelData(); - return result; + return true; } /******************************************************************************/ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h index 493f672dd..6c6c2817d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h @@ -40,7 +40,6 @@ namespace GeorgesQt class CGeorgesFormModel : public QAbstractItemModel { - public: CGeorgesFormModel(NLGEORGES::UForm *form, QMap< QString, QStringList> deps, QString comment, QStringList parents, bool* expanded, QObject *parent = 0); @@ -70,6 +69,10 @@ namespace GeorgesQt CFormItem *addArray(CFormItem *parent, NLGEORGES::CFormElmArray *array, NLGEORGES::CFormDfn *rootDfn, const char *name, uint structId, const char *formName, uint slot); + void emitDataChanged(const QModelIndex &index) + { + Q_EMIT dataChanged(index, index); + } private: void setupModelData(); void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent); From 6560f0c4735e6367ee3852ec98ec224b66c5593e Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 28 Sep 2012 09:50:44 -0500 Subject: [PATCH 014/282] Changed: #1306 Fixed index bug with form array rename. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/actions.cpp | 40 +++++-------------- .../src/plugins/georges_editor/actions.h | 5 +-- .../georges_editor/georgesform_model.cpp | 15 ++++--- .../georges_editor/georgesform_model.h | 1 + 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index a55bc389a..9fe3b0fa6 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -34,12 +34,9 @@ namespace GeorgesQt { - CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent) - : QUndoCommand(parent), m_model(model), m_elementId(elementId) + CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, CFormItem *item, const QVariant &value, QUndoCommand *parent) + : QUndoCommand("Rename Form Array Member", parent), m_model(model), m_item(item) { - m_row = index.row(); - m_col = index.column(); - m_newValue = value.toString(); } @@ -54,10 +51,7 @@ namespace GeorgesQt } void CUndoFormArrayRenameCommand::update(bool redo) - { - QModelIndex index = m_model->index(m_row, m_col); - CFormItem *item = m_model->getItem(index); - + { // Get the parent node const NLGEORGES::CFormDfn *parentDfn; uint indexDfn; @@ -67,41 +61,29 @@ namespace GeorgesQt NLGEORGES::UFormDfn::TEntryType type; bool isArray; bool vdfnArray; - NLGEORGES::CForm *form=static_cast(item->form()); - if(!form) - { - nlinfo("failed to convert form."); - return; - } - + NLGEORGES::CForm *form=static_cast(m_item->form()); NLGEORGES::CFormElm *elm = static_cast(&form->Elements); - if(!elm) - nlwarning("Failed to convert elm!"); - - nlverify ( elm->getNodeByName (item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); if (node) { std::string tmpName; node->getFormName(tmpName); - nlinfo("doing array rename on '%s'", tmpName.c_str()); NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); - if(!array) - nlwarning("the array is invalid."); // In the redo stage save the old value, just in case. if(redo) { // If the name of the element is empty then give it a nice default. - if(array->Elements[m_elementId].Name.empty()) + if(array->Elements[m_item->structId()].Name.empty()) { m_oldValue.append("#"); - m_oldValue.append(QString("%1").arg(m_elementId)); + m_oldValue.append(QString("%1").arg(m_item->structId())); } else { - m_oldValue = QString::fromStdString(array->Elements[m_elementId].Name); + m_oldValue = QString::fromStdString(array->Elements[m_item->structId()].Name); } } @@ -112,10 +94,10 @@ namespace GeorgesQt value = m_oldValue; - array->Elements[m_elementId].Name = value.toStdString(); - item->setName(value.toStdString()); + array->Elements[m_item->structId()].Name = value.toStdString(); + m_item->setName(value.toStdString()); - m_model->emitDataChanged(index); + m_model->emitDataChanged(m_model->index(m_item->row(), 0, m_item)); } } } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h index 43a19257d..0c57b0577 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -28,7 +28,7 @@ namespace GeorgesQt class CUndoFormArrayRenameCommand : public QUndoCommand { public: - CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent = 0); + CUndoFormArrayRenameCommand(CGeorgesFormModel *model, CFormItem *item, const QVariant &value, QUndoCommand *parent = 0); ~CUndoFormArrayRenameCommand() {} void redo(); @@ -37,12 +37,11 @@ namespace GeorgesQt void update(bool redo); protected: - int m_row, m_col; + CFormItem *m_item; CGeorgesFormModel *m_model; QString m_newValue; QString m_oldValue; - uint m_elementId; }; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index b9511231b..387bc8917 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -119,9 +119,8 @@ namespace GeorgesQt if(!item->isEditable(index.column())) return false; - - //bool result = item->setData(index.column(), value); - GeorgesEditorForm::UndoStack->push(new CUndoFormArrayRenameCommand(this,index,value,item->structId())); + + GeorgesEditorForm::UndoStack->push(new CUndoFormArrayRenameCommand(this,item,value)); Q_EMIT dataChanged(index, index); @@ -214,6 +213,14 @@ namespace GeorgesQt return QModelIndex(); } + QModelIndex CGeorgesFormModel::index(int row, int column, CFormItem *item) const + { + if(item == m_rootItem) + return QModelIndex(); + + return createIndex(row, 0, item); + } + /******************************************************************************/ QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const @@ -278,8 +285,6 @@ namespace GeorgesQt // Add the new node CFormItem *newNode = parent->add(CFormItem::Form, name, structId, formName, slot, m_form); - nlinfo("Added form %s : %s", name, formName); - // Can be NULL in virtual DFN if (parentDfn) { diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h index 6c6c2817d..07589b63c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h @@ -50,6 +50,7 @@ namespace GeorgesQt Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int row, int column, CFormItem *item) const; QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; From f7ffb4b8656f1e2ceb6115ac7d9ff88565a2e21a Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 18 Oct 2012 20:56:31 -0500 Subject: [PATCH 015/282] GEQt Plugin: Starting to add the context menu back. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/formitem.cpp | 31 +++++++++++++- .../src/plugins/georges_editor/formitem.h | 2 + .../georges_treeview_dialog.cpp | 42 ++++++++++--------- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index f053719c2..9281bad2e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -98,6 +98,36 @@ namespace GeorgesQt if (column != 0) return false; + if(isArrayMember()) + return true; + + return false; + } + + bool CFormItem::isArray() + { + // If it wasn't a root node then lets check the node type. + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form = static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, + &nodeDfn, &nodeType, &node, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(array && node) + return true; + + return false; + } + + bool CFormItem::isArrayMember() + { CFormItem *parent = this->parent(); // If it wasn't a root node then lets check the node type. @@ -118,7 +148,6 @@ namespace GeorgesQt return true; return false; - } QIcon CFormItem::getItemImage(CFormItem *rootItem) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index 2acda42bb..258a339db 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -67,6 +67,8 @@ namespace GeorgesQt NLGEORGES::UForm *form() { return m_form; } bool isEditable(int column); + bool isArray(); + bool isArrayMember(); QIcon getItemImage(CFormItem *rootItem); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index aa289a4aa..c058e6a20 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -460,26 +460,23 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::showContextMenu(const QPoint &pos) { - //QMenu contextMenu; - //QMenu *structContext = NULL; - //QPoint globalPos = this->mapToGlobal(pos); - // - //// Fisrt we're going to see if we've right clicked on a new item and select it. - //const QModelIndex &index = this->m_ui.treeView->currentIndex(); + QMenu contextMenu; + QMenu *structContext = NULL; + QPoint globalPos = this->mapToGlobal(pos); - //if(!index.isValid()) - // return; + // Fisrt we're going to see if we've right clicked on a new item and select it. + const QModelIndex &index = this->m_ui.treeView->currentIndex(); - //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); - //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); - //QModelIndex sourceIndex = mp->mapToSource(index); + if(!index.isValid()) + return; - //if (m) - //{ - // - // CFormItem *item = m->getItem(sourceIndex); + CGeorgesFormModel *m = dynamic_cast(m_ui.treeView->model()); + + if(m) + { + CFormItem *item = m->getItem(index); - // // Right click on the "parents" item + // Right click on the "parents" item // if (item->data(0) == "parents") // contextMenu.addAction("Add parent..."); // // Right click on a parent item @@ -488,8 +485,15 @@ namespace GeorgesQt // contextMenu.addAction("Add parent..."); // contextMenu.addAction("Remove parent"); // } - // else if(item->getFormElm()->isArray()) - // contextMenu.addAction("Add array entry..."); + if(item->isArray()) + { + contextMenu.addAction("Append array entry..."); + } + else if(item->isArrayMember()) + { + contextMenu.addAction("Delete array entry..."); + contextMenu.addAction("Insert after array entry..."); + } // else if(item->getFormElm()->isStruct()) // { // QMenu *structContext = new QMenu("Add struct element...", this); @@ -569,7 +573,7 @@ namespace GeorgesQt // } // } // if selected context menu item is valid. - //} // if 'm' model valid. + } // if 'm' model valid. //if(structContext) // delete structContext; From c5cafc7accaaec1e5d647abbf743ad057397ef42 Mon Sep 17 00:00:00 2001 From: mattraykowski Date: Sun, 21 Oct 2012 13:48:02 -0700 Subject: [PATCH 016/282] Changed: Enabled custom context menu signal to open a menu at the mouse position. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/formitem.h | 182 +++++++++--------- .../georges_treeview_dialog.cpp | 6 +- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index 258a339db..cc2dafece 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -1,91 +1,91 @@ -// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework -// Copyright (C) 2011 Adrian Jaekel -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef FORMITEM_H -#define FORMITEM_H - -// NeL includes -#include -#include - -// Qt includes -#include -#include - -namespace GeorgesQt -{ - - class CFormItem - { - public: - // What is the sub object ? - enum TSub - { - Null, // Nothing in this node (root ?) - Header, // Header node - Type, // This node is a type - Dfn, // This node is a dfn - Form, // This node is a form - }; - - CFormItem(); - ~CFormItem(); - - void appendChild(CFormItem *child); - - CFormItem *add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr); - - CFormItem *child(int row); - int childCount() const; - int columnCount() const; - QVariant data(int column) const; - int row() const; - CFormItem *parent(); - bool setData(int column, const QVariant &value); - - TSub nodeType() { return _Type; } - std::string formName() { return _FormName; } - - std::string name() { return _Name; } - void setName(std::string name) { _Name = name; } - - uint structId() { return _StructId; } - - NLGEORGES::UForm *form() { return m_form; } - - bool isEditable(int column); - bool isArray(); - bool isArrayMember(); - - QIcon getItemImage(CFormItem *rootItem); - - private: - QList childItems; - QList itemData; - CFormItem *parentItem; - NLGEORGES::UFormElm* formElm; - NLGEORGES::UForm *m_form; - - uint _StructId; - std::string _Name; - std::string _FormName; - TSub _Type; - uint _Slot; - - }; // CFormItem - -} -#endif // FORMITEM_H +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef FORMITEM_H +#define FORMITEM_H + +// NeL includes +#include +#include + +// Qt includes +#include +#include + +namespace GeorgesQt +{ + + class CFormItem + { + public: + // What is the sub object ? + enum TSub + { + Null, // Nothing in this node (root ?) + Header, // Header node + Type, // This node is a type + Dfn, // This node is a dfn + Form, // This node is a form + }; + + CFormItem(); + ~CFormItem(); + + void appendChild(CFormItem *child); + + CFormItem *add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr); + + CFormItem *child(int row); + int childCount() const; + int columnCount() const; + QVariant data(int column) const; + int row() const; + CFormItem *parent(); + bool setData(int column, const QVariant &value); + + TSub nodeType() { return _Type; } + std::string formName() { return _FormName; } + + std::string name() { return _Name; } + void setName(std::string name) { _Name = name; } + + uint structId() { return _StructId; } + + NLGEORGES::UForm *form() { return m_form; } + + bool isEditable(int column); + bool isArray(); + bool isArrayMember(); + + QIcon getItemImage(CFormItem *rootItem); + + private: + QList childItems; + QList itemData; + CFormItem *parentItem; + NLGEORGES::UFormElm* formElm; + NLGEORGES::UForm *m_form; + + uint _StructId; + std::string _Name; + std::string _FormName; + TSub _Type; + uint _Slot; + + }; // CFormItem + +} +#endif // FORMITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index c058e6a20..b2db0edb1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -74,6 +74,10 @@ namespace GeorgesQt m_form = 0; + m_ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(m_ui.treeView, SIGNAL(customContextMenuRequested(const QPoint&)), + this, SLOT(showContextMenu(const QPoint&))); connect(m_ui.treeView, SIGNAL(doubleClicked (QModelIndex)), this, SLOT(doubleClicked (QModelIndex))); connect(m_header, SIGNAL(headerClicked(int)), @@ -522,7 +526,7 @@ namespace GeorgesQt // else if(item->getFormElm()->isAtom() && item->valueFrom() == NLGEORGES::UFormElm::ValueForm) // contextMenu.addAction("Revert to parent/default..."); - // QAction *selectedItem = contextMenu.exec(globalPos); + QAction *selectedItem = contextMenu.exec(QCursor::pos()); // if(selectedItem) // { // if(selectedItem->text() == "Add parent...") From a45cf415c326c2075e4a159b8f540b8d2a54127d Mon Sep 17 00:00:00 2001 From: mattraykowski Date: Sun, 21 Oct 2012 13:58:44 -0700 Subject: [PATCH 017/282] Changed: if-statements for context menu selection - no logic --HG-- branch : branch-features-geqt-plugin --- .../georges_treeview_dialog.cpp | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index b2db0edb1..690e5106b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -491,7 +491,7 @@ namespace GeorgesQt // } if(item->isArray()) { - contextMenu.addAction("Append array entry..."); + contextMenu.addAction("Append array entry..."); } else if(item->isArrayMember()) { @@ -527,8 +527,23 @@ namespace GeorgesQt // contextMenu.addAction("Revert to parent/default..."); QAction *selectedItem = contextMenu.exec(QCursor::pos()); - // if(selectedItem) - // { + if(selectedItem) + { + if(selectedItem->text() == "Append array entry...") + { + + + } // Append an array entry... + else if(selectedItem->text() == "Delete array entry...") + { + + } + else if(selectedItem->text() == "Insert after array entry...") + { + + } + + // if(selectedItem->text() == "Add parent...") // { // // Get the file extension of the form so we can build a dialog pattern. @@ -576,7 +591,7 @@ namespace GeorgesQt // m_ui.treeView->expandAll(); // } - // } // if selected context menu item is valid. + } // if selected context menu item is valid. } // if 'm' model valid. //if(structContext) From fd5d961ba758ccd37215c822b4a748cc755b5110 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Apr 2014 00:49:17 +0200 Subject: [PATCH 018/282] Build fixes. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/georges_editor/actions.cpp | 6 +-- .../georges_treeview_dialog.cpp | 46 +++++++++---------- .../src/plugins/tile_editor/tile_item.cpp | 4 +- .../plugins/tile_editor/tile_item_delegate.h | 2 - 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index 9fe3b0fa6..c96bca95c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -83,7 +83,7 @@ namespace GeorgesQt } else { - m_oldValue = QString::fromStdString(array->Elements[m_item->structId()].Name); + m_oldValue = QString(array->Elements[m_item->structId()].Name.c_str()); } } @@ -94,8 +94,8 @@ namespace GeorgesQt value = m_oldValue; - array->Elements[m_item->structId()].Name = value.toStdString(); - m_item->setName(value.toStdString()); + array->Elements[m_item->structId()].Name = value.toAscii().data(); + m_item->setName(value.toAscii().data()); m_model->emitDataChanged(m_model->index(m_item->row(), 0, m_item)); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index fa417019b..f1819f52a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -108,30 +108,30 @@ namespace GeorgesQt NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByName(const QString formName) { - if(NLMISC::CPath::exists(formName.toStdString())) + if(NLMISC::CPath::exists(formName.toAscii().data())) { - //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toStdString())); - return (NLGEORGES::CForm *)m_georges->loadForm(formName.toStdString()); + //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toAscii().data())); + return (NLGEORGES::CForm *)m_georges->loadForm(formName.toAscii().data()); } //else //{ // CForm *form = 0; // // Load the DFN - // std::string extStr = NLMISC::CFile::getExtension( formName.toStdString() ); + // std::string extStr = NLMISC::CFile::getExtension( formName.toAscii().data() ); // QString dfnName = QString("%1.dfn").arg(extStr.c_str()); // UFormDfn *formdfn; - // if (NLMISC::CPath::exists(dfnName.toStdString())) + // if (NLMISC::CPath::exists(dfnName.toAscii().data())) // { - // formdfn = _georges->loadFormDfn (dfnName.toStdString()); + // formdfn = _georges->loadFormDfn (dfnName.toAscii().data()); // if (!formdfn) // { - // nlwarning("Failed to load dfn: %s", dfnName.toStdString().c_str()); + // nlwarning("Failed to load dfn: %s", dfnName.toAscii().data()); // return 0; // } // } // else // { - // nlwarning("Cannot find dfn: %s", dfnName.toStdString().c_str()); + // nlwarning("Cannot find dfn: %s", dfnName.toAscii().data()); // return 0; // } @@ -147,20 +147,20 @@ namespace GeorgesQt // } // return form; //} - nlinfo("File '%s' does not exist!", formName.toStdString().c_str()); + nlinfo("File '%s' does not exist!", formName.toAscii().data()); return 0; } NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByDfnName(const QString dfnName) { - if(NLMISC::CPath::exists(dfnName.toStdString())) + if(NLMISC::CPath::exists(dfnName.toAscii().data())) { // Create a new form object. NLGEORGES::CForm *form = new NLGEORGES::CForm(); m_form = form; // Retrieve a copy of the root definition. - NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toStdString())); + NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toAscii().data())); // Next we'll use the root node to build a new form. NLGEORGES::CFormElmStruct *fes = dynamic_cast(getRootNode(0)); @@ -175,7 +175,7 @@ namespace GeorgesQt return form; } - nlinfo("File '%s' does not exist!", dfnName.toStdString().c_str()); + nlinfo("File '%s' does not exist!", dfnName.toAscii().data()); return NULL; } @@ -243,7 +243,7 @@ namespace GeorgesQt nlinfo("typ's %d",deps["typ"].count()); nlinfo("dfn's %d",deps["dfn"].count()); - //nlwarning(strList.join(";").toStdString().c_str()); + //nlwarning(strList.join(";").toAscii().data()); if (root) { loadedForm = m_form->getFilename().c_str(); @@ -263,7 +263,7 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::addParentForm(QString parentFormNm) { // Try to load the form - NLGEORGES::UForm *uParentForm = m_georges->loadForm(parentFormNm.toStdString()); + NLGEORGES::UForm *uParentForm = m_georges->loadForm(parentFormNm.toAscii().data()); NLGEORGES::CForm *parentForm = dynamic_cast(uParentForm); NLGEORGES::CForm *mainForm = static_cast(m_form); @@ -277,11 +277,11 @@ namespace GeorgesQt if (parentForm->Elements.FormDfn == mainForm->Elements.FormDfn) { // This is the parent form selector - if(!mainForm->insertParent(mainForm->getParentCount(),parentFormNm.toStdString().c_str(), parentForm)) - nlwarning("Failed to add parent form: %s", parentFormNm.toStdString().c_str()); + if(!mainForm->insertParent(mainForm->getParentCount(),parentFormNm.toAscii().data(), parentForm)) + nlwarning("Failed to add parent form: %s", parentFormNm.toAscii().data()); else { - nlinfo("Successfullyadded parent form: %s", parentFormNm.toStdString().c_str()); + nlinfo("Successfullyadded parent form: %s", parentFormNm.toAscii().data()); model->addParentForm(parentFormNm); } } @@ -303,7 +303,7 @@ namespace GeorgesQt { NLMISC::COFile file; - std::string s = NLMISC::CPath::lookup(loadedForm.toStdString(), false); + std::string s = NLMISC::CPath::lookup(loadedForm.toAscii().data(), false); if(file.open (s)) { try @@ -387,7 +387,7 @@ namespace GeorgesQt //if (item->parent() && item->parent()->data(0) == "parents") //{ - // Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toStdString(),false).c_str()); + // Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toAscii().data(),false).c_str()); //} //// col containing additional stuff like icons @@ -397,7 +397,7 @@ namespace GeorgesQt // CFormItem *item = m->getItem(in2); // QString value = item->data(1).toString(); - // QString path = CPath::lookup(value.toStdString(),false).c_str(); + // QString path = CPath::lookup(value.toAscii().data(),false).c_str(); // if(value.contains(".tga") || value.contains(".png")) // { @@ -425,7 +425,7 @@ namespace GeorgesQt // { // Modules::objViewInt()->resetScene(); // //Modules::config().configRemapExtensions(); - // Modules::objViewInt()->loadMesh(path.toStdString(),""); + // Modules::objViewInt()->loadMesh(path.toAscii().data(),""); // } // return; // } @@ -551,7 +551,7 @@ namespace GeorgesQt // file = file.remove(0,file.indexOf(".")+1); // QString filePattern = "Parent Sheets (*."+file+")"; // - // nlinfo("parent defn name '%s'", file.toStdString().c_str()); + // nlinfo("parent defn name '%s'", file.toAscii().data()); // QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select parent sheets..."), m_lastSheetDir, filePattern); // if(!fileNames.isEmpty()) // { @@ -561,7 +561,7 @@ namespace GeorgesQt // QFileInfo pathInfo( fileToParent ); // QString tmpFileName( pathInfo.fileName() ); - // nlinfo("requesting to add parent form '%s'", tmpFileName.toStdString().c_str()); + // nlinfo("requesting to add parent form '%s'", tmpFileName.toAscii().data()); // // // Call to add the form and load it into the Georges form. // addParentForm(tmpFileName); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index fcd14a61b..9d9418561 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -223,7 +223,7 @@ TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString { m_tileFilename[channel] = filename; m_parentItem = parent; - //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); + //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); } TileItemNode::~TileItemNode() @@ -255,7 +255,7 @@ QVariant TileItemNode::data(int column, int role) const QPixmap pixmap;// = new QPixmap(); if(!pixmap.load(tileFilename)) - nlinfo("failed to load %s", tileFilename.toStdString().c_str()); + nlinfo("failed to load %s", tileFilename.toAscii().data()); if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) tileSize *= 2; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h index 1b7058b48..90c831fb8 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h @@ -20,8 +20,6 @@ #include #include -#include "ui_tile_widget.h" - #include class TileItemDelegate : public QStyledItemDelegate From 4f39a58e310a073f7e87b4840356f5b54cf04fff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Apr 2014 02:10:14 +0200 Subject: [PATCH 019/282] Tile Editor crash fixes. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 2 -- .../src/plugins/tile_editor/tile_editor_plugin.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 930ae9d8b..d1199ebc9 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -147,8 +147,6 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_ui; delete m_undoStack; delete m_rotationMenu; - delete m_zoomMenu; - delete m_tileDisplayMenu; delete m_tileEditorMenu; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h index 2398be2c4..cb7be7fc1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h @@ -68,7 +68,7 @@ public: virtual ~TileEditorContext() { - delete m_tileEditorMainWindow; + m_tileEditorMainWindow = NULL; } virtual QString id() const From 91f859bc8a2a2509e85bcd0ad04b0e39bdd3fbf0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 6 May 2014 01:30:28 +0200 Subject: [PATCH 020/282] Moved ovqt to /code/studio --HG-- branch : gsoc2014-dfighter --- code/CMakeLists.txt | 4 + code/CMakeModules/nel.cmake | 4 + code/nel/tools/3d/CMakeLists.txt | 1 - .../src/plugins/core/CMakeLists.txt | 73 --- .../src/plugins/core/context_manager.cpp | 167 ------ .../src/plugins/core/context_manager.h | 76 --- .../src/plugins/core/core.cpp | 77 --- .../object_viewer_qt/src/plugins/core/core.h | 54 -- .../src/plugins/core/core.qrc | 21 - .../src/plugins/core/core_constants.h | 121 ----- .../src/plugins/core/core_global.h | 30 -- .../src/plugins/core/core_plugin.cpp | 104 ---- .../src/plugins/core/core_plugin.h | 74 --- .../plugins/core/general_settings_page.cpp | 241 --------- .../src/plugins/core/general_settings_page.h | 74 --- .../src/plugins/core/general_settings_page.ui | 233 --------- .../src/plugins/core/icons/ic_nel_crash.png | Bin 6630 -> 0 bytes .../src/plugins/core/icons/ic_nel_new.png | Bin 21396 -> 0 bytes .../core/icons/ic_nel_path_settings.png | Bin 4557 -> 0 bytes .../src/plugins/core/icons/ic_nel_redo.png | Bin 4694 -> 0 bytes .../src/plugins/core/icons/ic_nel_save.png | Bin 43738 -> 0 bytes .../src/plugins/core/icons/ic_nel_save_as.png | Bin 52871 -> 0 bytes .../src/plugins/core/icons/ic_nel_undo.png | Bin 4714 -> 0 bytes .../src/plugins/core/icontext.h | 76 --- .../object_viewer_qt/src/plugins/core/icore.h | 70 --- .../src/plugins/core/icore_listener.h | 63 --- .../src/plugins/core/images/preferences.png | Bin 10286 -> 0 bytes .../src/plugins/core/ioptions_page.h | 75 --- .../src/plugins/core/main_window.cpp | 492 ------------------ .../src/plugins/core/main_window.h | 147 ------ .../src/plugins/core/menu_manager.cpp | 96 ---- .../src/plugins/core/menu_manager.h | 67 --- .../src/plugins/core/ovqt_plugin_core.xml | 7 - .../src/plugins/core/plugin_view_dialog.cpp | 108 ---- .../src/plugins/core/plugin_view_dialog.h | 58 --- .../src/plugins/core/plugin_view_dialog.ui | 135 ----- .../src/plugins/core/qtwin.cpp | 241 --------- .../object_viewer_qt/src/plugins/core/qtwin.h | 37 -- .../core/search_paths_settings_page.cpp | 219 -------- .../plugins/core/search_paths_settings_page.h | 74 --- .../core/search_paths_settings_page.ui | 198 ------- .../src/plugins/core/settings_dialog.cpp | 182 ------- .../src/plugins/core/settings_dialog.h | 75 --- .../src/plugins/core/settings_dialog.ui | 126 ----- .../images/ic_nel_generic_settings.png | Bin 5633 -> 0 bytes .../object_viewer/icons/ic_nel_down_item.png | Bin 3812 -> 0 bytes .../object_viewer/icons/ic_nel_pill.png | Bin 9291 -> 0 bytes .../object_viewer/icons/ic_nel_reset_all.png | Bin 5938 -> 0 bytes .../object_viewer/icons/ic_nel_up_item.png | Bin 3304 -> 0 bytes .../tile_editor/images/ic_nel_add_item.png | Bin 3270 -> 0 bytes .../tile_editor/images/ic_nel_delete_item.png | Bin 1496 -> 0 bytes .../tile_editor/images/ic_nel_open.png | Bin 4310 -> 0 bytes .../src/plugins/tile_editor/images/nel.png | Bin 15587 -> 0 bytes .../CMakeLists.txt | 0 .../data/andbasr.ttf | Bin .../doc/html/cdirection_widget.png | Bin .../doc/html/cedit_color_widget.png | Bin .../doc/html/cedit_range_float_widget.png | Bin .../doc/html/cedit_range_int_widget.png | Bin .../doc/html/gui_struct.png | Bin .../doc/html/object_viewer_qt_window.png | Bin .../doc/make_ovqt_dox.bat | 0 .../doc/make_ovqt_dox.sh | 0 .../object_viewer_qt => studio}/doc/ovqt.dox | 0 .../ovqt_config.h.cmake | 0 .../src/3rdparty/CMakeLists.txt | 0 .../3rdparty/qtpropertybrowser/CMakeLists.txt | 0 .../qtpropertybrowser/LGPL_EXCEPTION.txt | 0 .../3rdparty/qtpropertybrowser/LICENSE.GPL3 | 0 .../3rdparty/qtpropertybrowser/LICENSE.LGPL | 0 .../QtAbstractEditorFactoryBase | 0 .../QtAbstractPropertyBrowser | 0 .../QtAbstractPropertyManager | 0 .../qtpropertybrowser/QtBoolPropertyManager | 0 .../3rdparty/qtpropertybrowser/QtBrowserItem | 0 .../qtpropertybrowser/QtButtonPropertyBrowser | 0 .../qtpropertybrowser/QtCharEditorFactory | 0 .../qtpropertybrowser/QtCharPropertyManager | 0 .../qtpropertybrowser/QtCheckBoxFactory | 0 .../qtpropertybrowser/QtColorEditorFactory | 0 .../qtpropertybrowser/QtColorPropertyManager | 0 .../qtpropertybrowser/QtCursorEditorFactory | 0 .../qtpropertybrowser/QtCursorPropertyManager | 0 .../qtpropertybrowser/QtDateEditFactory | 0 .../qtpropertybrowser/QtDatePropertyManager | 0 .../qtpropertybrowser/QtDateTimeEditFactory | 0 .../QtDateTimePropertyManager | 0 .../qtpropertybrowser/QtDoublePropertyManager | 0 .../qtpropertybrowser/QtDoubleSpinBoxFactory | 0 .../qtpropertybrowser/QtEnumEditorFactory | 0 .../qtpropertybrowser/QtEnumPropertyManager | 0 .../qtpropertybrowser/QtFlagPropertyManager | 0 .../qtpropertybrowser/QtFontEditorFactory | 0 .../qtpropertybrowser/QtFontPropertyManager | 0 .../QtGroupBoxPropertyBrowser | 0 .../qtpropertybrowser/QtGroupPropertyManager | 0 .../qtpropertybrowser/QtIntPropertyManager | 0 .../QtKeySequenceEditorFactory | 0 .../QtKeySequencePropertyManager | 0 .../qtpropertybrowser/QtLineEditFactory | 0 .../qtpropertybrowser/QtLocalePropertyManager | 0 .../qtpropertybrowser/QtPointFPropertyManager | 0 .../qtpropertybrowser/QtPointPropertyManager | 0 .../src/3rdparty/qtpropertybrowser/QtProperty | 0 .../qtpropertybrowser/QtRectFPropertyManager | 0 .../qtpropertybrowser/QtRectPropertyManager | 0 .../qtpropertybrowser/QtScrollBarFactory | 0 .../qtpropertybrowser/QtSizeFPropertyManager | 0 .../QtSizePolicyPropertyManager | 0 .../qtpropertybrowser/QtSizePropertyManager | 0 .../qtpropertybrowser/QtSliderFactory | 0 .../qtpropertybrowser/QtSpinBoxFactory | 0 .../qtpropertybrowser/QtStringPropertyManager | 0 .../qtpropertybrowser/QtTimeEditFactory | 0 .../qtpropertybrowser/QtTimePropertyManager | 0 .../qtpropertybrowser/QtTreePropertyBrowser | 0 .../qtpropertybrowser/QtVariantEditorFactory | 0 .../qtpropertybrowser/QtVariantProperty | 0 .../QtVariantPropertyManager | 0 .../src/3rdparty/qtpropertybrowser/README.TXT | 0 .../qtpropertybrowser/images/cursor-arrow.png | Bin .../qtpropertybrowser/images/cursor-busy.png | Bin .../images/cursor-closedhand.png | Bin .../qtpropertybrowser/images/cursor-cross.png | Bin .../images/cursor-forbidden.png | Bin .../qtpropertybrowser/images/cursor-hand.png | Bin .../images/cursor-hsplit.png | Bin .../qtpropertybrowser/images/cursor-ibeam.png | Bin .../images/cursor-openhand.png | Bin .../images/cursor-sizeall.png | Bin .../qtpropertybrowser/images/cursor-sizeb.png | Bin .../qtpropertybrowser/images/cursor-sizef.png | Bin .../qtpropertybrowser/images/cursor-sizeh.png | Bin .../qtpropertybrowser/images/cursor-sizev.png | Bin .../images/cursor-uparrow.png | Bin .../images/cursor-vsplit.png | Bin .../qtpropertybrowser/images/cursor-wait.png | Bin .../images/cursor-whatsthis.png | Bin .../images/resetproperty.png | Bin .../qtbuttonpropertybrowser.cpp | 0 .../qtbuttonpropertybrowser.h | 0 .../qtpropertybrowser/qteditorfactory.cpp | 0 .../qtpropertybrowser/qteditorfactory.h | 0 .../qtgroupboxpropertybrowser.cpp | 0 .../qtgroupboxpropertybrowser.h | 0 .../qtpropertybrowser/qtpropertybrowser.cpp | 0 .../qtpropertybrowser/qtpropertybrowser.h | 0 .../qtpropertybrowser/qtpropertybrowser.pri | 0 .../qtpropertybrowser/qtpropertybrowser.qrc | 0 .../qtpropertybrowserutils.cpp | 0 .../qtpropertybrowserutils_p.h | 0 .../qtpropertybrowser/qtpropertymanager.cpp | 0 .../qtpropertybrowser/qtpropertymanager.h | 0 .../qttreepropertybrowser.cpp | 0 .../qtpropertybrowser/qttreepropertybrowser.h | 0 .../qtpropertybrowser/qtvariantproperty.cpp | 0 .../qtpropertybrowser/qtvariantproperty.h | 0 .../src/CMakeLists.txt | 0 .../src/description.h | 0 .../src/extension_system/iplugin.h | 0 .../src/extension_system/iplugin_manager.h | 0 .../src/extension_system/iplugin_spec.h | 0 .../src/extension_system/plugin_manager.cpp | 0 .../src/extension_system/plugin_manager.h | 0 .../src/extension_system/plugin_spec.cpp | 0 .../src/extension_system/plugin_spec.h | 0 .../src/ic_nel_pill.ico | Bin .../src/images/nel_ide_load.png | Bin .../object_viewer_qt => studio}/src/main.cpp | 0 .../src/object_viewer_qt.qrc | 0 .../src/object_viewer_qt.rc | 0 .../src/plugins/CMakeLists.txt | 0 .../src/plugins/bnp_manager/CMakeLists.txt | 0 .../bnp_manager/bnp_dirtree_dialog.cpp | 0 .../plugins/bnp_manager/bnp_dirtree_dialog.h | 0 .../plugins/bnp_manager/bnp_dirtree_form.ui | 0 .../src/plugins/bnp_manager/bnp_file.cpp | 0 .../src/plugins/bnp_manager/bnp_file.h | 0 .../bnp_manager/bnp_filelist_dialog.cpp | 0 .../plugins/bnp_manager/bnp_filelist_dialog.h | 0 .../bnp_manager/bnp_filelist_dialog.ui | 0 .../bnp_manager/bnp_filesystem_model.cpp | 0 .../bnp_manager/bnp_filesystem_model.h | 0 .../src/plugins/bnp_manager/bnp_manager.qrc | 0 .../bnp_manager/bnp_manager_constants.h | 0 .../bnp_manager/bnp_manager_plugin.cpp | 0 .../plugins/bnp_manager/bnp_manager_plugin.h | 0 .../bnp_manager/bnp_manager_window.cpp | 0 .../plugins/bnp_manager/bnp_manager_window.h | 0 .../plugins/bnp_manager/bnp_manager_window.ui | 0 .../plugins/bnp_manager/bnp_proxy_model.cpp | 0 .../src/plugins/bnp_manager/bnp_proxy_model.h | 0 .../bnp_manager/images/ic_nel_add_item.png | Bin .../bnp_manager/images/ic_nel_bnp_make.png | Bin .../bnp_manager/images/ic_nel_delete_item.png | Bin .../bnp_manager/images/ic_nel_export.png | Bin .../plugins/bnp_manager/images/ic_nel_new.png | Bin .../bnp_manager/images/ic_nel_reset_all.png | Bin .../bnp_manager/ovqt_plugin_bnp_manager.xml | 0 .../src/plugins/disp_sheet_id/CMakeLists.txt | 0 .../disp_sheet_id/disp_sheet_id_plugin.cpp | 0 .../disp_sheet_id/disp_sheet_id_plugin.h | 0 .../ovqt_plugin_disp_sheet_id.xml | 0 .../plugins/disp_sheet_id/sheet_id_view.cpp | 0 .../src/plugins/disp_sheet_id/sheet_id_view.h | 0 .../plugins/disp_sheet_id/sheet_id_view.ui | 0 .../src/plugins/example/CMakeLists.txt | 0 .../src/plugins/example/example_plugin.cpp | 0 .../src/plugins/example/example_plugin.h | 0 .../plugins/example/example_settings_page.cpp | 0 .../plugins/example/example_settings_page.h | 0 .../plugins/example/example_settings_page.ui | 0 .../plugins/example/ovqt_plugin_example.xml | 0 .../src/plugins/example/qnel_widget.cpp | 0 .../src/plugins/example/qnel_widget.h | 0 .../src/plugins/example/simple_viewer.cpp | 0 .../src/plugins/example/simple_viewer.h | 0 .../src/plugins/georges_editor/CMakeLists.txt | 0 .../src/plugins/georges_editor/actions.cpp | 0 .../src/plugins/georges_editor/actions.h | 0 .../georges_editor/expandable_headerview.cpp | 0 .../georges_editor/expandable_headerview.h | 0 .../plugins/georges_editor/formdelegate.cpp | 0 .../src/plugins/georges_editor/formdelegate.h | 0 .../src/plugins/georges_editor/formitem.cpp | 0 .../src/plugins/georges_editor/formitem.h | 0 .../src/plugins/georges_editor/georges.cpp | 0 .../src/plugins/georges_editor/georges.h | 0 .../georges_editor/georges_dirtree_dialog.cpp | 0 .../georges_editor/georges_dirtree_dialog.h | 0 .../georges_editor/georges_dirtree_form.ui | 0 .../plugins/georges_editor/georges_editor.qrc | 0 .../georges_editor/georges_editor_constants.h | 0 .../georges_editor/georges_editor_form.cpp | 0 .../georges_editor/georges_editor_form.h | 0 .../georges_editor/georges_editor_form.ui | 0 .../georges_editor/georges_editor_plugin.cpp | 0 .../georges_editor/georges_editor_plugin.h | 0 .../georges_filesystem_model.cpp | 0 .../georges_editor/georges_filesystem_model.h | 0 .../georges_treeview_dialog.cpp | 0 .../georges_editor/georges_treeview_dialog.h | 0 .../georges_editor/georges_treeview_form.ui | 0 .../georges_editor/georgesform_model.cpp | 0 .../georges_editor/georgesform_model.h | 0 .../georgesform_proxy_model.cpp | 0 .../georges_editor/georgesform_proxy_model.h | 0 .../plugins/georges_editor/images/array.ico | Bin .../plugins/georges_editor/images/header.ico | Bin .../plugins/georges_editor/images/hold.ico | Bin .../images/ic_nel_georges_editor.png | Bin .../plugins/georges_editor/images/root.ico | Bin .../plugins/georges_editor/images/struct.ico | Bin .../plugins/georges_editor/images/vstruct.ico | Bin .../plugins/georges_editor/images/zfee51.ico | Bin .../ovqt_plugin_georges_editor.xml | 0 .../src/plugins/georges_editor/stdpch.cpp | 0 .../src/plugins/georges_editor/stdpch.h | 0 .../src/plugins/gui_editor/CMakeLists.txt | 0 .../src/plugins/gui_editor/action_editor.cpp | 0 .../src/plugins/gui_editor/action_editor.h | 0 .../src/plugins/gui_editor/action_editor.ui | 0 .../plugins/gui_editor/add_widget_widget.cpp | 0 .../plugins/gui_editor/add_widget_widget.h | 0 .../plugins/gui_editor/add_widget_widget.ui | 0 .../gui_editor/editor_message_processor.cpp | 0 .../gui_editor/editor_message_processor.h | 0 .../gui_editor/editor_selection_watcher.cpp | 0 .../gui_editor/editor_selection_watcher.h | 0 .../plugins/gui_editor/gui_editor_constants.h | 0 .../plugins/gui_editor/gui_editor_context.cpp | 0 .../plugins/gui_editor/gui_editor_context.h | 0 .../gui_editor/gui_editor_core_listener.cpp | 0 .../gui_editor/gui_editor_core_listener.h | 0 .../plugins/gui_editor/gui_editor_global.h | 0 .../plugins/gui_editor/gui_editor_plugin.cpp | 0 .../plugins/gui_editor/gui_editor_plugin.h | 0 .../plugins/gui_editor/gui_editor_window.cpp | 0 .../plugins/gui_editor/gui_editor_window.h | 0 .../plugins/gui_editor/gui_editor_window.ui | 0 .../src/plugins/gui_editor/link_editor.cpp | 0 .../src/plugins/gui_editor/link_editor.h | 0 .../src/plugins/gui_editor/link_editor.ui | 0 .../src/plugins/gui_editor/link_list.cpp | 0 .../src/plugins/gui_editor/link_list.h | 0 .../src/plugins/gui_editor/link_list.ui | 0 .../src/plugins/gui_editor/nel3d_widget.cpp | 0 .../src/plugins/gui_editor/nel3d_widget.h | 0 .../src/plugins/gui_editor/nelgui_widget.cpp | 0 .../src/plugins/gui_editor/nelgui_widget.h | 0 .../gui_editor/new_property_widget.cpp | 0 .../plugins/gui_editor/new_property_widget.h | 0 .../plugins/gui_editor/new_property_widget.ui | 0 .../plugins/gui_editor/new_widget_widget.cpp | 0 .../plugins/gui_editor/new_widget_widget.h | 0 .../plugins/gui_editor/new_widget_widget.ui | 0 .../gui_editor/ovqt_plugin_gui_editor.xml | 0 .../src/plugins/gui_editor/proc_editor.cpp | 0 .../src/plugins/gui_editor/proc_editor.h | 0 .../src/plugins/gui_editor/proc_editor.ui | 0 .../src/plugins/gui_editor/proc_list.cpp | 0 .../src/plugins/gui_editor/proc_list.h | 0 .../src/plugins/gui_editor/proc_list.ui | 0 .../gui_editor/project_file_parser.cpp | 0 .../plugins/gui_editor/project_file_parser.h | 0 .../gui_editor/project_file_serializer.cpp | 0 .../gui_editor/project_file_serializer.h | 0 .../src/plugins/gui_editor/project_files.h | 0 .../gui_editor/project_files/login.xml | 0 .../src/plugins/gui_editor/project_window.cpp | 0 .../src/plugins/gui_editor/project_window.h | 0 .../src/plugins/gui_editor/project_window.ui | 0 .../gui_editor/property_browser_ctrl.cpp | 0 .../gui_editor/property_browser_ctrl.h | 0 .../plugins/gui_editor/widget_hierarchy.cpp | 0 .../src/plugins/gui_editor/widget_hierarchy.h | 0 .../plugins/gui_editor/widget_hierarchy.ui | 0 .../src/plugins/gui_editor/widget_info.h | 0 .../gui_editor/widget_info_serializer.cpp | 0 .../gui_editor/widget_info_serializer.h | 0 .../src/plugins/gui_editor/widget_info_tree.h | 0 .../gui_editor/widget_info_tree_node.h | 0 .../gui_editor/widget_info_tree_visitor.h | 0 .../plugins/gui_editor/widget_properties.cpp | 0 .../plugins/gui_editor/widget_properties.h | 0 .../plugins/gui_editor/widget_properties.ui | 0 .../gui_editor/widget_properties_parser.cpp | 0 .../gui_editor/widget_properties_parser.h | 0 .../plugins/gui_editor/widget_serializer.cpp | 0 .../plugins/gui_editor/widget_serializer.h | 0 .../plugins/gui_editor/widgets/CtrlBase.xml | 0 .../gui_editor/widgets/CtrlBaseButton.xml | 0 .../plugins/gui_editor/widgets/CtrlButton.xml | 0 .../gui_editor/widgets/CtrlColPick.xml | 0 .../plugins/gui_editor/widgets/CtrlScroll.xml | 0 .../gui_editor/widgets/CtrlTabButton.xml | 0 .../gui_editor/widgets/CtrlTextButton.xml | 0 .../widgets/DBGroupSelectNumber.xml | 0 .../plugins/gui_editor/widgets/DBViewBar.xml | 0 .../plugins/gui_editor/widgets/DBViewBar3.xml | 0 .../gui_editor/widgets/DBViewDigit.xml | 0 .../gui_editor/widgets/DBViewNumber.xml | 0 .../gui_editor/widgets/DBViewQuantity.xml | 0 .../plugins/gui_editor/widgets/GroupCell.xml | 0 .../gui_editor/widgets/GroupContainer.xml | 0 .../gui_editor/widgets/GroupEditBox.xml | 0 .../plugins/gui_editor/widgets/GroupFrame.xml | 0 .../plugins/gui_editor/widgets/GroupHTML.xml | 0 .../gui_editor/widgets/GroupHeader.xml | 0 .../plugins/gui_editor/widgets/GroupList.xml | 0 .../plugins/gui_editor/widgets/GroupMenu.xml | 0 .../plugins/gui_editor/widgets/GroupModal.xml | 0 .../gui_editor/widgets/GroupParagraph.xml | 0 .../gui_editor/widgets/GroupScrollText.xml | 0 .../plugins/gui_editor/widgets/GroupTab.xml | 0 .../plugins/gui_editor/widgets/GroupTable.xml | 0 .../plugins/gui_editor/widgets/GroupTree.xml | 0 .../gui_editor/widgets/InterfaceElement.xml | 0 .../gui_editor/widgets/InterfaceGroup.xml | 0 .../widgets/InterfaceGroupWheel.xml | 0 .../plugins/gui_editor/widgets/RootGroup.xml | 0 .../plugins/gui_editor/widgets/ViewBitmap.xml | 0 .../gui_editor/widgets/ViewBitmapCombo.xml | 0 .../plugins/gui_editor/widgets/ViewText.xml | 0 .../gui_editor/widgets/ViewTextFormated.xml | 0 .../plugins/gui_editor/widgets/ViewTextID.xml | 0 .../gui_editor/widgets/ViewTextIDFormated.xml | 0 .../plugins/landscape_editor/CMakeLists.txt | 0 .../plugins/landscape_editor/builder_zone.cpp | 0 .../plugins/landscape_editor/builder_zone.h | 0 .../landscape_editor/builder_zone_base.cpp | 0 .../landscape_editor/builder_zone_base.h | 0 .../landscape_editor/builder_zone_region.cpp | 0 .../landscape_editor/builder_zone_region.h | 0 .../landscape_editor/icons/ic_grid.png | Bin .../icons/ic_nel_landscape_item.png | Bin .../icons/ic_nel_landscape_settings.png | Bin .../icons/ic_nel_transition_land.png | Bin .../icons/ic_nel_world_editor.png | Bin .../landscape_editor/icons/ic_nel_zone.png | Bin .../landscape_editor/icons/ic_nel_zonel.png | Bin .../landscape_editor/icons/ic_nel_zones.png | Bin .../landscape_editor/icons/ic_snapshot.png | Bin .../landscape_editor/landscape_actions.cpp | 0 .../landscape_editor/landscape_actions.h | 0 .../landscape_editor/landscape_editor.qrc | 0 .../landscape_editor_constants.h | 0 .../landscape_editor_global.h | 0 .../landscape_editor_plugin.cpp | 0 .../landscape_editor_plugin.h | 0 .../landscape_editor_window.cpp | 0 .../landscape_editor_window.h | 0 .../landscape_editor_window.ui | 0 .../landscape_editor/landscape_scene.cpp | 0 .../landscape_editor/landscape_scene.h | 0 .../landscape_editor/landscape_scene_base.cpp | 0 .../landscape_editor/landscape_scene_base.h | 0 .../landscape_editor/landscape_view.cpp | 0 .../plugins/landscape_editor/landscape_view.h | 0 .../landscape_editor/list_zones_model.cpp | 0 .../landscape_editor/list_zones_model.h | 0 .../landscape_editor/list_zones_widget.cpp | 0 .../landscape_editor/list_zones_widget.h | 0 .../landscape_editor/list_zones_widget.ui | 0 .../ovqt_plugin_landscape_editor.xml | 0 .../landscape_editor/pixmap_database.cpp | 0 .../landscape_editor/pixmap_database.h | 0 .../project_settings_dialog.cpp | 0 .../project_settings_dialog.h | 0 .../project_settings_dialog.ui | 0 .../landscape_editor/shapshot_dialog.ui | 0 .../landscape_editor/snapshot_dialog.cpp | 0 .../landscape_editor/snapshot_dialog.h | 0 .../landscape_editor/zone_region_editor.cpp | 0 .../landscape_editor/zone_region_editor.h | 0 .../src/plugins/log/CMakeLists.txt | 0 .../src/plugins/log/log_form.ui | 0 .../src/plugins/log/log_plugin.cpp | 0 .../src/plugins/log/log_plugin.h | 0 .../src/plugins/log/log_settings_page.cpp | 0 .../src/plugins/log/log_settings_page.h | 0 .../src/plugins/log/log_settings_page.ui | 0 .../src/plugins/log/ovqt_plugin_log.xml | 0 .../src/plugins/log/qt_displayer.cpp | 0 .../src/plugins/log/qt_displayer.h | 0 .../plugins/mission_compiler/CMakeLists.txt | 0 .../mission_compiler/images/arrow-left-2.png | Bin .../images/arrow-left-double-2.png | Bin .../mission_compiler/images/arrow-right-2.png | Bin .../images/arrow-right-double-2.png | Bin .../images/document-export-4.png | Bin .../images}/ic_nel_add_item.png | Bin .../images}/ic_nel_delete_item.png | Bin .../images}/ic_nel_down_item.png | Bin .../images}/ic_nel_generic_settings.png | Bin .../images}/ic_nel_reset_all.png | Bin .../images}/ic_nel_up_item.png | Bin .../images/news-subscribe-2.png | Bin .../mission_compiler/images/run-build-2.png | Bin .../mission_compiler/mission_compiler.qrc | 0 .../mission_compiler_main_window.cpp | 0 .../mission_compiler_main_window.h | 0 .../mission_compiler_main_window.ui | 0 .../mission_compiler_plugin.cpp | 0 .../mission_compiler_plugin.h | 0 .../mission_compiler_plugin_constants.h | 0 .../mission_compiler_settings_page.cpp | 0 .../mission_compiler_settings_page.h | 0 .../mission_compiler_settings_page.ui | 0 .../ovqt_plugin_mission_compiler.xml | 0 .../mission_compiler/server_entry_dialog.cpp | 0 .../mission_compiler/server_entry_dialog.h | 0 .../mission_compiler/server_entry_dialog.ui | 0 .../mission_compiler/validation_file.cpp | 0 .../mission_compiler/validation_file.h | 0 .../src/plugins/object_viewer/CMakeLists.txt | 0 .../object_viewer/graphics_settings_page.cpp | 0 .../object_viewer/graphics_settings_page.h | 0 .../object_viewer/graphics_settings_page.ui | 0 .../object_viewer/graphics_viewport.cpp | 0 .../plugins/object_viewer/graphics_viewport.h | 0 .../object_viewer/icons}/ic_nel_add_item.png | Bin .../object_viewer/icons/ic_nel_anim.png | Bin .../object_viewer/icons/ic_nel_animset.png | Bin .../icons/ic_nel_append_item.png | Bin .../object_viewer/icons/ic_nel_bgcolor.png | Bin .../icons/ic_nel_camera_3dedit.png | Bin .../object_viewer/icons/ic_nel_camera_add.png | Bin .../object_viewer/icons/ic_nel_camera_del.png | Bin .../object_viewer/icons/ic_nel_camera_fps.png | Bin .../object_viewer/icons/ic_nel_daynight.png | Bin .../icons}/ic_nel_delete_item.png | Bin .../object_viewer/icons}/ic_nel_down_item.png | Bin .../object_viewer/icons/ic_nel_framedelay.png | Bin .../icons/ic_nel_insert_item.png | Bin .../object_viewer/icons/ic_nel_mixer.png | Bin .../object_viewer/icons/ic_nel_mrm_mesh.png | Bin .../object_viewer/icons/ic_nel_new.png | Bin .../object_viewer}/icons/ic_nel_open.png | Bin .../icons/ic_nel_particle_system.png | Bin .../icons/ic_nel_particle_system_close.png | Bin .../object_viewer/icons/ic_nel_particles.png | Bin .../object_viewer}/icons/ic_nel_pill.png | Bin .../object_viewer/icons}/ic_nel_reset_all.png | Bin .../icons/ic_nel_reset_camera.png | Bin .../object_viewer/icons/ic_nel_save.png | Bin .../object_viewer/icons/ic_nel_save_as.png | Bin .../object_viewer/icons/ic_nel_skelscale.png | Bin .../object_viewer/icons/ic_nel_sound.png | Bin .../object_viewer/icons}/ic_nel_up_item.png | Bin .../object_viewer/icons/ic_nel_veget.png | Bin .../object_viewer/icons/ic_nel_vegetset.png | Bin .../object_viewer/icons/ic_nel_water.png | Bin .../object_viewer/icons/ic_nel_wind.png | Bin .../icons/ic_nel_workspace_item.png | Bin .../ic_nel_collision_zone_item_24.png | Bin .../ic_nel_emitter_item_24.png | Bin .../ic_nel_force_item_24.png | Bin .../ic_nel_instance_item_24.png | Bin .../ic_nel_light_item_24.png | Bin .../ic_nel_located_item_24.png | Bin .../ic_nel_particle_item_24.png | Bin .../ic_nel_particle_system_24.png | Bin .../ic_nel_particle_system_close_24.png | Bin .../ic_nel_sound_item_24.png | Bin .../ic_nel_workspace_item_24.png | Bin .../plugins/object_viewer/images/dqynight.png | Bin .../object_viewer/images/ico_mrm_mesh.png | Bin .../plugins/object_viewer/images/mixer.png | Bin .../src/plugins/object_viewer}/images/nel.png | Bin .../plugins/object_viewer/images/pause.png | Bin .../src/plugins/object_viewer/images/play.png | Bin .../plugins/object_viewer/images/polymode.png | Bin .../object_viewer/images/pqrticles.png | Bin .../plugins/object_viewer/images/refresh.png | Bin .../plugins/object_viewer/images/rmfill.png | Bin .../plugins/object_viewer/images/rmline.png | Bin .../plugins/object_viewer/images/rmpoints.png | Bin .../object_viewer/images/seek-backward.png | Bin .../object_viewer/images/seek-forward.png | Bin .../object_viewer/images/skip-backward.png | Bin .../object_viewer/images/skip-forward.png | Bin .../plugins/object_viewer/images/sound.png | Bin .../src/plugins/object_viewer/images/stop.png | Bin .../plugins/object_viewer/images/water.png | Bin .../src/plugins/object_viewer/images/wind.png | Bin .../src/plugins/object_viewer/main_window.cpp | 0 .../src/plugins/object_viewer/main_window.h | 0 .../src/plugins/object_viewer/modules.cpp | 0 .../src/plugins/object_viewer/modules.h | 0 .../plugins/object_viewer/object_viewer.cpp | 0 .../src/plugins/object_viewer/object_viewer.h | 0 .../plugins/object_viewer/object_viewer.qrc | 0 .../object_viewer/object_viewer_constants.h | 0 .../object_viewer/object_viewer_plugin.cpp | 0 .../object_viewer/object_viewer_plugin.h | 0 .../ovqt_plugin_object_viewer.xml | 0 .../particle_system/attrib_form.ui | 0 .../particle_system/attrib_widget.cpp | 0 .../particle_system/attrib_widget.h | 0 .../particle_system/auto_lod_dialog.cpp | 0 .../particle_system/auto_lod_dialog.h | 0 .../particle_system/auto_lod_form.ui | 0 .../particle_system/basic_edit_form.ui | 0 .../particle_system/basic_edit_widget.cpp | 0 .../particle_system/basic_edit_widget.h | 0 .../particle_system/bin_op_dialog.cpp | 0 .../particle_system/bin_op_dialog.h | 0 .../particle_system/constraint_mesh_form.ui | 0 .../constraint_mesh_widget.cpp | 0 .../particle_system/constraint_mesh_widget.h | 0 .../particle_system/curve_dialog.cpp | 0 .../particle_system/curve_dialog.h | 0 .../particle_system/curve_form.ui | 0 .../particle_system/direction_form.ui | 0 .../particle_system/direction_widget.cpp | 0 .../particle_system/direction_widget.h | 0 .../object_viewer/particle_system/dup_ps.cpp | 0 .../object_viewer/particle_system/dup_ps.h | 0 .../particle_system/emitter_form.ui | 0 .../particle_system/emitter_page.cpp | 0 .../particle_system/emitter_page.h | 0 .../particle_system/follow_path_dialog.cpp | 0 .../particle_system/follow_path_dialog.h | 0 .../particle_system/located_bindable_form.ui | 0 .../particle_system/located_bindable_page.cpp | 0 .../particle_system/located_bindable_page.h | 0 .../particle_system/located_form.ui | 0 .../particle_system/located_page.cpp | 0 .../particle_system/located_page.h | 0 .../particle_system/mesh_form.ui | 0 .../particle_system/mesh_widget.cpp | 0 .../particle_system/mesh_widget.h | 0 .../particle_system/morph_mesh_dialog.cpp | 0 .../particle_system/morph_mesh_dialog.h | 0 .../particle_system/morph_mesh_form.ui | 0 .../particle_system/multi_tex_dialog.cpp | 0 .../particle_system/multi_tex_dialog.h | 0 .../particle_system/multi_tex_form.ui | 0 .../particle_control_dialog.cpp | 0 .../particle_system/particle_control_dialog.h | 0 .../particle_system/particle_control_form.ui | 0 .../particle_system/particle_editor.cpp | 0 .../particle_system/particle_editor.h | 0 .../particle_system/particle_force_form.ui | 0 .../particle_system/particle_force_page.cpp | 0 .../particle_system/particle_force_page.h | 0 .../particle_system/particle_light_form.ui | 0 .../particle_system/particle_light_page.cpp | 0 .../particle_system/particle_light_page.h | 0 .../particle_link_skeleton_dialog.cpp | 0 .../particle_link_skeleton_dialog.h | 0 .../particle_link_skeleton_form.ui | 0 .../particle_system/particle_node.cpp | 0 .../particle_system/particle_node.h | 0 .../particle_property_dialog.cpp | 0 .../particle_property_dialog.h | 0 .../particle_system/particle_sound_form.ui | 0 .../particle_system/particle_sound_page.cpp | 0 .../particle_system/particle_sound_page.h | 0 .../particle_system/particle_system_form.ui | 0 .../particle_system/particle_system_page.cpp | 0 .../particle_system/particle_system_page.h | 0 .../particle_texture_anim_form.ui | 0 .../particle_texture_anim_widget.cpp | 0 .../particle_texture_anim_widget.h | 0 .../particle_system/particle_texture_form.ui | 0 .../particle_texture_widget.cpp | 0 .../particle_system/particle_texture_widget.h | 0 .../particle_system/particle_tree_model.cpp | 0 .../particle_system/particle_tree_model.h | 0 .../particle_workspace_dialog.cpp | 0 .../particle_workspace_dialog.h | 0 .../particle_workspace_form.ui | 0 .../particle_workspace_page.cpp | 0 .../particle_system/particle_workspace_page.h | 0 .../particle_system/particle_zone_form.ui | 0 .../particle_system/particle_zone_page.cpp | 0 .../particle_system/particle_zone_page.h | 0 .../particle_system/ps_initial_pos.cpp | 0 .../particle_system/ps_initial_pos.h | 0 .../particle_system/ps_mover_form.ui | 0 .../particle_system/ps_mover_page.cpp | 0 .../particle_system/ps_mover_page.h | 0 .../particle_system/ps_wrapper.h | 0 .../particle_system/scheme_bank_dialog.cpp | 0 .../particle_system/scheme_bank_dialog.h | 0 .../particle_system/scheme_bank_form.ui | 0 .../particle_system/scheme_manager.cpp | 0 .../particle_system/scheme_manager.h | 0 .../particle_system/spinner_dialog.cpp | 0 .../particle_system/spinner_dialog.h | 0 .../particle_system/tail_form.ui | 0 .../particle_system/tail_particle_widget.cpp | 0 .../particle_system/tail_particle_widget.h | 0 .../particle_system/value_blender_dialog.cpp | 0 .../particle_system/value_blender_dialog.h | 0 .../value_from_emitter_dialog.cpp | 0 .../value_from_emitter_dialog.h | 0 .../particle_system/value_gradient_dialog.cpp | 0 .../particle_system/value_gradient_dialog.h | 0 .../particle_system/value_gradient_form.ui | 0 .../particle_system/workspace_form.ui | 0 .../object_viewer/scene/animation_dialog.cpp | 0 .../object_viewer/scene/animation_dialog.h | 0 .../object_viewer/scene/animation_form.ui | 0 .../scene/animation_set_dialog.cpp | 0 .../scene/animation_set_dialog.h | 0 .../object_viewer/scene/animation_set_form.ui | 0 .../object_viewer/scene/camera_control.cpp | 0 .../object_viewer/scene/camera_control.h | 0 .../object_viewer/scene/day_night_dialog.cpp | 0 .../object_viewer/scene/day_night_dialog.h | 0 .../object_viewer/scene/day_night_form.ui | 0 .../plugins/object_viewer/scene/entity.cpp | 0 .../src/plugins/object_viewer/scene/entity.h | 0 .../scene/global_wind_dialog.cpp | 0 .../object_viewer/scene/global_wind_dialog.h | 0 .../object_viewer/scene/global_wind_form.ui | 0 .../object_viewer/scene/setup_fog_dialog.cpp | 0 .../object_viewer/scene/setup_fog_dialog.h | 0 .../object_viewer/scene/setup_fog_form.ui | 0 .../scene/skeleton_scale_dialog.cpp | 0 .../scene/skeleton_scale_dialog.h | 0 .../scene/skeleton_scale_form.ui | 0 .../scene/skeleton_tree_model.cpp | 0 .../object_viewer/scene/skeleton_tree_model.h | 0 .../plugins/object_viewer/scene/slot_form.ui | 0 .../scene/slot_manager_dialog.cpp | 0 .../object_viewer/scene/slot_manager_dialog.h | 0 .../object_viewer/scene/sun_color_dialog.cpp | 0 .../object_viewer/scene/sun_color_dialog.h | 0 .../object_viewer/scene/sun_color_form.ui | 0 .../object_viewer/scene/tune_mrm_dialog.cpp | 0 .../object_viewer/scene/tune_mrm_dialog.h | 0 .../object_viewer/scene/tune_mrm_form.ui | 0 .../object_viewer/scene/tune_timer_dialog.cpp | 0 .../object_viewer/scene/tune_timer_dialog.h | 0 .../object_viewer/scene/tune_timer_form.ui | 0 .../object_viewer/scene/water_pool_dialog.cpp | 0 .../object_viewer/scene/water_pool_dialog.h | 0 .../object_viewer/scene/water_pool_form.ui | 0 .../object_viewer/sound_settings_page.cpp | 0 .../object_viewer/sound_settings_page.h | 0 .../object_viewer/sound_settings_page.ui | 0 .../plugins/object_viewer/sound_system.cpp | 0 .../src/plugins/object_viewer/sound_system.h | 0 .../src/plugins/object_viewer/stdpch.cpp | 0 .../src/plugins/object_viewer/stdpch.h | 0 .../vegetable/vegetable_appearance_page.cpp | 0 .../vegetable/vegetable_appearance_page.h | 0 .../vegetable/vegetable_apperance_form.ui | 0 .../vegetable/vegetable_density_form.ui | 0 .../vegetable/vegetable_density_page.cpp | 0 .../vegetable/vegetable_density_page.h | 0 .../vegetable/vegetable_dialog.cpp | 0 .../vegetable/vegetable_dialog.h | 0 .../vegetable/vegetable_dialog_form.ui | 0 .../vegetable/vegetable_editor.cpp | 0 .../vegetable/vegetable_editor.h | 0 .../vegetable/vegetable_landscape_form.ui | 0 .../vegetable/vegetable_landscape_page.cpp | 0 .../vegetable/vegetable_landscape_page.h | 0 .../vegetable/vegetable_node.cpp | 0 .../object_viewer/vegetable/vegetable_node.h | 0 .../vegetable/vegetable_noise_value_form.ui | 0 .../vegetable_noise_value_widget.cpp | 0 .../vegetable/vegetable_noise_value_widget.h | 0 .../vegetable/vegetable_rotate_form.ui | 0 .../vegetable/vegetable_rotate_page.cpp | 0 .../vegetable/vegetable_rotate_page.h | 0 .../vegetable/vegetable_scale_form.ui | 0 .../vegetable/vegetable_scale_page.cpp | 0 .../vegetable/vegetable_scale_page.h | 0 .../object_viewer/vegetable_settings_page.cpp | 0 .../object_viewer/vegetable_settings_page.h | 0 .../object_viewer/vegetable_settings_page.ui | 0 .../object_viewer/widgets/color_edit_form.ui | 0 .../widgets/color_edit_widget.cpp | 0 .../object_viewer/widgets/color_edit_widget.h | 0 .../widgets/edit_range_float_form.ui | 0 .../widgets/edit_range_uint_form.ui | 0 .../widgets/edit_range_widget.cpp | 0 .../object_viewer/widgets/edit_range_widget.h | 0 .../object_viewer/widgets/hoverpoints.cpp | 0 .../object_viewer/widgets/hoverpoints.h | 0 .../plugins/ovqt_sheet_builder/CMakeLists.txt | 0 .../ovqt_plugin_sheet_builder.xml | 0 .../ovqt_sheet_builder/ovqt_sheet_builder.cpp | 0 .../ovqt_sheet_builder/ovqt_sheet_builder.h | 0 .../ovqt_sheet_builder/ovqt_sheet_builder.pro | 0 .../plugins/ovqt_sheet_builder/sheetbuilder.h | 0 .../sheetbuilderconfgdialog.cpp | 0 .../sheetbuilderconfgdialog.h | 0 .../ovqt_sheet_builder/sheetbuilderdialog.cpp | 0 .../ovqt_sheet_builder/sheetbuilderdialog.h | 0 .../src/plugins/tile_editor/CMakeLists.txt | 0 .../plugins/tile_editor/images/add_tile.png | Bin .../tile_editor/images/delete_image.png | Bin .../tile_editor/images/delete_tile.png | Bin .../src/plugins/tile_editor/images/down.png | Bin .../tile_editor/images/empty_image.png | Bin .../tile_editor/images}/ic_nel_add_item.png | Bin .../images}/ic_nel_delete_item.png | Bin .../plugins/tile_editor/images/ic_nel_new.png | Bin .../tile_editor/images}/ic_nel_open.png | Bin .../tile_editor/images/ic_nel_save.png | Bin .../tile_editor/images/ic_nel_save_as.png | Bin .../src/plugins/tile_editor/images/left.png | Bin .../src/plugins/tile_editor}/images/nel.png | Bin .../tile_editor/images/replace_image.png | Bin .../src/plugins/tile_editor/images/reset.png | Bin .../src/plugins/tile_editor/images/right.png | Bin .../plugins/tile_editor/images/rotation0.png | Bin .../tile_editor/images/rotation180.png | Bin .../tile_editor/images/rotation270.png | Bin .../plugins/tile_editor/images/rotation90.png | Bin .../src/plugins/tile_editor/images/up.png | Bin .../tile_editor/ovqt_plugin_tile_editor.xml | 0 .../src/plugins/tile_editor/tile_editor.qrc | 0 .../tile_editor/tile_editor_main_window.cpp | 0 .../tile_editor/tile_editor_main_window.h | 0 .../tile_editor/tile_editor_main_window.ui | 0 .../tile_editor/tile_editor_plugin.cpp | 0 .../plugins/tile_editor/tile_editor_plugin.h | 0 .../src/plugins/tile_editor/tile_item.cpp | 0 .../src/plugins/tile_editor/tile_item.h | 0 .../tile_editor/tile_item_delegate.cpp | 0 .../plugins/tile_editor/tile_item_delegate.h | 0 .../src/plugins/tile_editor/tile_model.cpp | 0 .../src/plugins/tile_editor/tile_model.h | 0 .../translation_manager/CMakeLists.txt | 0 .../src/plugins/translation_manager/README | 0 .../translation_manager/editor_phrase.cpp | 0 .../translation_manager/editor_phrase.h | 0 .../translation_manager/editor_worksheet.cpp | 0 .../translation_manager/editor_worksheet.h | 0 .../translation_manager/extract_bot_names.cpp | 0 .../translation_manager/extract_bot_names.h | 0 .../extract_new_sheet_names.cpp | 0 .../extract_new_sheet_names.h | 0 .../translation_manager/ftp_selection.cpp | 0 .../translation_manager/ftp_selection.h | 0 .../translation_manager/ftp_selection.qrc | 0 .../translation_manager/ftp_selection.ui | 0 .../translation_manager/images/cdtoparent.png | Bin .../translation_manager/images/dir.png | Bin .../translation_manager/images/file.png | Bin .../ovqt_plugin_translation_manager.xml | 0 .../translation_manager/source_selection.cpp | 0 .../translation_manager/source_selection.h | 0 .../translation_manager/source_selection.ui | 0 .../translation_manager_constants.h | 0 .../translation_manager_editor.h | 0 .../translation_manager_main_window.cpp | 0 .../translation_manager_main_window.h | 0 .../translation_manager_main_window.ui | 0 .../translation_manager_plugin.cpp | 0 .../translation_manager_plugin.h | 0 .../translation_manager_settings_page.cpp | 0 .../translation_manager_settings_page.h | 0 .../translation_manager_settings_page.ui | 0 .../src/plugins/world_editor/CMakeLists.txt | 0 .../world_editor/icons/ic_nel_move.png | Bin .../world_editor/icons/ic_nel_rotate.png | Bin .../world_editor/icons/ic_nel_scale.png | Bin .../world_editor/icons/ic_nel_select.png | Bin .../world_editor/icons/ic_nel_turn.png | Bin .../icons/ic_nel_world_editor.png | Bin .../world_editor/ovqt_plugin_world_editor.xml | 0 .../plugins/world_editor/primitive_item.cpp | 0 .../src/plugins/world_editor/primitive_item.h | 0 .../plugins/world_editor/primitives_model.cpp | 0 .../plugins/world_editor/primitives_model.h | 0 .../plugins/world_editor/primitives_view.cpp | 0 .../plugins/world_editor/primitives_view.h | 0 .../world_editor/project_settings_dialog.cpp | 0 .../world_editor/project_settings_dialog.h | 0 .../world_editor/project_settings_dialog.ui | 0 .../world_editor/property_editor_widget.cpp | 0 .../world_editor/property_editor_widget.h | 0 .../world_editor/property_editor_widget.ui | 0 .../src/plugins/world_editor/world_editor.qrc | 0 .../world_editor/world_editor_actions.cpp | 0 .../world_editor/world_editor_actions.h | 0 .../world_editor/world_editor_constants.h | 0 .../world_editor/world_editor_global.h | 0 .../world_editor/world_editor_misc.cpp | 0 .../plugins/world_editor/world_editor_misc.h | 0 .../world_editor/world_editor_plugin.cpp | 0 .../world_editor/world_editor_plugin.h | 0 .../world_editor/world_editor_scene.cpp | 0 .../plugins/world_editor/world_editor_scene.h | 0 .../world_editor/world_editor_scene_item.cpp | 0 .../world_editor/world_editor_scene_item.h | 0 .../world_editor_settings_page.cpp | 0 .../world_editor/world_editor_settings_page.h | 0 .../world_editor_settings_page.ui | 0 .../world_editor/world_editor_window.cpp | 0 .../world_editor/world_editor_window.h | 0 .../world_editor/world_editor_window.ui | 0 .../src/plugins/zone_painter/CMakeLists.txt | 0 .../zone_painter/images/color-fill.png | Bin .../images/color-picker-black.png | Bin .../plugins/zone_painter/images/colorize.png | Bin .../zone_painter/images/draw-brush.png | Bin .../plugins/zone_painter/images/go-down-7.png | Bin .../plugins/zone_painter/images/go-jump-4.png | Bin .../plugins/zone_painter/images/lock-6.png | Bin .../zone_painter/images/lock-silver.png | Bin .../zone_painter/ovqt_plugin_zone_painter.xml | 0 .../zone_painter/painter_dock_widget.cpp | 0 .../zone_painter/painter_dock_widget.h | 0 .../zone_painter/painter_dock_widget.ui | 0 .../src/plugins/zone_painter/qnel_widget.cpp | 0 .../src/plugins/zone_painter/qnel_widget.h | 0 .../src/plugins/zone_painter/zone_painter.qrc | 0 .../zone_painter/zone_painter_main_window.cpp | 0 .../zone_painter/zone_painter_main_window.h | 0 .../zone_painter/zone_painter_main_window.ui | 0 .../zone_painter/zone_painter_model.cpp | 0 .../plugins/zone_painter/zone_painter_model.h | 0 .../zone_painter/zone_painter_plugin.cpp | 0 .../zone_painter/zone_painter_plugin.h | 0 .../zone_painter_settings_page.cpp | 0 .../zone_painter/zone_painter_settings_page.h | 0 .../zone_painter_settings_page.ui | 0 .../src/translations/object_viewer_qt_de.ts | 0 .../src/translations/object_viewer_qt_en.ts | 0 .../src/translations/object_viewer_qt_fr.ts | 0 .../src/translations/object_viewer_qt_ru.ts | 0 .../src/translations/translations.qrc | 0 872 files changed, 8 insertions(+), 3892 deletions(-) delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_crash.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_new.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_path_settings.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_redo.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save_as.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_undo.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icontext.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/preferences.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/ioptions_page.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_generic_settings.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_down_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_pill.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_reset_all.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_up_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png rename code/{nel/tools/3d/object_viewer_qt => studio}/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/data/andbasr.ttf (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cdirection_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cedit_color_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cedit_range_float_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cedit_range_int_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/gui_struct.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/object_viewer_qt_window.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/make_ovqt_dox.bat (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/make_ovqt_dox.sh (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/ovqt.dox (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/ovqt_config.h.cmake (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/LICENSE.LGPL (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtBrowserItem (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCharEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCharPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtColorEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtColorPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDateEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDatePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtFontEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtFontPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtIntPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtLineEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtPointPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtProperty (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtRectPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtScrollBarFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSizePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSliderFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtStringPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtTimeEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtTimePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtVariantProperty (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/README.TXT (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-busy.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-cross.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-hand.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-wait.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/resetproperty.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qteditorfactory.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertymanager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtvariantproperty.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/description.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/iplugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/iplugin_manager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/iplugin_spec.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_manager.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_manager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_spec.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_spec.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/ic_nel_pill.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/images/nel_ide_load.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/main.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/object_viewer_qt.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/object_viewer_qt.rc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_dirtree_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_dirtree_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_file.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_file.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filelist_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filelist_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filelist_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filesystem_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filesystem_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_proxy_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_proxy_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_bnp_make.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_export.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_new.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_reset_all.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/sheet_id_view.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/sheet_id_view.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/sheet_id_view.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/ovqt_plugin_example.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/qnel_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/qnel_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/simple_viewer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/simple_viewer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/actions.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/actions.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/expandable_headerview.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/expandable_headerview.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formdelegate.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formdelegate.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formitem.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formitem.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_dirtree_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_dirtree_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_dirtree_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_form.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_form.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_filesystem_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_filesystem_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_treeview_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_treeview_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_treeview_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_proxy_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_proxy_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/array.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/header.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/hold.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/ic_nel_georges_editor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/root.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/struct.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/vstruct.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/zfee51.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/stdpch.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/stdpch.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/action_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/action_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/action_editor.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/add_widget_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/add_widget_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/add_widget_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_message_processor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_message_processor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_selection_watcher.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_selection_watcher.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_context.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_context.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_core_listener.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_core_listener.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_global.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_editor.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_list.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_list.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_list.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nel3d_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nel3d_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nelgui_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nelgui_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_property_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_property_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_property_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_widget_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_widget_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_widget_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_editor.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_list.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_list.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_list.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_parser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_parser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_serializer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_serializer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_files.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_files/login.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/property_browser_ctrl.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/property_browser_ctrl.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_hierarchy.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_hierarchy.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_hierarchy.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_serializer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_serializer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_tree.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_tree_node.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_tree_visitor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties_parser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties_parser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_serializer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_serializer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlBase.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlBaseButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlColPick.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlScroll.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlTabButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlTextButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewBar.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewBar3.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewDigit.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewNumber.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewQuantity.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupCell.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupContainer.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupEditBox.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupFrame.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupHTML.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupHeader.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupList.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupMenu.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupModal.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupParagraph.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupScrollText.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupTab.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupTable.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupTree.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/InterfaceElement.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/InterfaceGroup.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/RootGroup.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewBitmap.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewText.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewTextFormated.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewTextID.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_base.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_base.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_region.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_region.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_grid.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_transition_land.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_world_editor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_zone.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_zonel.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_zones.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_snapshot.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_actions.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_actions.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_global.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene_base.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene_base.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_view.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_view.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/pixmap_database.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/pixmap_database.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/project_settings_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/project_settings_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/project_settings_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/shapshot_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/snapshot_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/snapshot_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/zone_region_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/zone_region_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/ovqt_plugin_log.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/qt_displayer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/qt_displayer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-left-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-left-double-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-right-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-right-double-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/document-export-4.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_down_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_generic_settings.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_reset_all.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_up_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/news-subscribe-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/run-build-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_plugin_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/server_entry_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/server_entry_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/server_entry_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/validation_file.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/validation_file.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_viewport.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_viewport.h (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_anim.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_animset.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_append_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_bgcolor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_add.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_del.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_fps.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_daynight.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_down_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_framedelay.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_insert_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_mixer.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_new.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core => studio/src/plugins/object_viewer}/icons/ic_nel_open.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_particle_system.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_particles.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core => studio/src/plugins/object_viewer}/icons/ic_nel_pill.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_reset_all.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_reset_camera.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_save.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_save_as.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_skelscale.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_sound.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_up_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_veget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_vegetset.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_water.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_wind.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_workspace_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/dqynight.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/ico_mrm_mesh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/mixer.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core => studio/src/plugins/object_viewer}/images/nel.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/pause.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/play.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/polymode.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/pqrticles.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/refresh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/rmfill.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/rmline.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/rmpoints.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/seek-backward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/seek-forward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/skip-backward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/skip-forward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/sound.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/stop.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/water.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/wind.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/modules.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/modules.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/attrib_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/attrib_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/attrib_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/auto_lod_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/auto_lod_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/basic_edit_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/basic_edit_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/bin_op_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/curve_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/curve_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/curve_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/direction_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/direction_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/direction_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/dup_ps.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/dup_ps.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/emitter_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/emitter_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/emitter_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/follow_path_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_bindable_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_bindable_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_bindable_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/mesh_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/mesh_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/mesh_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/morph_mesh_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/multi_tex_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/multi_tex_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_control_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_control_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_force_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_force_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_force_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_light_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_light_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_light_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_node.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_node.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_property_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_sound_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_sound_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_sound_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_system_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_system_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_system_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_tree_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_tree_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_zone_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_zone_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_zone_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_initial_pos.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_mover_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_mover_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_mover_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_wrapper.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_bank_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_manager.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_manager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/spinner_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/spinner_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/tail_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/tail_particle_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_blender_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_gradient_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_gradient_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/workspace_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_set_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_set_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_set_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/camera_control.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/camera_control.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/day_night_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/day_night_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/day_night_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/entity.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/entity.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/global_wind_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/global_wind_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/global_wind_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/setup_fog_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/setup_fog_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/setup_fog_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_scale_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_scale_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_tree_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_tree_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/slot_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/slot_manager_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/slot_manager_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/sun_color_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/sun_color_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/sun_color_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_mrm_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_mrm_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_timer_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_timer_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_timer_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/water_pool_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/water_pool_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/water_pool_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_system.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_system.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/stdpch.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/stdpch.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_density_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_density_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_node.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_node.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_scale_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/color_edit_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/color_edit_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/color_edit_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_float_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_uint_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/hoverpoints.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/hoverpoints.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilder.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/add_tile.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/delete_image.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/delete_tile.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/down.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/empty_image.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons => studio/src/plugins/tile_editor/images}/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons => studio/src/plugins/tile_editor/images}/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/ic_nel_new.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons => studio/src/plugins/tile_editor/images}/ic_nel_open.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/ic_nel_save.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/ic_nel_save_as.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/left.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer => studio/src/plugins/tile_editor}/images/nel.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/replace_image.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/reset.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/right.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation0.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation180.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation270.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation90.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/up.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item_delegate.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item_delegate.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/README (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_phrase.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_phrase.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_worksheet.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_worksheet.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_bot_names.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_bot_names.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_new_sheet_names.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_new_sheet_names.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/images/cdtoparent.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/images/dir.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/images/file.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/source_selection.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/source_selection.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/source_selection.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_move.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_rotate.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_scale.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_select.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_turn.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_world_editor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/ovqt_plugin_world_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitive_item.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitive_item.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_view.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_view.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/project_settings_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/project_settings_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/project_settings_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/property_editor_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/property_editor_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/property_editor_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_actions.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_actions.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_global.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_misc.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_misc.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene_item.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene_item.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/color-fill.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/color-picker-black.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/colorize.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/draw-brush.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/go-down-7.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/go-jump-4.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/lock-6.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/lock-silver.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/painter_dock_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/painter_dock_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/painter_dock_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/qnel_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/qnel_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_de.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_en.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_fr.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_ru.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/translations.qrc (100%) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 4f0439dfd..ba40d803e 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -190,6 +190,10 @@ IF(WITH_TOOLS) ADD_SUBDIRECTORY(tool) ENDIF(WITH_TOOLS) +IF(WITH_STUDIO) + ADD_SUBDIRECTORY(studio) +ENDIF(WITH_STUDIO) + # To build the documention, you will have to enable it # and then do the equivalent of "make DoxygenDoc". IF(BUILD_DOCUMENTATION) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index b194b5ff9..36b813fa2 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -229,6 +229,10 @@ Remove the CMakeCache.txt file and try again from another folder, e.g.: ENDMACRO(CHECK_OUT_OF_SOURCE) MACRO(NL_SETUP_DEFAULT_OPTIONS) + IF(WITH_QT) + OPTION(WITH_STUDIO "Build Core Studio" OFF ) + ENDIF(WITH_QT) + ### # Features ### diff --git a/code/nel/tools/3d/CMakeLists.txt b/code/nel/tools/3d/CMakeLists.txt index cc3b54f02..c9981e276 100644 --- a/code/nel/tools/3d/CMakeLists.txt +++ b/code/nel/tools/3d/CMakeLists.txt @@ -56,7 +56,6 @@ IF(WITH_NEL_TOOLS) IF(WITH_QT) ADD_SUBDIRECTORY(tile_edit_qt) - ADD_SUBDIRECTORY(object_viewer_qt) ADD_SUBDIRECTORY(object_viewer_widget) ENDIF(WITH_QT) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt deleted file mode 100644 index 5a20ba46c..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) - -FILE(GLOB SRC *.cpp *.h) -SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) - -SET(OVQT_CORE_PLUGIN_HDR - icore.h - icontext.h - icore_listener.h - ioptions_page.h - core_plugin.h - core.h - main_window.h - menu_manager.h - context_manager.h - settings_dialog.h - search_paths_settings_page.h - general_settings_page.h - plugin_view_dialog.h -) - -SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui - plugin_view_dialog.ui - general_settings_page.ui - search_paths_settings_page.ui -) - -SET(OVQT_CORE_PLUGIN_RCS core.qrc) - -SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) - -QT4_ADD_RESOURCES(OVQT_CORE_PLUGIN_RC_SRCS ${OVQT_CORE_PLUGIN_RCS}) -QT4_WRAP_CPP(OVQT_CORE_PLUGIN_MOC_SRC ${OVQT_CORE_PLUGIN_HDR}) -QT4_WRAP_UI(OVQT_CORE_PLUGIN_UI_HDRS ${OVQT_CORE_PLUGIN_UIS}) - -SOURCE_GROUP(QtResources FILES ${OVQT_CORE_PLUGIN_UIS} ${OVQT_CORE_PLUGIN_RCS}) -SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_CORE_PLUGIN_UI_HDRS}) -SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) -SOURCE_GROUP("Core Plugin" FILES ${SRC}) -SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) - -ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) - -TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) - -NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) -NL_ADD_LIB_SUFFIX(ovqt_plugin_core) - -ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) - -IF(WIN32) - IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) - ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) - ENDIF(WITH_INSTALL_LIBRARIES) -ELSE(WIN32) - IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) - ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) - ENDIF(WITH_INSTALL_LIBRARIES) -ENDIF(WIN32) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp deleted file mode 100644 index 8355b5cb8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "context_manager.h" -#include "icontext.h" -#include "main_window.h" - -// NeL includes -#include - -// Qt includes -#include -#include - -namespace Core -{ - -struct ContextManagerPrivate -{ - explicit ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget); - Core::MainWindow *m_mainWindow; - QTabWidget *m_tabWidget; - QVector m_contexts; - int m_oldCurrent; -}; - -ContextManagerPrivate::ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget) - : m_mainWindow(mainWindow), - m_tabWidget(tabWidget), - m_oldCurrent(-1) -{ -} - -ContextManager::ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget) - : d(new ContextManagerPrivate(mainWindow, tabWidget)) -{ - QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(objectAdded(QObject *)), - this, SLOT(objectAdded(QObject *))); - QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(aboutToRemoveObject(QObject *)), - this, SLOT(aboutToRemoveObject(QObject *))); - - QObject::connect(d->m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); -} - -ContextManager::~ContextManager() -{ - delete d; -} - -Core::IContext *ContextManager::currentContext() const -{ - int currentIndex = d->m_tabWidget->currentIndex(); - if (currentIndex < 0) - return 0; - return d->m_contexts.at(currentIndex); -} - -Core::IContext *ContextManager::context(const QString &id) const -{ - const int index = indexOf(id); - if (index >= 0) - return d->m_contexts.at(index); - return 0; -} - -void ContextManager::registerUndoStack(QUndoStack *stack) -{ - nlassert(stack); - d->m_mainWindow->undoGroup()->addStack(stack); -} - -void ContextManager::unregisterUndoStack(QUndoStack *stack) -{ - nlassert(stack); - d->m_mainWindow->undoGroup()->removeStack(stack); -} - -void ContextManager::activateContext(const QString &id) -{ - const int index = indexOf(id); - if (index >= 0) - d->m_tabWidget->setCurrentIndex(index); -} - -void ContextManager::updateCurrentContext() -{ - d->m_mainWindow->updateContext(currentContext()); -} - -void ContextManager::objectAdded(QObject *obj) -{ - IContext *context = qobject_cast(obj); - if (context) - addContextObject(context); -} - -void ContextManager::aboutToRemoveObject(QObject *obj) -{ - IContext *context = qobject_cast(obj); - if (context) - removeContextObject(context); -} - -void ContextManager::addContextObject(IContext *context) -{ - d->m_contexts.push_back(context); - d->m_mainWindow->addContextObject(context); - - QWidget *tabWidget = new QWidget(d->m_tabWidget); - d->m_tabWidget->addTab(tabWidget, context->icon(), context->trName()); - QGridLayout *gridLayout = new QGridLayout(tabWidget); - gridLayout->setObjectName(QString::fromUtf8("gridLayout_") + context->id()); - gridLayout->setContentsMargins(0, 0, 0, 0); - gridLayout->addWidget(context->widget(), 0, 0, 1, 1); -} - -void ContextManager::removeContextObject(IContext *context) -{ - d->m_mainWindow->removeContextObject(context); - - const int index = indexOf(context->id()); - QWidget *widget = d->m_tabWidget->widget(index); - d->m_tabWidget->removeTab(index); - d->m_contexts.remove(index); - delete widget; -} - -void ContextManager::currentTabChanged(int index) -{ - if (index >= 0) - { - IContext *context = d->m_contexts.at(index); - IContext *oldContext = 0; - if (d->m_oldCurrent >= 0) - oldContext = d->m_contexts.at(d->m_oldCurrent); - d->m_oldCurrent = index; - Q_EMIT currentContextChanged(context, oldContext); - } -} - -int ContextManager::indexOf(const QString &id) const -{ - for (int i = 0; i < d->m_contexts.count(); ++i) - { - if (d->m_contexts.at(i)->id() == id) - return i; - } - nlwarning(QString("Warning, no such context: %1").arg(id).toUtf8().constData()); - return -1; -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h deleted file mode 100644 index 8151648e7..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h +++ /dev/null @@ -1,76 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CONTEXT_MANAGER_H -#define CONTEXT_MANAGER_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include - -QT_BEGIN_NAMESPACE -class QTabWidget; -class QUndoStack; -QT_END_NAMESPACE - -namespace Core -{ -class IContext; -class MainWindow; -struct ContextManagerPrivate; - -class CORE_EXPORT ContextManager : public QObject -{ - Q_OBJECT - -public: - explicit ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget); - virtual ~ContextManager(); - - Core::IContext *currentContext() const; - Core::IContext *context(const QString &id) const; - - // temporary solution for multiple undo stacks per context - void registerUndoStack(QUndoStack *stack); - void unregisterUndoStack(QUndoStack *stack); - -Q_SIGNALS: - // the default argument '=0' is important for connects without the oldContext argument. - void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0); - -public Q_SLOTS: - void activateContext(const QString &id); - void updateCurrentContext(); - -private Q_SLOTS: - void objectAdded(QObject *obj); - void aboutToRemoveObject(QObject *obj); - void addContextObject(IContext *context); - void removeContextObject(IContext *context); - void currentTabChanged(int index); - -private: - int indexOf(const QString &id) const; - - ContextManagerPrivate *d; -}; - -} // namespace Core - -#endif // CONTEXT_MANAGER_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp deleted file mode 100644 index b21d934c8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "core.h" -#include "context_manager.h" -#include "main_window.h" -#include "../../extension_system/iplugin_manager.h" - -static Core::CoreImpl *m_coreInstance = 0; - -namespace Core -{ - -ICore *ICore::instance() -{ - return m_coreInstance; -} - -CoreImpl::CoreImpl(MainWindow *mainWindow) -{ - m_mainWindow = mainWindow; - m_coreInstance = this; -} - -CoreImpl::~CoreImpl() -{ - m_coreInstance = 0; -} - -bool CoreImpl::showOptionsDialog(const QString &group, - const QString &page, - QWidget *parent) -{ - return m_mainWindow->showOptionsDialog(group, page, parent); -} - -MenuManager *CoreImpl::menuManager() const -{ - return m_mainWindow->menuManager(); -} - -ContextManager *CoreImpl::contextManager() const -{ - return m_mainWindow->contextManager(); -} - -QSettings *CoreImpl::settings() const -{ - return m_mainWindow->settings(); -} - -QMainWindow *CoreImpl::mainWindow() const -{ - return m_mainWindow; -} - -ExtensionSystem::IPluginManager *CoreImpl::pluginManager() const -{ - return m_mainWindow->pluginManager(); -} - -} // namespace Core diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h deleted file mode 100644 index f34dd6ae6..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h +++ /dev/null @@ -1,54 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_H -#define CORE_H - -#include "icore.h" - -namespace Core -{ -class MainWindow; - -class CoreImpl : public ICore -{ - Q_OBJECT - -public: - explicit CoreImpl(MainWindow *mainWindow); - virtual ~CoreImpl(); - - virtual bool showOptionsDialog(const QString &group = QString(), - const QString &page = QString(), - QWidget *parent = 0); - - virtual MenuManager *menuManager() const; - virtual ContextManager *contextManager() const; - - virtual QSettings *settings() const; - virtual QMainWindow *mainWindow() const; - - virtual ExtensionSystem::IPluginManager *pluginManager() const; -private: - MainWindow *m_mainWindow; - friend class MainWindow; -}; - -} // namespace Core - -#endif // CORE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc deleted file mode 100644 index 68b6ad141..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc +++ /dev/null @@ -1,21 +0,0 @@ - - - icons/ic_nel_add_item.png - icons/ic_nel_redo.png - icons/ic_nel_undo.png - icons/ic_nel_crash.png - icons/ic_nel_delete_item.png - icons/ic_nel_down_item.png - icons/ic_nel_generic_settings.png - icons/ic_nel_open.png - icons/ic_nel_new.png - icons/ic_nel_save.png - icons/ic_nel_save_as.png - icons/ic_nel_path_settings.png - icons/ic_nel_pill.png - icons/ic_nel_reset_all.png - icons/ic_nel_up_item.png - images/nel.png - images/preferences.png - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h deleted file mode 100644 index 8bf6d5fcd..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h +++ /dev/null @@ -1,121 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2010 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_CONSTANTS_H -#define CORE_CONSTANTS_H - -namespace Core -{ -namespace Constants -{ - -const char *const OVQT_VERSION_LONG = "0.8"; -const char *const OVQT_VENDOR = "Ryzom Core"; -const char *const OVQT_YEAR = "2010, 2011"; -const char *const OVQT_CORE_PLUGIN = "Core"; - -//mainwindow -const char *const MAIN_WINDOW = "ObjectViewerQt.MainWindow"; - -//menubar -const char *const MENU_BAR = "ObjectViewerQt.MenuBar"; - -//menus -const char *const M_FILE = "ObjectViewerQt.Menu.File"; -const char *const M_EDIT = "ObjectViewerQt.Menu.Edit"; -const char *const M_VIEW = "ObjectViewerQt.Menu.View"; -const char *const M_SCENE = "ObjectViewerQt.Menu.Scene"; -const char *const M_TOOLS = "ObjectViewerQt.Menu.Tools"; -const char *const M_WINDOW = "ObjectViewerQt.Menu.Window"; -const char *const M_HELP = "ObjectViewerQt.Menu.Help"; - -const char *const M_FILE_RECENTFILES = "ObjectViewerQt.Menu.File.RecentFiles"; -const char *const M_SHEET = "ObjectViewerQt.Menu.Sheet"; - -//actions -const char *const NEW = "ObjectViewerQt.New"; -const char *const OPEN = "ObjectViewerQt.Open"; -const char *const SAVE = "ObjectViewerQt.Save"; -const char *const SAVE_AS = "ObjectViewerQt.SaveAs"; -const char *const SAVE_ALL = "ObjectViewerQt.SaveAll"; -const char *const EXIT = "ObjectViewerQt.Exit"; - -const char *const UNDO = "ObjectViewerQt.Undo"; -const char *const REDO = "ObjectViewerQt.Redo"; -const char *const CUT = "ObjectViewerQt.Cut"; -const char *const COPY = "ObjectViewerQt.Copy"; -const char *const PASTE = "ObjectViewerQt.Paste"; -const char *const DEL = "ObjectViewerQt.Del"; -const char *const FIND = "ObjectViewerQt.Find"; -const char *const SELECT_ALL = "ObjectViewerQt.SelectAll"; -const char *const GOTO_POS = "ObjectViewerQt.Goto"; - -const char *const SETTINGS = "ObjectViewerQt.Settings"; -const char *const TOGGLE_FULLSCREEN = "ObjectViewerQt.ToggleFullScreen"; - -const char *const CLOSE = "ObjectViewerQt.Close"; -const char *const CLOSEALL = "ObjectViewerQt.CloseAll"; -const char *const CLOSEOTHERS = "ObjectViewerQt.CloseOthers"; -const char *const ABOUT = "ObjectViewerQt.About"; -const char *const ABOUT_PLUGINS = "ObjectViewerQt.AboutPlugins"; -const char *const ABOUT_QT = "ObjectViewerQt.AboutQt"; - -//settings -const char *const SETTINGS_CATEGORY_GENERAL = "general"; -const char *const SETTINGS_CATEGORY_GENERAL_ICON = ":/icons/ic_nel_generic_settings.png"; -const char *const SETTINGS_TR_CATEGORY_GENERAL = QT_TR_NOOP("General"); - -const char *const MAIN_WINDOW_SECTION = "MainWindow"; -const char *const MAIN_WINDOW_STATE = "WindowState"; -const char *const MAIN_WINDOW_GEOMETRY = "WindowGeometry"; -const char *const QT_STYLE = "QtStyle"; -const char *const QT_PALETTE = "QtPalette"; - -const char *const LANGUAGE = "Language"; -const char *const PLUGINS_PATH = "PluginPath"; -const char *const DATA_PATH_SECTION = "DataPath"; -const char *const SEARCH_PATHS = "SearchPaths"; -const char *const RECURSIVE_SEARCH_PATHS = "RecursiveSearchPathes"; -const char *const LEVELDESIGN_PATH = "LevelDesignPath"; -const char *const PRIMITIVES_PATH = "PrimitivesPath"; -const char *const ASSETS_PATH = "AssetsPath"; -const char *const LIGOCONFIG_FILE = "LigoConfigFile"; -const char *const REMAP_EXTENSIONS = "RemapExtensions"; - -const char *const LOG_SECTION = "LogSettings"; -const char *const LOG_ERROR = "LogError"; -const char *const LOG_WARNING = "LogWarning"; -const char *const LOG_DEBUG = "LogDebug"; -const char *const LOG_ASSERT = "LogAssert"; -const char *const LOG_INFO = "LogInfo"; - -//resources -const char *const ICON_NEL = ":/core/images/nel.png"; -const char *const ICON_SETTINGS = ":/core/images/preferences.png"; -const char *const ICON_PILL = ":/core/icons/ic_nel_pill.png"; -const char *const ICON_OPEN = ":/core/icons/ic_nel_open.png"; -const char *const ICON_NEW = ":/core/icons/ic_nel_new.png"; -const char *const ICON_SAVE = ":/core/icons/ic_nel_save.png"; -const char *const ICON_SAVE_AS = ":/core/icons/ic_nel_save_as.png"; -const char *const ICON_CRASH = ":/core/icons/ic_nel_crash.png"; -const char *const ICON_UNDO = ":/core/icons/ic_nel_undo.png"; -const char *const ICON_REDO = ":/core/icons/ic_nel_redo.png"; - -} // namespace Constants -} // namespace Core - -#endif // CORE_CONSTANTS_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h deleted file mode 100644 index 48fe0ece9..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h +++ /dev/null @@ -1,30 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_GLOBAL_H -#define CORE_GLOBAL_H - -#include - -#if defined(CORE_LIBRARY) -# define CORE_EXPORT Q_DECL_EXPORT -#else -# define CORE_EXPORT Q_DECL_IMPORT -#endif - -#endif // CORE_GLOBAL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp deleted file mode 100644 index a72a68ccc..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2010 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "core_plugin.h" -#include "settings_dialog.h" -#include "core_constants.h" -#include "search_paths_settings_page.h" -#include "general_settings_page.h" -#include "../../extension_system/iplugin_spec.h" - -// NeL includes -#include "nel/misc/debug.h" - -// Qt includes -#include -#include -#include -#include -#include -#include - -using namespace Core; - -CorePlugin::CorePlugin() - : m_plugMan(0), - m_mainWindow(0) -{ -} - -CorePlugin::~CorePlugin() -{ - Q_FOREACH(QObject *obj, m_autoReleaseObjects) - { - m_plugMan->removeObject(obj); - } - qDeleteAll(m_autoReleaseObjects); - m_autoReleaseObjects.clear(); - - if (m_mainWindow) - delete m_mainWindow; -} - -bool CorePlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) -{ - Q_UNUSED(errorString); - m_plugMan = pluginManager; - - m_mainWindow = new MainWindow(pluginManager); - bool success = m_mainWindow->initialize(errorString); - - GeneralSettingsPage *generalSettings = new GeneralSettingsPage(this); - SearchPathsSettingsPage *searchPathPage = new SearchPathsSettingsPage(false, this); - SearchPathsSettingsPage *recureseSearchPathPage = new SearchPathsSettingsPage(true, this); - - generalSettings->applyGeneralSettings(); - searchPathPage->applySearchPaths(); - recureseSearchPathPage->applySearchPaths(); - addAutoReleasedObject(generalSettings); - addAutoReleasedObject(searchPathPage); - addAutoReleasedObject(recureseSearchPathPage); - return success; -} - -void CorePlugin::extensionsInitialized() -{ - m_mainWindow->extensionsInitialized(); -} - -void CorePlugin::shutdown() -{ -} - -void CorePlugin::setNelContext(NLMISC::INelContext *nelContext) -{ -#ifdef NL_OS_WINDOWS - // Ensure that a context doesn't exist yet. - // This only applies to platforms without PIC, e.g. Windows. - nlassert(!NLMISC::INelContext::isContextInitialised()); -#endif // NL_OS_WINDOWS - m_libContext = new NLMISC::CLibraryContext(*nelContext); -} - -void CorePlugin::addAutoReleasedObject(QObject *obj) -{ - m_plugMan->addObject(obj); - m_autoReleaseObjects.prepend(obj); -} - -Q_EXPORT_PLUGIN(CorePlugin) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h deleted file mode 100644 index 5062227e3..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h +++ /dev/null @@ -1,74 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2010 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_PLUGIN_H -#define CORE_PLUGIN_H - -#include "../../extension_system/iplugin.h" -#include "main_window.h" - -#include "nel/misc/app_context.h" - -#include - -namespace NLMISC -{ -class CLibraryContext; -} - -namespace ExtensionSystem -{ -class IPluginSpec; -} - -namespace Core -{ - -class CorePlugin : public QObject, public ExtensionSystem::IPlugin -{ - Q_OBJECT - Q_INTERFACES(ExtensionSystem::IPlugin) -public: - - CorePlugin(); - virtual ~CorePlugin(); - - bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); - void extensionsInitialized(); - void shutdown(); - - void setNelContext(NLMISC::INelContext *nelContext); - - void addAutoReleasedObject(QObject *obj); - - ExtensionSystem::IPluginManager *pluginManager() const - { - return m_plugMan; - } - -protected: - NLMISC::CLibraryContext *m_libContext; - -private: - ExtensionSystem::IPluginManager *m_plugMan; - MainWindow *m_mainWindow; - QList m_autoReleaseObjects; -}; - -} // namespace Core - -#endif // CORE_PLUGIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp deleted file mode 100644 index bfbb06d66..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "general_settings_page.h" -#include "core_constants.h" -#include "icore.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -namespace Core -{ - -GeneralSettingsPage::GeneralSettingsPage(QObject *parent) - : IOptionsPage(parent), - m_page(0) -{ - m_originalPalette = QApplication::palette(); -} - -GeneralSettingsPage::~GeneralSettingsPage() -{ -} - -QString GeneralSettingsPage::id() const -{ - return QLatin1String("general_settings"); -} - -QString GeneralSettingsPage::trName() const -{ - return tr("General"); -} - -QString GeneralSettingsPage::category() const -{ - return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); -} - -QString GeneralSettingsPage::trCategory() const -{ - return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); -} - -QIcon GeneralSettingsPage::categoryIcon() const -{ - return QIcon(); -} - -void GeneralSettingsPage::applyGeneralSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - - settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - QApplication::setStyle(QStyleFactory::create(settings->value(Constants::QT_STYLE, "").toString())); - - if (settings->value(Constants::QT_PALETTE, true).toBool()) - QApplication::setPalette(QApplication::style()->standardPalette()); - else - QApplication::setPalette(m_originalPalette); - settings->endGroup(); - - QString levelDesignPrefix; -#if defined(_DEBUG) && defined(NL_OS_WINDOWS) - levelDesignPrefix = "l:"; -#else - levelDesignPrefix = QString("%1/data_leveldesign").arg(RYZOM_SHARE_PREFIX); -#endif - - // Add primitives path and ligo config file to CPath - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - QString primitivePath = settings->value(Core::Constants::PRIMITIVES_PATH, QString("%1/primitives").arg(levelDesignPrefix)).toString(); - QString ligoConfigFile = settings->value(Core::Constants::LIGOCONFIG_FILE, QString("%1/leveldesign/world_editor_files/world_editor_classes.xml").arg(levelDesignPrefix)).toString(); - QString leveldesignPath = settings->value(Core::Constants::LEVELDESIGN_PATH, QString("%1/leveldesign").arg(levelDesignPrefix)).toString(); - NLMISC::CPath::addSearchPath(primitivePath.toUtf8().constData(), true, false); - NLMISC::CPath::display(); - NLMISC::CPath::addSearchFile(ligoConfigFile.toUtf8().constData()); - NLMISC::CPath::addSearchPath(leveldesignPath.toUtf8().constData(), true, false); - settings->endGroup(); -} - -QWidget *GeneralSettingsPage::createPage(QWidget *parent) -{ - m_page = new QWidget(parent); - m_ui.setupUi(m_page); - - readSettings(); - connect(m_ui.languageComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(changeLanguage(QString))); - connect(m_ui.pluginsPathButton, SIGNAL(clicked()), this, SLOT(setPluginsPath())); - connect(m_ui.leveldesignPathButton, SIGNAL(clicked()), this, SLOT(setLevelDesignPath())); - connect(m_ui.assetsPathButton, SIGNAL(clicked()), this, SLOT(setAssetsPath())); - connect(m_ui.primitivesPathButton, SIGNAL(clicked()), this, SLOT(setPrimitivesPath())); - connect(m_ui.ligoConfigFileButton, SIGNAL(clicked()), this, SLOT(setLigoConfigFile())); - return m_page; -} - -void GeneralSettingsPage::apply() -{ - writeSettings(); - applyGeneralSettings(); -} - -void GeneralSettingsPage::finish() -{ - delete m_page; - m_page = 0; -} - -void GeneralSettingsPage::changeLanguage(const QString &lang) -{ - QMessageBox::information(0, tr("Restart required"), - tr("The language change will take effect after a restart of Object Viewer Qt.")); -} - -void GeneralSettingsPage::setPluginsPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the plugins path"), - m_ui.pluginsPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.pluginsPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::setLevelDesignPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the level design path"), - m_ui.leveldesignPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.leveldesignPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::setPrimitivesPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the primitives path"), - m_ui.primitivesPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.primitivesPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::setLigoConfigFile() -{ - QString newFile = QFileDialog::getOpenFileName(0, tr("Set the ligo config file"), - m_ui.ligoConfigFileLineEdit->text()); - if (!newFile.isEmpty()) - { - m_ui.ligoConfigFileLineEdit->setText(newFile); - } -} - - -void GeneralSettingsPage::setAssetsPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the assets path"), - m_ui.assetsPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.assetsPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::readSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - - m_ui.pluginsPathLineEdit->setText(settings->value(Core::Constants::PLUGINS_PATH, "./plugins").toString()); - - settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - m_ui.styleComboBox->addItems(QStyleFactory::keys()); - QString style = settings->value(Constants::QT_STYLE, "").toString(); - if (style == "") - m_ui.styleComboBox->setCurrentIndex(0); - else - m_ui.styleComboBox->setCurrentIndex(m_ui.styleComboBox->findText(style)); - m_ui.paletteCheckBox->setChecked(settings->value(Constants::QT_PALETTE, true).toBool()); - settings->endGroup(); - - QStringList paths; - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - m_ui.leveldesignPathLineEdit->setText(settings->value(Core::Constants::LEVELDESIGN_PATH, "l:/leveldesign").toString()); - m_ui.assetsPathLineEdit->setText(settings->value(Core::Constants::ASSETS_PATH, "w:/database").toString()); - m_ui.primitivesPathLineEdit->setText(settings->value(Core::Constants::PRIMITIVES_PATH, "l:/primitives").toString()); - m_ui.ligoConfigFileLineEdit->setText(settings->value(Core::Constants::LIGOCONFIG_FILE, "l:/leveldesign/world_editor_files/world_editor_classes.xml").toString()); - settings->endGroup(); -} - -void GeneralSettingsPage::writeSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - - settings->setValue(Core::Constants::PLUGINS_PATH, m_ui.pluginsPathLineEdit->text()); - - settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - if (m_ui.styleComboBox->currentIndex() == 0) - settings->setValue(Constants::QT_STYLE, ""); - else - settings->setValue(Constants::QT_STYLE, m_ui.styleComboBox->currentText()); - settings->setValue(Constants::QT_PALETTE, m_ui.paletteCheckBox->isChecked()); - settings->endGroup(); - - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - settings->setValue(Core::Constants::LEVELDESIGN_PATH, m_ui.leveldesignPathLineEdit->text()); - settings->setValue(Core::Constants::ASSETS_PATH, m_ui.assetsPathLineEdit->text()); - settings->setValue(Core::Constants::PRIMITIVES_PATH, m_ui.primitivesPathLineEdit->text()); - settings->setValue(Core::Constants::LIGOCONFIG_FILE, m_ui.ligoConfigFileLineEdit->text()); - settings->endGroup(); - settings->sync(); -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h deleted file mode 100644 index 66eacd189..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h +++ /dev/null @@ -1,74 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef GENERAL_SETTINGS_PAGE_H -#define GENERAL_SETTINGS_PAGE_H - -#include - -#include "ioptions_page.h" - -#include "ui_general_settings_page.h" - -class QWidget; - -namespace Core -{ -/** -@class GeneralSettingsPage -*/ -class GeneralSettingsPage : public Core::IOptionsPage -{ - Q_OBJECT - -public: - explicit GeneralSettingsPage(QObject *parent = 0); - ~GeneralSettingsPage(); - - QString id() const; - QString trName() const; - QString category() const; - QString trCategory() const; - QIcon categoryIcon() const; - QWidget *createPage(QWidget *parent); - - void apply(); - void finish(); - - void applyGeneralSettings(); - -private Q_SLOTS: - void changeLanguage(const QString &lang); - void setPluginsPath(); - void setLevelDesignPath(); - void setAssetsPath(); - void setPrimitivesPath(); - void setLigoConfigFile(); - -private: - void readSettings(); - void writeSettings(); - - QPalette m_originalPalette; - QWidget *m_page; - Ui::GeneralSettingsPage m_ui; -}; - -} // namespace Core - -#endif // GENERAL_SETTINGS_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui deleted file mode 100644 index 7d40b65df..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui +++ /dev/null @@ -1,233 +0,0 @@ - - - GeneralSettingsPage - - - - 0 - 0 - 267 - 282 - - - - Form - - - - 6 - - - 3 - - - - - Qt Style - - - - 6 - - - 6 - - - - - - default - - - - - - - - Use style's standard palette - - - - - - - - - - Language - - - - 6 - - - - - false - - - - English - - - - - German - - - - - French - - - - - Russian - - - - - - - - - - - Paths - - - - 6 - - - 6 - - - - - Plugins - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - Sheets - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - Assets Database: - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - Primitives - - - - - - - - - - ... - - - - - - - - - - Ligo Config File - - - - - - - ... - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_crash.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_crash.png deleted file mode 100644 index 5e1f6380bad86acca278838ce7a1c6499eb2660f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6630 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 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_path_settings.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_path_settings.png deleted file mode 100644 index 8f344111275abb152ae1a8d1aeabde4627ddeab0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4557 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 rVX-&<{98FWQhbW?9;ba!ELWdKlNX>N2bPDNB8 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 %I{nv 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 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save_as.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save_as.png deleted file mode 100644 index 6cb71a33436e58801b73476821800b1b95a1018e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52871 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 -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ICONTEXT_H -#define ICONTEXT_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QWidget; -class QUndoStack; -QT_END_NAMESPACE - -namespace Core -{ -/** -@interface IContext -@brief The IContext is an interface for providing tab pages in main window. -@details You need to subclass this interface and put an instance of your subclass - into the plugin manager object pool. -*/ -class CORE_EXPORT IContext: public QObject -{ - Q_OBJECT -public: - IContext(QObject *parent = 0): QObject(parent) {} - virtual ~IContext() {} - - /// id() is a unique identifier for referencing this page - virtual QString id() const = 0; - - /// trName() is the (translated) name for display. - virtual QString trName() const = 0; - - /// icon() is the icon for display - virtual QIcon icon() const = 0; - - /// The widget will be destroyed by the widget hierarchy when the main window closes - virtual QWidget *widget() = 0; - - virtual QUndoStack *undoStack() = 0; - - virtual void open() = 0; - - virtual void save(){} - - virtual void saveAs(){} - - virtual void newDocument(){} - - virtual void close(){} -}; - -} // namespace Core - -#endif // ICONTEXT_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h deleted file mode 100644 index 4f1ee474f..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h +++ /dev/null @@ -1,70 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ICORE_H -#define ICORE_H - -#include "core_global.h" - -#include - -QT_BEGIN_NAMESPACE -class QMainWindow; -class QSettings; -QT_END_NAMESPACE - -namespace ExtensionSystem -{ -class IPluginManager; -} - -namespace Core -{ -class MenuManager; -class ContextManager; - -class CORE_EXPORT ICore : public QObject -{ - Q_OBJECT - -public: - ICore() {} - virtual ~ICore() {} - - static ICore *instance(); - - virtual bool showOptionsDialog(const QString &group = QString(), - const QString &page = QString(), - QWidget *parent = 0) = 0; - - virtual MenuManager *menuManager() const = 0; - virtual ContextManager *contextManager() const = 0; - - virtual QSettings *settings() const = 0; - virtual QMainWindow *mainWindow() const = 0; - - virtual ExtensionSystem::IPluginManager *pluginManager() const = 0; - -Q_SIGNALS: - void changeSettings(); - void closeMainWindow(); -}; - -} // namespace Core - -#endif // ICORE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h deleted file mode 100644 index c27e40242..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h +++ /dev/null @@ -1,63 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ICORE_LISTENER_H -#define ICORE_LISTENER_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include - -QT_BEGIN_NAMESPACE -class QWidget; -QT_END_NAMESPACE - -namespace Core -{ -/** -@interface ICoreListener -@brief The ICoreListener is an interface for providing a hook for plugins to veto on close event emitted from -the core plugin. -@details You implement this interface if you want to prevent the closing of the whole application. -If the application window requests a close, then first ICoreListener::closeMainWindow() is called -(in arbitrary order) on all registered objects implementing this interface. -If one if these calls returns false, the process is aborted and the event is ignored. If all calls return -true, the corresponding signal is emitted and the event is accepted/performed. - -You need to add your implementing object to the plugin managers objects: -PluginManager->addObject(yourImplementingObject); -Don't forget to remove the object again at deconstruction (e.g. in the destructor of -your plugin) -*/ -class CORE_EXPORT ICoreListener: public QObject -{ - Q_OBJECT -public: - ICoreListener(QObject *parent = 0): QObject(parent) {} - virtual ~ICoreListener() {} - - /// Return false from the implemented method if you want to prevent the event. - virtual bool closeMainWindow() const = 0; -}; - -} // namespace Core - - -#endif // ICORE_LISTENER_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/preferences.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/preferences.png deleted file mode 100644 index 729bc039355928ae3b0c39969f6dbfea6154a125..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10286 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 -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef IOPTIONS_PAGE_H -#define IOPTIONS_PAGE_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include - -QT_BEGIN_NAMESPACE -class QWidget; -class QIcon; -QT_END_NAMESPACE - -namespace Core -{ -/** -@interface IOptionsPage -@brief The IOptionsPage is an interface for providing options pages. -@details You need to subclass this interface and put an instance of your subclass - into the plugin manager object pool. -*/ -class CORE_EXPORT IOptionsPage: public QObject -{ - Q_OBJECT -public: - IOptionsPage(QObject *parent = 0): QObject(parent) {} - virtual ~IOptionsPage() {} - - /// id() is a unique identifier for referencing this page - virtual QString id() const = 0; - - /// trName() is the (translated) name for display. - virtual QString trName() const = 0; - - /// category() is the unique id for the category that the page should be displayed in - virtual QString category() const = 0; - - /// trCategory() is the translated category - virtual QString trCategory() const = 0; - - virtual QIcon categoryIcon() const = 0; - - /// createPage() is called to retrieve the widget to show in the preferences dialog - /// The widget will be destroyed by the widget hierarchy when the dialog closes - virtual QWidget *createPage(QWidget *parent) = 0; - - /// apply() is called to store the settings. It should detect if any changes have been made and store those. - virtual void apply() = 0; - - /// finish() is called directly before the preferences dialog closes - virtual void finish() = 0; -}; - -} // namespace Core - -#endif // IOPTIONS_PAGE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp deleted file mode 100644 index a90e67bc0..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp +++ /dev/null @@ -1,492 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "main_window.h" -#include "icontext.h" -#include "icore_listener.h" -#include "menu_manager.h" -#include "context_manager.h" -#include "core.h" -#include "core_constants.h" -#include "settings_dialog.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace Core -{ - -MainWindow::MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) - : QMainWindow(parent), - m_pluginManager(0), - m_menuManager(0), - m_contextManager(0), - m_coreImpl(0), - m_lastDir("."), - m_undoGroup(0), - m_settings(0) -{ - QCoreApplication::setApplicationName(QLatin1String("ObjectViewerQt")); - QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::OVQT_VERSION_LONG)); - QCoreApplication::setOrganizationName(QLatin1String("RyzomCore")); - - setObjectName(Constants::MAIN_WINDOW); - setWindowIcon(QIcon(Constants::ICON_PILL)); - setWindowTitle(tr("Object Viewer Qt")); - - m_pluginManager = pluginManager; - m_settings = m_pluginManager->settings(); - m_coreImpl = new CoreImpl(this); - -#ifdef Q_WS_MAC - m_menuBar = new QMenuBar(0); -#else - m_menuBar = new QMenuBar(this); - setMenuBar(m_menuBar); -#endif - - m_menuManager = new MenuManager(m_menuBar, this); - - m_tabWidget = new QTabWidget(this); - m_tabWidget->setTabPosition(QTabWidget::South); - m_tabWidget->setMovable(false); - m_tabWidget->setDocumentMode(true); - setCentralWidget(m_tabWidget); - - m_contextManager = new ContextManager(this, m_tabWidget); - - setDockNestingEnabled(true); - m_originalPalette = QApplication::palette(); - m_undoGroup = new QUndoGroup(this); - - createDialogs(); - createActions(); - createMenus(); - createStatusBar(); - resize(1024, 768); -} - -MainWindow::~MainWindow() -{ - m_pluginManager->removeObject(m_coreImpl); - m_pluginManager->removeObject(m_menuManager); - - delete m_coreImpl; - m_coreImpl = 0; -} - -bool MainWindow::initialize(QString *errorString) -{ - Q_UNUSED(errorString); - m_pluginManager->addObject(m_coreImpl); - m_pluginManager->addObject(m_menuManager); - return true; -} - -void MainWindow::extensionsInitialized() -{ - readSettings(); - connect(m_contextManager, SIGNAL(currentContextChanged(Core::IContext *)), - this, SLOT(updateContext(Core::IContext *))); - if (m_contextManager->currentContext() != NULL) - updateContext(m_contextManager->currentContext()); - show(); -} - -MenuManager *MainWindow::menuManager() const -{ - return m_menuManager; -} - -ContextManager *MainWindow::contextManager() const -{ - return m_contextManager; -} - -QSettings *MainWindow::settings() const -{ - return m_settings; -} - -QUndoGroup *MainWindow::undoGroup() const -{ - return m_undoGroup; -} - -ExtensionSystem::IPluginManager *MainWindow::pluginManager() const -{ - return m_pluginManager; -} - -void MainWindow::addContextObject(IContext *context) -{ - QUndoStack *stack = context->undoStack(); - if (stack) - m_undoGroup->addStack(stack); -} - -void MainWindow::removeContextObject(IContext *context) -{ - QUndoStack *stack = context->undoStack(); - if (stack) - m_undoGroup->removeStack(stack); -} - -void MainWindow::open() -{ - m_contextManager->currentContext()->open(); -} - -void MainWindow::newFile() -{ - m_contextManager->currentContext()->newDocument(); -} - -void MainWindow::save() -{ - m_contextManager->currentContext()->save(); -} - -void MainWindow::saveAs() -{ - m_contextManager->currentContext()->saveAs(); -} - -void MainWindow::saveAll() -{ -} - -void MainWindow::closeDocument() -{ - m_contextManager->currentContext()->close(); -} - - -void MainWindow::cut() -{ -} - -void MainWindow::copy() -{ -} - -void MainWindow::paste() -{ -} - -void MainWindow::del() -{ -} - -void MainWindow::find() -{ -} - -void MainWindow::gotoPos() -{ -} - -void MainWindow::setFullScreen(bool enabled) -{ - if (bool(windowState() & Qt::WindowFullScreen) == enabled) - return; - if (enabled) - setWindowState(windowState() | Qt::WindowFullScreen); - else - setWindowState(windowState() & ~Qt::WindowFullScreen); -} - -bool MainWindow::showOptionsDialog(const QString &group, - const QString &page, - QWidget *parent) -{ - if (!parent) - parent = this; - SettingsDialog settingsDialog(m_pluginManager, group, page, parent); - settingsDialog.show(); - bool ok = settingsDialog.execDialog(); - if (ok) - Q_EMIT m_coreImpl->changeSettings(); - return ok; -} - -void MainWindow::about() -{ - QMessageBox::about(this, tr("About Object Viewer Qt"), - tr("

Object Viewer Qt

" - "

Ryzom Core team

Compiled on %1 %2").arg(__DATE__).arg(__TIME__)); -} - -void MainWindow::updateContext(Core::IContext *context) -{ - m_undoGroup->setActiveStack(context->undoStack()); -} - -void MainWindow::closeEvent(QCloseEvent *event) -{ - QList listeners = m_pluginManager->getObjects(); - Q_FOREACH(ICoreListener *listener, listeners) - { - if (!listener->closeMainWindow()) - { - event->ignore(); - return; - } - } - Q_EMIT m_coreImpl->closeMainWindow(); - - writeSettings(); - event->accept(); -} - -void MainWindow::createActions() -{ - m_newAction = new QAction(tr("&New"), this); - m_newAction->setIcon(QIcon(Constants::ICON_NEW)); - m_newAction->setShortcut(QKeySequence::New); - menuManager()->registerAction(m_newAction, Constants::NEW); - connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile())); - m_newAction->setEnabled(false); - - m_openAction = new QAction(tr("&Open..."), this); - m_openAction->setIcon(QIcon(Constants::ICON_OPEN)); - m_openAction->setShortcut(QKeySequence::Open); - m_openAction->setStatusTip(tr("Open an existing file")); - menuManager()->registerAction(m_openAction, Constants::OPEN); - connect(m_openAction, SIGNAL(triggered()), this, SLOT(open())); - - m_saveAction = new QAction(tr("&Save"), this); - m_saveAction->setIcon(QIcon(Constants::ICON_SAVE)); - m_saveAction->setShortcut(QKeySequence::Save); - menuManager()->registerAction(m_saveAction, Constants::SAVE); - connect(m_saveAction, SIGNAL(triggered()), this, SLOT(save())); - m_saveAction->setEnabled(false); - - m_saveAsAction = new QAction(tr("Save &As..."), this); - m_saveAsAction->setIcon(QIcon(Constants::ICON_SAVE_AS)); - m_saveAsAction->setShortcut(QKeySequence::SaveAs); - menuManager()->registerAction(m_saveAsAction, Constants::SAVE_AS); - connect(m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); - m_saveAsAction->setEnabled(false); - - m_saveAllAction = new QAction(tr("&Save A&ll"), this); - m_saveAllAction->setShortcut(QKeySequence::SelectAll); - menuManager()->registerAction(m_saveAllAction, Constants::SAVE_ALL); - connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll())); - m_saveAllAction->setEnabled(false); - - m_closeAction = new QAction(tr("Close"), this); - m_closeAction->setShortcut(QKeySequence::Close); - menuManager()->registerAction(m_closeAction, Constants::CLOSE); - connect(m_closeAction, SIGNAL(triggered()), this, SLOT(closeDocument())); - m_closeAction->setEnabled(false); - - m_exitAction = new QAction(tr("E&xit"), this); - m_exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); - m_exitAction->setStatusTip(tr("Exit the application")); - menuManager()->registerAction(m_exitAction, Constants::EXIT); - connect(m_exitAction, SIGNAL(triggered()), this, SLOT(close())); - - m_cutAction = new QAction(tr("Cu&t"), this); - m_cutAction->setShortcut(QKeySequence::Cut); - menuManager()->registerAction(m_cutAction, Constants::CUT); - connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cut())); - m_cutAction->setEnabled(false); - - m_copyAction = new QAction(tr("&Copy"), this); - m_copyAction->setShortcut(QKeySequence::Copy); - menuManager()->registerAction(m_copyAction, Constants::COPY); - connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copy())); - m_copyAction->setEnabled(false); - - m_pasteAction = new QAction(tr("&Paste"), this); - m_pasteAction->setShortcut(QKeySequence::Paste); - menuManager()->registerAction(m_pasteAction, Constants::PASTE); - connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); - m_pasteAction->setEnabled(false); - - m_delAction = new QAction(tr("&Delete"), this); - m_delAction->setShortcut(QKeySequence::Delete); - menuManager()->registerAction(m_delAction, Constants::DEL); - connect(m_delAction, SIGNAL(triggered()), this, SLOT(del())); - m_delAction->setEnabled(false); - - m_selectAllAction = new QAction(tr("Select &All"), this); - m_selectAllAction->setShortcut(QKeySequence::SelectAll); - menuManager()->registerAction(m_selectAllAction, Constants::SELECT_ALL); - connect(m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll())); - m_selectAllAction->setEnabled(false); - - m_findAction = new QAction(tr("&Find"), this); - m_findAction->setShortcut(QKeySequence::Find); - menuManager()->registerAction(m_findAction, Constants::FIND); - connect(m_findAction, SIGNAL(triggered()), this, SLOT(find())); - m_findAction->setEnabled(false); - - m_gotoAction = new QAction(tr("&Go To.."), this); - m_gotoAction->setShortcut(QKeySequence(tr("Ctrl+G"))); - menuManager()->registerAction(m_gotoAction, Constants::GOTO_POS); - connect(m_gotoAction, SIGNAL(triggered()), this, SLOT(gotoPos())); - m_gotoAction->setEnabled(false); - - m_fullscreenAction = new QAction(tr("Fullscreen"), this); - m_fullscreenAction->setCheckable(true); - m_fullscreenAction->setShortcut(QKeySequence(tr("Ctrl+Shift+F11"))); - menuManager()->registerAction(m_fullscreenAction, Constants::TOGGLE_FULLSCREEN); - connect(m_fullscreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool))); - - m_settingsAction = new QAction(tr("&Settings"), this); - m_settingsAction->setIcon(QIcon(":/images/preferences.png")); - m_settingsAction->setShortcut(QKeySequence::Preferences); - m_settingsAction->setStatusTip(tr("Open the settings dialog")); - menuManager()->registerAction(m_settingsAction, Constants::SETTINGS); - connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog())); - - m_aboutAction = new QAction(tr("&About"), this); - m_aboutAction->setStatusTip(tr("Show the application's About box")); - menuManager()->registerAction(m_aboutAction, Constants::ABOUT); - connect(m_aboutAction, SIGNAL(triggered()), this, SLOT(about())); - - m_aboutQtAction = new QAction(tr("About &Qt"), this); - m_aboutQtAction->setStatusTip(tr("Show the Qt library's About box")); - menuManager()->registerAction(m_aboutQtAction, Constants::ABOUT_QT); - connect(m_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); - - m_pluginViewAction = new QAction(tr("About &Plugins"), this); - m_pluginViewAction->setStatusTip(tr("Show the plugin view dialog")); - menuManager()->registerAction(m_pluginViewAction, Constants::ABOUT_PLUGINS); - connect(m_pluginViewAction, SIGNAL(triggered()), m_pluginView, SLOT(show())); - -#ifdef Q_WS_MAC - m_exitAction->setMenuRole(QAction::QuitRole); - m_settingsAction->setMenuRole(QAction::PreferencesRole); - m_aboutAction->setMenuRole(QAction::AboutRole); - m_aboutQtAction->setMenuRole(QAction::AboutQtRole); - m_pluginViewAction->setMenuRole(QAction::ApplicationSpecificRole); -#endif -} - -void MainWindow::createMenus() -{ - m_fileMenu = m_menuBar->addMenu(tr("&File")); - menuManager()->registerMenu(m_fileMenu, Constants::M_FILE); - m_fileMenu->addAction(m_newAction); - m_fileMenu->addAction(m_openAction); - m_fileMenu->addSeparator(); - m_fileMenu->addAction(m_saveAction); - m_fileMenu->addAction(m_saveAsAction); - m_fileMenu->addAction(m_saveAllAction); - m_fileMenu->addAction(m_closeAction); - m_fileMenu->addSeparator(); - - m_recentFilesMenu = m_fileMenu->addMenu(tr("Recent &Files")); - m_recentFilesMenu->setEnabled(false); - menuManager()->registerMenu(m_recentFilesMenu, Constants::M_FILE_RECENTFILES); - - m_fileMenu->addSeparator(); - m_fileMenu->addAction(m_exitAction); - - m_editMenu = m_menuBar->addMenu(tr("&Edit")); - QAction *undoAction = m_undoGroup->createUndoAction(this); - menuManager()->registerAction(undoAction, Constants::UNDO); - undoAction->setIcon(QIcon(Constants::ICON_UNDO)); - undoAction->setShortcut(QKeySequence::Undo); - QAction *redoAction = m_undoGroup->createRedoAction(this); - menuManager()->registerAction(redoAction, Constants::REDO); - redoAction->setIcon(QIcon(Constants::ICON_REDO)); - redoAction->setShortcut(QKeySequence::Redo); - m_editMenu->addAction(undoAction); - m_editMenu->addAction(redoAction); - - m_editMenu->addSeparator(); - m_editMenu->addAction(m_cutAction); - m_editMenu->addAction(m_copyAction); - m_editMenu->addAction(m_pasteAction); - m_editMenu->addAction(m_delAction); - m_editMenu->addSeparator(); - m_editMenu->addAction(m_selectAllAction); - m_editMenu->addSeparator(); - m_editMenu->addAction(m_findAction); - m_editMenu->addAction(m_gotoAction); - menuManager()->registerMenu(m_editMenu, Constants::M_EDIT); - - m_viewMenu = m_menuBar->addMenu(tr("&View")); - m_viewMenu->addAction(m_fullscreenAction); - m_viewMenu->addAction(m_dockWidget->toggleViewAction()); - menuManager()->registerMenu(m_viewMenu, Constants::M_VIEW); - - m_toolsMenu = m_menuBar->addMenu(tr("&Tools")); - menuManager()->registerMenu(m_toolsMenu, Constants::M_TOOLS); - - m_sheetMenu = m_toolsMenu->addMenu(tr("&Sheet")); - menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); - -// m_toolsMenu->addSeparator(); - - m_toolsMenu->addAction(m_settingsAction); - - m_menuBar->addSeparator(); - - m_helpMenu = m_menuBar->addMenu(tr("&Help")); - menuManager()->registerMenu(m_helpMenu, Constants::M_HELP); - m_helpMenu->addAction(m_aboutAction); - m_helpMenu->addAction(m_aboutQtAction); - m_helpMenu->addAction(m_pluginViewAction); -} - -void MainWindow::createStatusBar() -{ - statusBar()->showMessage(tr("StatusReady")); -} - -void MainWindow::createDialogs() -{ - m_pluginView = new PluginView(m_pluginManager, this); - - // Create undo/redo command list - m_dockWidget = new QDockWidget("Command List", this); - m_dockWidget->setObjectName(QString::fromUtf8("UndoRedoCommandDockWidget")); - QUndoView *undoView = new QUndoView(m_undoGroup, m_dockWidget); - m_dockWidget->setWidget(undoView); - addDockWidget(Qt::RightDockWidgetArea, m_dockWidget); -} - -void MainWindow::readSettings() -{ - m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - restoreState(m_settings->value(Constants::MAIN_WINDOW_STATE).toByteArray()); - restoreGeometry(m_settings->value(Constants::MAIN_WINDOW_GEOMETRY).toByteArray()); - m_settings->endGroup(); -} - -void MainWindow::writeSettings() -{ - m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - m_settings->setValue(Constants::MAIN_WINDOW_STATE, saveState()); - m_settings->setValue(Constants::MAIN_WINDOW_GEOMETRY, saveGeometry()); - m_settings->endGroup(); -} - -} /* namespace Core */ - -/* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h deleted file mode 100644 index d258a5eba..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h +++ /dev/null @@ -1,147 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef MAIN_WINDOW_H -#define MAIN_WINDOW_H - -// Project includes -#include "../../extension_system/iplugin_manager.h" -#include "plugin_view_dialog.h" - -// STL includes - -// Qt includes -#include -#include -#include - -namespace Core -{ -class CSettingsDialog; -class CorePlugin; -class IContext; -class MenuManager; -class ContextManager; -class CoreImpl; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); - ~MainWindow(); - - bool initialize(QString *errorString); - void extensionsInitialized(); - - MenuManager *menuManager() const; - ContextManager *contextManager() const; - QSettings *settings() const; - QUndoGroup *undoGroup() const; - - ExtensionSystem::IPluginManager *pluginManager() const; - - void addContextObject(IContext *context); - void removeContextObject(IContext *context); - -public Q_SLOTS: - bool showOptionsDialog(const QString &group = QString(), - const QString &page = QString(), - QWidget *parent = 0); - void updateContext(Core::IContext *context); - -private Q_SLOTS: - void open(); - void newFile(); - void save(); - void saveAs(); - void saveAll(); - void closeDocument(); - void cut(); - void copy(); - void paste(); - void del(); - void find(); - void gotoPos(); - void setFullScreen(bool enabled); - void about(); - -protected: - virtual void closeEvent(QCloseEvent *event); - -private: - void createActions(); - void createMenus(); - void createStatusBar(); - void createDialogs(); - - void readSettings(); - void writeSettings(); - - ExtensionSystem::IPluginManager *m_pluginManager; - PluginView *m_pluginView; - MenuManager *m_menuManager; - ContextManager *m_contextManager; - CoreImpl *m_coreImpl; - - QPalette m_originalPalette; - QString m_lastDir; - - QDockWidget *m_dockWidget; - QUndoGroup *m_undoGroup; - QSettings *m_settings; - - QTimer *m_mainTimer; - QTimer *m_statusBarTimer; - - QTabWidget *m_tabWidget; - - QMenu *m_fileMenu; - QMenu *m_recentFilesMenu; - QMenu *m_editMenu; - QMenu *m_viewMenu; - QMenu *m_toolsMenu; - QMenu *m_helpMenu; - QMenuBar *m_menuBar; - QMenu *m_sheetMenu; - - QAction *m_newAction; - QAction *m_openAction; - QAction *m_saveAction; - QAction *m_saveAsAction; - QAction *m_saveAllAction; - QAction *m_closeAction; - QAction *m_exitAction; - QAction *m_cutAction; - QAction *m_copyAction; - QAction *m_pasteAction; - QAction *m_delAction; - QAction *m_selectAllAction; - QAction *m_findAction; - QAction *m_gotoAction; - QAction *m_fullscreenAction; - QAction *m_settingsAction; - QAction *m_pluginViewAction; - QAction *m_aboutAction; - QAction *m_aboutQtAction; - -};/* class MainWindow */ - -} /* namespace Core */ - -#endif // MAIN_WINDOW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp deleted file mode 100644 index 3e6272f0a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "menu_manager.h" - -// NeL includes -#include - -namespace Core -{ -struct MenuManagerPrivate -{ - MenuManagerPrivate(): m_menuBar(0) {} - QMenuBar *m_menuBar; - typedef QHash IdMenuMap; - IdMenuMap m_menuMap; - typedef QHash IdActionMap; - IdActionMap m_actionMap; -}; - -MenuManager::MenuManager(QMenuBar *menuBar, QObject *parent) - : QObject(parent), - d(new MenuManagerPrivate()) -{ - d->m_menuBar = menuBar; -} - -MenuManager::~MenuManager() -{ - d->m_menuMap.clear(); - delete d; -} - -void MenuManager::registerMenu(QMenu *menu, const QString &id) -{ - menu->setObjectName(id); - d->m_menuMap.insert(id, menu); -} - -void MenuManager::registerAction(QAction *action, const QString &id) -{ - action->setObjectName(id); - d->m_actionMap.insert(id, action); -} - -QMenu *MenuManager::menu(const QString &id) const -{ - QMenu *result = 0; - if (!d->m_menuMap.contains(id)) - nlwarning("QMenu %s not found", id.toUtf8().constData()); - else - result = d->m_menuMap.value(id); - return result; -} - -QAction *MenuManager::action(const QString &id) const -{ - QAction *result = 0; - if (!d->m_actionMap.contains(id)) - nlwarning("QAction %s not found", id.toUtf8().constData()); - else - result = d->m_actionMap.value(id); - return result; -} - -void MenuManager::unregisterMenu(const QString &id) -{ - d->m_menuMap.remove(id); -} - -void MenuManager::unregisterAction(const QString &id) -{ - d->m_actionMap.remove(id); -} - -QMenuBar *MenuManager::menuBar() const -{ - return d->m_menuBar; -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h deleted file mode 100644 index fd6af8f3a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h +++ /dev/null @@ -1,67 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef MENU_MANAGER_H -#define MENU_MANAGER_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include -#include -#include -#include -#include -#include - -namespace Core -{ -struct MenuManagerPrivate; - -/* -@interface MenuManager -@brief The MenuManager provide the interface for registration of menus and menu item. -@details The MenuManager provides centralized access to menus and menu items. -All menus and menu items should be registered in the MenuManager. -*/ -class CORE_EXPORT MenuManager: public QObject -{ - Q_OBJECT - -public: - MenuManager(QMenuBar *menuBar, QObject *parent = 0); - virtual ~MenuManager(); - - void registerMenu(QMenu *menu, const QString &id); - void registerAction(QAction *action, const QString &id); - - QMenu *menu(const QString &id) const; - QAction *action(const QString &id) const; - - void unregisterMenu(const QString &id); - void unregisterAction(const QString &id); - - QMenuBar *menuBar() const; -private: - - MenuManagerPrivate *d; -}; - -} // namespace Core - -#endif // MENU_MANAGER_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml deleted file mode 100644 index 2f5d6e9a8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml +++ /dev/null @@ -1,7 +0,0 @@ - - ovqt_plugin_core - Core - 0.8 - Ryzom Core - Core plugin. - \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp deleted file mode 100644 index 175902d39..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "plugin_view_dialog.h" -#include "core_constants.h" - -#include "nel/misc/debug.h" - -// Qt includes -#include -#include -#include -#include - -// Project includes -#include "../../extension_system/iplugin_spec.h" -#include "../../extension_system/iplugin_manager.h" - -namespace Core -{ - -PluginView::PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) - : QDialog(parent), - m_checkStateColumn(0) -{ - m_ui.setupUi(this); - m_pluginManager = pluginManager; - - connect(m_pluginManager, SIGNAL(pluginsChanged()), this, SLOT(updateList())); - connect(this, SIGNAL(accepted()), this, SLOT(updateSettings())); - - // WhiteList is list of plugins which can not disable. - m_whiteList << Constants::OVQT_CORE_PLUGIN; - updateList(); -} - -PluginView::~PluginView() -{ -} - -void PluginView::updateList() -{ - static QIcon okIcon = QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton); - static QIcon errorIcon = QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton); - static QIcon notLoadedIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton); - - m_specToItem.clear(); - - QList items; - Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) - { - QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() - << spec->name() - << QString("%1").arg(spec->version()) - << spec->vendor() - << QDir::toNativeSeparators(spec->filePath())); - - bool ok = !spec->hasError(); - QIcon icon = ok ? okIcon : errorIcon; - if (ok && (spec->state() != ExtensionSystem::State::Running)) - icon = notLoadedIcon; - - item->setIcon(m_checkStateColumn, icon); - - if (!m_whiteList.contains(spec->name())) - item->setCheckState(m_checkStateColumn, spec->isEnabled() ? Qt::Checked : Qt::Unchecked); - - items.append(item); - m_specToItem.insert(spec, item); - } - - m_ui.pluginTreeWidget->clear(); - if (!items.isEmpty()) - m_ui.pluginTreeWidget->addTopLevelItems(items); - - m_ui.pluginTreeWidget->resizeColumnToContents(m_checkStateColumn); -} - -void PluginView::updateSettings() -{ - Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) - { - if (m_specToItem.contains(spec) && (!m_whiteList.contains(spec->name()))) - { - QTreeWidgetItem *item = m_specToItem.value(spec); - if (item->checkState(m_checkStateColumn) == Qt::Checked) - spec->setEnabled(true); - else - spec->setEnabled(false); - } - } -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h deleted file mode 100644 index aae16749d..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h +++ /dev/null @@ -1,58 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PLUGIN_VIEW_H -#define PLUGIN_VIEW_H - -#include "ui_plugin_view_dialog.h" - -#include -#include - -namespace ExtensionSystem -{ -class IPluginManager; -class IPluginSpec; -} - -namespace Core -{ - -class PluginView: public QDialog -{ - Q_OBJECT - -public: - PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); - ~PluginView(); - -private Q_SLOTS: - void updateList(); - void updateSettings(); - -private: - - const int m_checkStateColumn; - QMap m_specToItem; - QStringList m_whiteList; - ExtensionSystem::IPluginManager *m_pluginManager; - Ui::PluginView m_ui; -}; /* class PluginView */ - -} /* namespace Core */ - -#endif // PLUGIN_VIEW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui deleted file mode 100644 index 9d7d395be..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui +++ /dev/null @@ -1,135 +0,0 @@ - - - PluginView - - - - 0 - 0 - 756 - 296 - - - - About plugins - - - true - - - - - - true - - - 0 - - - false - - - true - - - false - - - true - - - - Name - - - - - Version - - - - - Vendor - - - - - Location - - - - - - - - false - - - Details - - - - - - - false - - - Error details - - - - - - - Qt::Horizontal - - - - 427 - 20 - - - - - - - - Close - - - - - - - false - - - All objects list - - - - - - - - - - - closePushButton - clicked() - PluginView - accept() - - - 620 - 232 - - - 507 - 226 - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp deleted file mode 100644 index 115203ded..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#include "qtwin.h" -#include -#include -#include -#include -#include - -#ifdef Q_WS_WIN - -#include - -// Blur behind data structures -#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified -#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified -#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified -#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message - -typedef struct _DWM_BLURBEHIND -{ - DWORD dwFlags; - BOOL fEnable; - HRGN hRgnBlur; - BOOL fTransitionOnMaximized; -} DWM_BLURBEHIND, *PDWM_BLURBEHIND; - -typedef struct _MARGINS -{ - int cxLeftWidth; - int cxRightWidth; - int cyTopHeight; - int cyBottomHeight; -} MARGINS, *PMARGINS; - -typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL *pfEnabled); -typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset); -typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind); -typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); - -static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; -static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; -static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; -static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; - - -/* - * Internal helper class that notifies windows if the - * DWM compositing state changes and updates the widget - * flags correspondingly. - */ -class WindowNotifier : public QWidget -{ -public: - WindowNotifier() - { - winId(); - } - void addWidget(QWidget *widget) - { - widgets.append(widget); - } - void removeWidget(QWidget *widget) - { - widgets.removeAll(widget); - } - bool winEvent(MSG *message, long *result); - -private: - QWidgetList widgets; -}; - -static bool resolveLibs() -{ - if (!pDwmIsCompositionEnabled) - { - QLibrary dwmLib(QString::fromAscii("dwmapi")); - pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); - pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); - pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); - pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); - } - return pDwmIsCompositionEnabled != 0; -} - -#endif - -/*! - * Chekcs and returns true if Windows DWM composition - * is currently enabled on the system. - * - * To get live notification on the availability of - * this feature, you will currently have to - * reimplement winEvent() on your widget and listen - * for the WM_DWMCOMPOSITIONCHANGED event to occur. - * - */ -bool QtWin::isCompositionEnabled() -{ -#ifdef Q_WS_WIN - if (resolveLibs()) - { - HRESULT hr = S_OK; - BOOL isEnabled = false; - hr = pDwmIsCompositionEnabled(&isEnabled); - if (SUCCEEDED(hr)) - return isEnabled; - } -#endif - return false; -} - -/*! - * Enables Blur behind on a Widget. - * - * \a enable tells if the blur should be enabled or not - */ -bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable) -{ - Q_ASSERT(widget); - bool result = false; -#ifdef Q_WS_WIN - if (resolveLibs()) - { - DWM_BLURBEHIND bb = {0}; - HRESULT hr = S_OK; - bb.fEnable = enable; - bb.dwFlags = DWM_BB_ENABLE; - bb.hRgnBlur = NULL; - widget->setAttribute(Qt::WA_TranslucentBackground, enable); - widget->setAttribute(Qt::WA_NoSystemBackground, enable); - hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); - if (SUCCEEDED(hr)) - { - result = true; - windowNotifier()->addWidget(widget); - } - } -#endif - return result; -} - -/*! - * ExtendFrameIntoClientArea. - * - * This controls the rendering of the frame inside the window. - * Note that passing margins of -1 (the default value) will completely - * remove the frame from the window. - * - * \note you should not call enableBlurBehindWindow before calling - * this functions - * - * \a enable tells if the blur should be enabled or not - */ -bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) -{ - - Q_ASSERT(widget); - Q_UNUSED(left); - Q_UNUSED(top); - Q_UNUSED(right); - Q_UNUSED(bottom); - - bool result = false; -#ifdef Q_WS_WIN - if (resolveLibs()) - { - QLibrary dwmLib(QString::fromAscii("dwmapi")); - HRESULT hr = S_OK; - MARGINS m = {left, top, right, bottom}; - hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); - if (SUCCEEDED(hr)) - { - result = true; - windowNotifier()->addWidget(widget); - } - widget->setAttribute(Qt::WA_TranslucentBackground, result); - } -#endif - return result; -} - -/*! - * Returns the current colorizationColor for the window. - * - * \a enable tells if the blur should be enabled or not - */ -QColor QtWin::colorizatinColor() -{ - QColor resultColor = QApplication::palette().window().color(); - -#ifdef Q_WS_WIN - if (resolveLibs()) - { - DWORD color = 0; - BOOL opaque = FALSE; - QLibrary dwmLib(QString::fromAscii("dwmapi")); - HRESULT hr = S_OK; - hr = pDwmGetColorizationColor(&color, &opaque); - if (SUCCEEDED(hr)) - resultColor = QColor(color); - } -#endif - return resultColor; -} - -#ifdef Q_WS_WIN -WindowNotifier *QtWin::windowNotifier() -{ - static WindowNotifier *windowNotifierInstance = 0; - if (!windowNotifierInstance) - windowNotifierInstance = new WindowNotifier; - return windowNotifierInstance; -} - - -/* Notify all enabled windows that the DWM state changed */ -bool WindowNotifier::winEvent(MSG *message, long *result) -{ - if (message && message->message == WM_DWMCOMPOSITIONCHANGED) - { - bool compositionEnabled = QtWin::isCompositionEnabled(); - Q_FOREACH(QWidget * widget, widgets) - { - if (widget) - { - widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); - } - widget->update(); - } - } - return QWidget::winEvent(message, result); -} -#endif diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h deleted file mode 100644 index 5692a34fb..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#ifndef QTWIN_H -#define QTWIN_H - -#include -#include -/** - * This is a helper class for using the Desktop Window Manager - * functionality on Windows 7 and Windows Vista. On other platforms - * these functions will simply not do anything. - */ - -class WindowNotifier; - -class QtWin -{ -public: - static bool enableBlurBehindWindow(QWidget *widget, bool enable = true); - static bool extendFrameIntoClientArea(QWidget *widget, - int left = -1, int top = -1, - int right = -1, int bottom = -1); - static bool isCompositionEnabled(); - static QColor colorizatinColor(); - -private: - static WindowNotifier *windowNotifier(); -}; - -#endif // QTWIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp deleted file mode 100644 index e76d6c796..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "search_paths_settings_page.h" -#include "core_constants.h" -#include "icore.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace Core -{ - -QString lastDir = "."; - -SearchPathsSettingsPage::SearchPathsSettingsPage(bool recurse, QObject *parent) - : IOptionsPage(parent), - m_recurse(recurse), - m_page(0) -{ -} - -SearchPathsSettingsPage::~SearchPathsSettingsPage() -{ -} - -QString SearchPathsSettingsPage::id() const -{ - if (m_recurse) - return QLatin1String("search_recurse_paths"); - else - return QLatin1String("search_paths"); -} - -QString SearchPathsSettingsPage::trName() const -{ - if (m_recurse) - return tr("Search Recurse Paths"); - else - return tr("Search Paths"); -} - -QString SearchPathsSettingsPage::category() const -{ - return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); -} - -QString SearchPathsSettingsPage::trCategory() const -{ - return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); -} - -QIcon SearchPathsSettingsPage::categoryIcon() const -{ - return QIcon(); -} - -QWidget *SearchPathsSettingsPage::createPage(QWidget *parent) -{ - m_page = new QWidget(parent); - m_ui.setupUi(m_page); - - readSettings(); - checkEnabledButton(); - connect(m_ui.addToolButton, SIGNAL(clicked()), this, SLOT(addPath())); - connect(m_ui.removeToolButton, SIGNAL(clicked()), this, SLOT(delPath())); - connect(m_ui.upToolButton, SIGNAL(clicked()), this, SLOT(upPath())); - connect(m_ui.downToolButton, SIGNAL(clicked()), this, SLOT(downPath())); - connect(m_ui.resetToolButton, SIGNAL(clicked()), m_ui.pathsListWidget, SLOT(clear())); - return m_page; -} - -void SearchPathsSettingsPage::apply() -{ - writeSettings(); - applySearchPaths(); -} - -void SearchPathsSettingsPage::finish() -{ - delete m_page; - m_page = 0; -} - -void SearchPathsSettingsPage::applySearchPaths() -{ - QStringList paths, remapExt; - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - if (m_recurse) - paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); - else - paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); - - remapExt = settings->value(Core::Constants::REMAP_EXTENSIONS).toStringList(); - settings->endGroup(); - - for (int i = 1; i < remapExt.size(); i += 2) - NLMISC::CPath::remapExtension(remapExt.at(i - 1).toUtf8().constData(), remapExt.at(i).toUtf8().constData(), true); - - Q_FOREACH(QString path, paths) - { - NLMISC::CPath::addSearchPath(path.toUtf8().constData(), m_recurse, false); - } -} - -void SearchPathsSettingsPage::addPath() -{ - QString newPath = QFileDialog::getExistingDirectory(m_page, "", lastDir); - if (!newPath.isEmpty()) - { - QListWidgetItem *newItem = new QListWidgetItem; - newItem->setText(newPath); - newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - m_ui.pathsListWidget->addItem(newItem); - lastDir = newPath; - } - - checkEnabledButton(); -} - -void SearchPathsSettingsPage::delPath() -{ - QListWidgetItem *removeItem = m_ui.pathsListWidget->takeItem(m_ui.pathsListWidget->currentRow()); - if (!removeItem) - delete removeItem; - - checkEnabledButton(); -} - -void SearchPathsSettingsPage::upPath() -{ - int currentRow = m_ui.pathsListWidget->currentRow(); - if (!(currentRow == 0)) - { - QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); - m_ui.pathsListWidget->insertItem(--currentRow, item); - m_ui.pathsListWidget->setCurrentRow(currentRow); - } -} - -void SearchPathsSettingsPage::downPath() -{ - int currentRow = m_ui.pathsListWidget->currentRow(); - if (!(currentRow == m_ui.pathsListWidget->count()-1)) - { - QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); - m_ui.pathsListWidget->insertItem(++currentRow, item); - m_ui.pathsListWidget->setCurrentRow(currentRow); - } -} - -void SearchPathsSettingsPage::readSettings() -{ - QStringList paths; - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - if (m_recurse) - paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); - else - paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); - settings->endGroup(); - Q_FOREACH(QString path, paths) - { - QListWidgetItem *newItem = new QListWidgetItem; - newItem->setText(path); - newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - m_ui.pathsListWidget->addItem(newItem); - } -} - -void SearchPathsSettingsPage::writeSettings() -{ - QStringList paths; - for (int i = 0; i < m_ui.pathsListWidget->count(); ++i) - paths << m_ui.pathsListWidget->item(i)->text(); - - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - if (m_recurse) - settings->setValue(Core::Constants::RECURSIVE_SEARCH_PATHS, paths); - else - settings->setValue(Core::Constants::SEARCH_PATHS, paths); - settings->endGroup(); - settings->sync(); -} - -void SearchPathsSettingsPage::checkEnabledButton() -{ - bool bEnabled = true; - if (m_ui.pathsListWidget->count() == 0) - bEnabled = false; - - m_ui.removeToolButton->setEnabled(bEnabled); - m_ui.upToolButton->setEnabled(bEnabled); - m_ui.downToolButton->setEnabled(bEnabled); -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h deleted file mode 100644 index c45b29571..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h +++ /dev/null @@ -1,74 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef SEARCH_PATHS_SETTINGS_PAGE_H -#define SEARCH_PATHS_SETTINGS_PAGE_H - -#include - -#include "ioptions_page.h" - -#include "ui_search_paths_settings_page.h" - -class QWidget; - -namespace Core -{ -/** -@class SearchPathsSettingsPage -*/ -class SearchPathsSettingsPage : public Core::IOptionsPage -{ - Q_OBJECT - -public: - explicit SearchPathsSettingsPage(bool recurse, QObject *parent = 0); - ~SearchPathsSettingsPage(); - - QString id() const; - QString trName() const; - QString category() const; - QString trCategory() const; - QIcon categoryIcon() const; - QWidget *createPage(QWidget *parent); - - void apply(); - void finish(); - - // Set of the search paths(not recursive) and the remap extensions (loading from settings file) - void applySearchPaths(); - -private Q_SLOTS: - void addPath(); - void delPath(); - void upPath(); - void downPath(); - -private: - void readSettings(); - void writeSettings(); - void checkEnabledButton(); - - bool m_recurse; - QWidget *m_page; - Ui::SearchPathsSettingsPage m_ui; -}; - -} // namespace Core - -#endif // SEARCH_PATHS_SETTINGS_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui deleted file mode 100644 index cf47314b8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui +++ /dev/null @@ -1,198 +0,0 @@ - - - SearchPathsSettingsPage - - - - 0 - 0 - 431 - 285 - - - - Form - - - - 6 - - - 3 - - - - - Search paths - - - - - - - Qt::Horizontal - - - - 228 - 20 - - - - - - - - 3 - - - - - - 0 - 0 - - - - Add - - - - - - - :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png - - - - 20 - 20 - - - - true - - - - - - - - 0 - 0 - - - - Delete - - - - - - - :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png - - - - 20 - 20 - - - - true - - - - - - - - 0 - 0 - - - - Up - - - - - - - :/core/icons/ic_nel_up_item.png:/core/icons/ic_nel_up_item.png - - - - 20 - 20 - - - - true - - - - - - - - 0 - 0 - - - - Down - - - - - - - :/core/icons/ic_nel_down_item.png:/core/icons/ic_nel_down_item.png - - - - 20 - 20 - - - - true - - - - - - - Reset - - - - - - - :/core/icons/ic_nel_reset_all.png:/core/icons/ic_nel_reset_all.png - - - - 20 - 20 - - - - true - - - - - - - - - - - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp deleted file mode 100644 index 4b7bbac3a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "settings_dialog.h" -#include "ioptions_page.h" - -// Qt includes -#include -#include - -struct PageData -{ - int index; - QString category; - QString id; -}; - -Q_DECLARE_METATYPE(PageData); - -namespace Core -{ -SettingsDialog::SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, - const QString &categoryId, - const QString &pageId, - QWidget *parent) - : QDialog(parent), - m_applied(false) -{ - m_ui.setupUi(this); - - m_plugMan = pluginManager; - - QString initialCategory = categoryId; - QString initialPage = pageId; - - m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - - connect(m_ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); - - m_ui.splitter->setCollapsible(1, false); - m_ui.pageTree->header()->setVisible(false); - - connect(m_ui.pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(pageSelected())); - - QMap categories; - - QList pages = m_plugMan->getObjects(); - - int index = 0; - Q_FOREACH(IOptionsPage *page, pages) - { - PageData pageData; - pageData.index = index; - pageData.category = page->category(); - pageData.id = page->id(); - - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setText(0, page->trName()); - item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - - QStringList categoriesId = page->category().split(QLatin1Char('|')); - QStringList trCategories = page->trCategory().split(QLatin1Char('|')); - QString currentCategory = categoriesId.at(0); - - QTreeWidgetItem *treeitem; - if (!categories.contains(currentCategory)) - { - treeitem = new QTreeWidgetItem(m_ui.pageTree); - treeitem->setText(0, trCategories.at(0)); - treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - categories.insert(currentCategory, treeitem); - } - - int catCount = 1; - while (catCount < categoriesId.count()) - { - if (!categories.contains(currentCategory + QLatin1Char('|') + categoriesId.at(catCount))) - { - treeitem = new QTreeWidgetItem(categories.value(currentCategory)); - currentCategory += QLatin1Char('|') + categoriesId.at(catCount); - treeitem->setText(0, trCategories.at(catCount)); - treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - categories.insert(currentCategory, treeitem); - } - else - { - currentCategory += QLatin1Char('|') + categoriesId.at(catCount); - } - ++catCount; - } - - categories.value(currentCategory)->addChild(item); - - m_pages.append(page); - m_ui.stackedPages->addWidget(page->createPage(m_ui.stackedPages)); - - if (page->id() == initialPage && currentCategory == initialCategory) - { - m_ui.stackedPages->setCurrentIndex(m_ui.stackedPages->count()); - m_ui.pageTree->setCurrentItem(item); - } - - index++; - } - - QList sizes; - sizes << 150 << 300; - m_ui.splitter->setSizes(sizes); - - m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.pageTree), 0); - m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.layoutWidget), 1); -} - -SettingsDialog::~SettingsDialog() -{ -} - -void SettingsDialog::pageSelected() -{ - QTreeWidgetItem *item = m_ui.pageTree->currentItem(); - PageData data = item->data(0, Qt::UserRole).value(); - int index = data.index; - m_currentCategory = data.category; - m_currentPage = data.id; - m_ui.stackedPages->setCurrentIndex(index); -} - -void SettingsDialog::accept() -{ - m_applied = true; - Q_FOREACH(IOptionsPage *page, m_pages) - { - page->apply(); - page->finish(); - } - done(QDialog::Accepted); -} - -void SettingsDialog::reject() -{ - Q_FOREACH(IOptionsPage *page, m_pages) - page->finish(); - done(QDialog::Rejected); -} - -void SettingsDialog::apply() -{ - Q_FOREACH(IOptionsPage *page, m_pages) - page->apply(); - m_applied = true; -} - -bool SettingsDialog::execDialog() -{ - m_applied = false; - exec(); - return m_applied; -} - -void SettingsDialog::done(int val) -{ - QDialog::done(val); -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h deleted file mode 100644 index 9e1c86444..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h +++ /dev/null @@ -1,75 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SETTINGS_DIALOG_H -#define SETTINGS_DIALOG_H - -#include "ui_settings_dialog.h" - -// Qt includes -#include - -// Project includes -#include "../../extension_system/iplugin_manager.h" - -namespace Core -{ -class IOptionsPage; - -/** -@class CSettingsDialog -@brief Settings dialog -*/ -class SettingsDialog: public QDialog -{ - Q_OBJECT - -public: - SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, - const QString &initialCategory = QString(), - const QString &initialPage = QString(), - QWidget *parent = 0); - - ~SettingsDialog(); - - /// Run the dialog and return true if 'Ok' was choosen or 'Apply' was invoked at least once - bool execDialog(); - -public Q_SLOTS: - void done(int); - -private Q_SLOTS: - void pageSelected(); - void accept(); - void reject(); - void apply(); - -private: - QList m_pages; - bool m_applied; - QString m_currentCategory; - QString m_currentPage; - - ExtensionSystem::IPluginManager *m_plugMan; - - Ui::SettingsDialog m_ui; -}; /* class CSettingsDialog */ - -} /* namespace Core */ - -#endif // SETTINGS_DIALOG_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui deleted file mode 100644 index 8e9780c9a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui +++ /dev/null @@ -1,126 +0,0 @@ - - - SettingsDialog - - - - 0 - 0 - 697 - 476 - - - - Settings - - - - :/core/images/preferences.png:/core/images/preferences.png - - - - 6 - - - 9 - - - - - Qt::Horizontal - - - - - 0 - 0 - - - - 1 - - - - 0 - - - - - - - 6 - - - 0 - - - - - - 350 - 250 - - - - - - - - Qt::Horizontal - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - SettingsDialog - accept() - - - 297 - 361 - - - 297 - 193 - - - - - buttonBox - rejected() - SettingsDialog - reject() - - - 297 - 361 - - - 297 - 193 - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_generic_settings.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_generic_settings.png deleted file mode 100644 index 799bacb284c7e3e1e41cbaeb538ffe32e21a4b3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5633 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 t_zc8nAU*@}8Hmq7dN2bPDNB8 zb~7$DE;i7Ety%y87OzP}K~#8N?OO+QRM)kgKBE~)qY6TRdhZoAkc5N~>b-X%Bw+zU zbX))%1EvdALuu^q>D;*|ew5@$JaY{x%|Q@}Agf1fKoWsoJ1 zOj*fVnYH%1@4b2R-reV%d&<3cWU_yM9-IUsWirJgnaq$Zli33{@iLjtLnf0yxE?&9 zH-VTOMC}*LWF^^hS!cdR_00l}`qxDo^c5p~)HljC>g%OA#A)T(c1 zD`Y3rWU@^uGFcJ?G$TnSQ$3(A-@Dg?JTL))`Hf~u%bcPTT5!QHc*Sv@YiMLy4SMgvYik}%tDz= zbMJb2AD#q_&B;{A``6lA-FRZQ9W6H+sM*FyyZyarD0x1;Sdd1qSLf5)%gX70SJcrv zE9>Z|jTQ8xnnLm2mGmS!79C2Dd%01qg`RR$O3GI$Xt|{s1Y&-($wL1Qp1&Cao;ClU zY1kylWa=d{+42@E^N$~yX-#$JX0*%ClU^>(rjItZ(8rrrjA8t_>38FgueH?Bb2*D? zPoOtdS(sCqR!tl1jnrmq`Dva?*};Oi4|<&5BQZv2SLwB1+cL{~xW=HPM_lL9oAo7M zAU+wsX-8!m6|Jz;zn>xJz;mBJsWO?>279Z)$7b0M z7wI%~IVFBlbC@Zu6hU+C7<qV`1^)t;wZ9R60L z*U}buCwgyngCKgR4w~M>$G={^jNV4*d#x&uUM@C{bd&|faYAnvv|Tbg~e&vh0RA`I;b z@}UpbHQ$!}c)`4jn14DxidM{;L0L)#A!HIVLnDt__@p7Uv>7y?Ez@hL9x*+eJ1v(}dsqO- z|3fzK7GjA;s;e~HLA3S`coc4Ws9Z$XHcYe+9JqMDW2tV z&K|ZDnrXJTrDrpfMJL9Sov2fM&s$4Np>cbH6;ZWDb-hR_-vvTZ3sC&ru0w$`nKD8y z&&r-*`$3#qMX~rjh9Iq(uF+sM!m+PQTLJvTH+TS|&3L8THxZM3zbZ)PRYPwI;3$F+sG;7!yT zJCK*KuW8V#zRqd-v;~0i`qml;TY4LWe%4S*KV4cPz~@rS#|)_xuasp|%M4qJLMKz_ zMN&mkA;qHgaB&e>lAJtTl$U$R#c7W6b{%q?JzJ3w8+$T+@nTxJd^vsP>J|FRmCN+i zix+7}>ne&f(+S^@j*z$8*OgvE1bMw8N8rWW6xx8HQjGBrA9Dp+k#XAO`3G4_<*N;r z2Kruc2C+oP;|+wcA64ek8&$cY{ccejErYX4v9zF_8#mC^OPA=GD_7_;I=#NFjY0zh z$CbF;H|y1Tkgn7g|#bZKaat~`Bl1eY#~=k37rW6TZ0 zFR(SF!{fKjo=I(vBN3)bqqzzElYZ@@#4x{jfX>(#=N8$P#$1 zEOP{jYM3+Z9d|G1 z2nz`*DJ?0vu^=vv&YU_$m+-7h=g-r{^XEn}B!u!Lgb=4U8xsNxq5x%colgDxOqHS@ z{^GV)c1NpNqELLTQm3Y)5rOndNxHzRB^mTeaXS3~+Lqey7cQai6{Hd-D+pta4nFcQ zI(TlZ)7)9cMPQ)6pDN4C$=lPDN{fqcCM70raGpJTEK%|I_fIS@FaL8yLEQb+!MJ#n+mrn-2>-ws7j-tjTl!<^5wjgv6hb+-^pD>FXbfD`M5ADK%&EAGThmT zjvwx&p|j{LIy}&S2AyYsfC+X!`6PvhhEicc{%3i)Ia_LKYJL?K7DknomDG>loyENj zJ{IQ;knhK^sIRFZZx44$PE5SEC?+~&N`$6+6UNk*Dsvq*&#)0hP4PlzB3(_4qn5d3R?gCB(;5dRiI<1O!k@N(!Ag zae_|cJ5!tjX>oq?BrRLIlzhCr1o`lwz?kox+1DHq;8 zJUpB_A&`@}XEHQ3HVXd%-|>EEaIpV$l{&5aq0y{T_y8u!;B+<(4yP1CsRiownm;sJ znEe3v986Kjmo1XZDw1{D-D#2G9|igQQv?Y0ba&HfkURygn&RY%x6u!#u?p9BR2giedhm${j}X_i7Z%*2sX59i2a*YcF|%gC!Y zW2`5^+-IN{Unn&_=FWAGkBxmT9L_8mVXv>ZcZ|FsE{Gi!0^nBQ7|urtA3Ju8OmXz+ zQEF*vAx~(2{`~pZAy{2EX@$=)p5fT(c=}VT-k;8}S z1c)7Hfbg+nN9gF$J^?-!I5G+lJ`NlMj^Ns=RjbGYnvaT#8lE?A-fCw=j0Zsf?q2~R zSjR*~y$o}ug$ozbLB#cA(6mHcYL6T_45A}Aie%|XAC3k3Xxp}J&h{*66v0vuCZ%;+}+(ty@((zgl@E5U0u|O z5SWvlP35JfZ=;^TV)DPh$7RkO?czm?{u>Sq0&qttYr2Izlbs0NU7gee(wr!9%U~g_ zTDg+4Gc##vef@8c2VmNAY9Bao6`Xk-kPSSTm1Zt$v(nR_$jZnV_CN(#U0rnxS=O>C zy1F_*vV)jB6YoM^z!1j(CrOOehzhC57+1Em{3$9Tq8=ic)G=~J$oWi;O7TLyUi!ZLO`8h!h${)y?dTjEmmx?g377MkZO}AP|IbJ50mXRvWahuQVElYcR2!f*C5F zD=60}UqoVe?~1003V4RpXb|+Z#V=v$3EuOt*9P zT7WctFtC)G0`knmeaWT=+b=B1$a=E)GDTxlXAB5(+N5-@m%P{Ruknb2F zQ;q5mvqR*DDKl;{wrMlUVgBwAV^jd#wvS#D-yyGH@*Zw(0%3Nxl#U70OrDOz`~Y^M z&@ODsI2Z0i7w7rWVP9u4tzV5f4rI4j;JOc=n23n@>WYd_0{#66@t+Rt-#_BOKvN*>YcWsAWvv$%IPvknj|>aTaCdgLjR+0ho4j!04POW$8)0wn-n}A=6ao-9KnFqo zAcV_Uf{9Zf$6182FN(Hxwnn-T=_d#?B=UUR?lBuHMsljssb9Kh0tm-$ujsk6SC!@G zT@Uc_CVy{l+Vo(OLVW4(`#19~Lu0OdfUpdm!y++96y|LgDj%AjWu1 zObl(^x>acWz`lJWIIwT*d^^62wla$Oh$d{uxe)0)Mx2i&umH}6dI|w7)v5jnM`?9e zLO^Vt35oA5*6Xen1o#g7yEu~<99a`gw?~997C`$LI&sVbc=CxS#5iZuh2}p-!8BoM z>*nU>j{M=3$jC?vL@LbY&gA#QB7_k3j|gM`qmNK3CP&lZ;ZFs*j}bN{Z+gtjeD!7; zu5w{CU*dzOm7@R7Z#TIEQue9V>wdJB_w?CY(S_(h z`bvBl4M3`8m=cRdN22FCQu~wJscX~q=fj5(|I|fggnsC zuNXr6)X&$4yzm^q*$xy5;j`D@hV6Kg#wF5x&d2A%usv^77<|0XZ5Cy~YHQ6jKgMsT zmKGzKNNu&T_#JOv?D2D@uO@^G@{Ipj5K5O~f@mo=N%2r9iVUN!-A_>`oEDq?L5$P1 z)Koz}2n(Gc|BSoSoTG04iSHn7b(oI!$KM+=YgS0Jujik5+?Qfg#Tht0Q%#$amW~g& zISTL3i#H4wK(k)WnW5XHeZdQqISSdHHlzOL=@3t$bqP$|6wk~LA;wkUap##7kC!Fd zSW_e%qo1P#`CzReIX-?E>w{Ao_Y-x>$I8+&TBB;Kwy}J_8v7Nh;mA%0x{Z+^M2M3J z^RX$g-FA#P`>aX`ZZkGpLIBuaILU`sSqjz4Coxur_diY369tN)luTy zGIm96#iLwwR z&6`?)sQ@m=1d2So7uLWTS`G-Tv$eRn+Q#CSH3sds@?^3zxiVQF+P+G)ydO^Vxs|rY zH`d!(eze?De{(51&TITjP{q|6v?6>lIa4#|b5p|7xzw(KrSRUSCNs^~v+ktr+errD zLWkjSz7h)}*bGfigWNOogM~1}*dM2TCT|MP$BzZL(ZdclNJ6yKV6H{MVu|7eTjGIL zKpnh!Av()3ojc8W#$%4QbQD$GM2^kW)W;J)i{Y`!-a>53YBFg5Geagbo3`f1|A2*% zuToy(LAKiCNw^r zNltG37?;eRNlVyhXCZ{yXwZEd`-HyS4v~o@2Cu2lMFv%`Qw>*QJf1}a#(1iUi~~gy!AaN zFFlY8BFwH-Ht4ngSAiEkg1^69g4th=Vf;f7re-hI=cX1gzF?8aONotXY@bK~lF9FN zoB@k|Fwd!v{^Y@RusZ`+?JS(*7mmA@w*=hA6<~|+mH#YvqkNxrFO-)@QJy}d2 z2p#eGXGcB%*${U+hWD*7>M0YEqQOk_d5KEi$HVl#X?~&yV@Mc~oa|{ZXoq=E(Q4ES zr%{<*isIRrkr|oE#{T&TE>XE^ys<0yW&9rXq8S>%ESf0Uvc z-lSos`C+D9o(Yq`yX|myOL~%FVUa4Ax0dNNzo;|U4VOa*yePqcbZSP@^DqSRl*b(E z@R>`!&}v_h2laqx2XcU2xc&$#&lXq^|3eJB)+vJv82p8<(P+4VKV`juYZV|q<^2lx zgX5H*$(t%LG%~YP%7IFA-3OfQEyI5Z>ya8)Vh?dC(p~=lK^}$-|97Aevr0wy|3C>) zie#%8S}(V=zENgn{$`p&z5`Cz7jtO;T6+W}Nul!=Ks3f{Tdr1fqFkqa9wqJTb(Ut= z>aEOwUtzBOq*$x^d5%`|Vun_8IbNgM6=}4{icu;YL3;X|ou{Otf8X?P2}lz7e`Kd! UsoZjLV*mgE07*qoM6N<$g2^9G?f?J) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_up_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_up_item.png deleted file mode 100644 index ee471023e095a1ae11a0f614eb953b727b0b169d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3304 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 Eg5p97)c^nh diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png deleted file mode 100644 index a5a1787d593591f855be9a7eb8da271cc8d8f214..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1496 zcmaKs{XY{30LC|C-c2!W(h#B2QhA@kOt{brn;~tK$;-mn#DM?-zdb>=i zu*@RTd8@_pvUxpuxyoG1>Bsxw?uX}jKHujL_-0@|T~w8{l>h*Ms+%k3&``sHb<81=-~(e+|N^9C&_KHVw5X^3IM3J{S1(sAHJ}8!egC%W4+FY#L`JIX8~B! zIZ7C+< z6bcMhk7Jz$z zt<~^Npzeyeat^;b(tkMW#bRkwb5S`|-P(cZ{!1geIKC7Tzpi^Q9XhN7r*| zh)Tmw?h}4)r(e%EPx*~jbiDn>W9k_F^gyx#1J1b!&uZuD!J$Duh_I|$-B|3)pjcABT`DZr@@$gnJ?g*7niqC zPg~-q=_uM61|+bWZC}wlE4;C-L;LVrU6J(R@D0Z4=p`kt`4==LnW(d8wXiBZND)3NugXyk}j`B>QSp`rx>7I47#1U z_C?Zqn_!w_iq*Q=7#33$KOO+R;CW!bcdn#k;~tqqg>*o8s|#;{%M1@^2B=`1X*QOW z`~~EL<8YMd;Wk~hP%ln9+T{3weTCGPC>#3IdbbgtfSL(^;<-$(&+()%CWY(ZY}rUs zYZ^=Sws7E+dDpj6e_>>!qz;jFg;SMzWx6GvaM=_CJv#h+^qF(IggsR{8BYMQlBT|c zLR(J;=NJUkn>YRLcdDtY?zXt@zIEUuTe=1hEndEU6|7%)i#=`5cs5S}P9Mh=PcJfo z{ZbSwueq|yZyG~GMGk&1;XI&33fgfyu~6eIQgk!Fkv4<^W8F=|9U5oXINb+#fCen_ z{sB?u3Xfi@SxqMAC%ZI%1BJIf0uMiCx!yXz62rndMv z$=6toP8$LinV$s7C|ZjMS5+@W1rn4NxN=o7bmp|tGx-1vXy7V6(LK7Owl1b<1|o_O z>bY9rcsZ;+(mT(U8Vqy|@K*SC7Xeg!@WG?ntw{ZC`G3Vh1-90Bf1vJ=9f)jI$P4Q6YBQ@Z8;^^H#>9pe+1$q6DXU$-5VbBeJ(3kUiuh943T}3C$!G=4Zw&rX zIZx;etQ%$b10W;H`0fD|-g&n~Eq? zJZ zC}pc4u@0qD`7mQX=zMD+8o3Hi#&31p7{mxJ*6-KkigeYIgt}@Xn1a05YyE6U8VHU~ z8PL=CTn*0W$(#-|89Sz`9P!(hY?pOfm^ZQVXfjUeBhD+B#yUg0vkok?_%`$Xq0`=> g{}tB1bjDO$2a)_&SEAML{IoE@&Dj&vfF`E?18{b*hyVZp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png deleted file mode 100644 index c4992affd19cf3a55bb8ec2f3121e5befa69a55c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4310 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 diff --git a/code/nel/tools/3d/object_viewer_qt/CMakeLists.txt b/code/studio/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/CMakeLists.txt rename to code/studio/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/data/andbasr.ttf b/code/studio/data/andbasr.ttf similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/data/andbasr.ttf rename to code/studio/data/andbasr.ttf diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cdirection_widget.png b/code/studio/doc/html/cdirection_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cdirection_widget.png rename to code/studio/doc/html/cdirection_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cedit_color_widget.png b/code/studio/doc/html/cedit_color_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cedit_color_widget.png rename to code/studio/doc/html/cedit_color_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_float_widget.png b/code/studio/doc/html/cedit_range_float_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_float_widget.png rename to code/studio/doc/html/cedit_range_float_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_int_widget.png b/code/studio/doc/html/cedit_range_int_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_int_widget.png rename to code/studio/doc/html/cedit_range_int_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/gui_struct.png b/code/studio/doc/html/gui_struct.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/gui_struct.png rename to code/studio/doc/html/gui_struct.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/object_viewer_qt_window.png b/code/studio/doc/html/object_viewer_qt_window.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/object_viewer_qt_window.png rename to code/studio/doc/html/object_viewer_qt_window.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.bat b/code/studio/doc/make_ovqt_dox.bat similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.bat rename to code/studio/doc/make_ovqt_dox.bat diff --git a/code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.sh b/code/studio/doc/make_ovqt_dox.sh similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.sh rename to code/studio/doc/make_ovqt_dox.sh diff --git a/code/nel/tools/3d/object_viewer_qt/doc/ovqt.dox b/code/studio/doc/ovqt.dox similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/ovqt.dox rename to code/studio/doc/ovqt.dox diff --git a/code/nel/tools/3d/object_viewer_qt/ovqt_config.h.cmake b/code/studio/ovqt_config.h.cmake similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/ovqt_config.h.cmake rename to code/studio/ovqt_config.h.cmake diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/CMakeLists.txt b/code/studio/src/3rdparty/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/CMakeLists.txt rename to code/studio/src/3rdparty/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/CMakeLists.txt b/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/CMakeLists.txt rename to code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt b/code/studio/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt rename to code/studio/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 b/code/studio/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 rename to code/studio/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.LGPL b/code/studio/src/3rdparty/qtpropertybrowser/LICENSE.LGPL similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.LGPL rename to code/studio/src/3rdparty/qtpropertybrowser/LICENSE.LGPL diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase b/code/studio/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase rename to code/studio/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBrowserItem b/code/studio/src/3rdparty/qtpropertybrowser/QtBrowserItem similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBrowserItem rename to code/studio/src/3rdparty/qtpropertybrowser/QtBrowserItem diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtCharEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtCharEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtCharPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtCharPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtColorEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtColorEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtColorPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtColorPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtDateEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtDateEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDatePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtDatePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDatePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtDatePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtFontEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtFontEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtFontPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtFontPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtIntPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtIntPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtIntPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtIntPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLineEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtLineEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLineEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtLineEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtPointPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtPointPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtProperty b/code/studio/src/3rdparty/qtpropertybrowser/QtProperty similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtProperty rename to code/studio/src/3rdparty/qtpropertybrowser/QtProperty diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtRectPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtRectPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtScrollBarFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtScrollBarFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtScrollBarFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtScrollBarFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtSizePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtSizePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSliderFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtSliderFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSliderFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtSliderFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtStringPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtStringPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtStringPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtStringPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimeEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtTimeEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimeEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtTimeEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtTimePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtTimePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantProperty b/code/studio/src/3rdparty/qtpropertybrowser/QtVariantProperty similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantProperty rename to code/studio/src/3rdparty/qtpropertybrowser/QtVariantProperty diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/README.TXT b/code/studio/src/3rdparty/qtpropertybrowser/README.TXT similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/README.TXT rename to code/studio/src/3rdparty/qtpropertybrowser/README.TXT diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-busy.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-busy.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-busy.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-busy.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-cross.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-cross.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-cross.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-cross.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hand.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hand.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hand.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hand.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-wait.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-wait.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-wait.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-wait.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/resetproperty.png b/code/studio/src/3rdparty/qtpropertybrowser/images/resetproperty.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/resetproperty.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/resetproperty.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.h b/code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.h rename to code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.h b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.h b/code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/CMakeLists.txt rename to code/studio/src/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/description.h b/code/studio/src/description.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/description.h rename to code/studio/src/description.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin.h b/code/studio/src/extension_system/iplugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin.h rename to code/studio/src/extension_system/iplugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_manager.h rename to code/studio/src/extension_system/iplugin_manager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_spec.h b/code/studio/src/extension_system/iplugin_spec.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_spec.h rename to code/studio/src/extension_system/iplugin_spec.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.cpp rename to code/studio/src/extension_system/plugin_manager.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.h rename to code/studio/src/extension_system/plugin_manager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.cpp b/code/studio/src/extension_system/plugin_spec.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.cpp rename to code/studio/src/extension_system/plugin_spec.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.h b/code/studio/src/extension_system/plugin_spec.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.h rename to code/studio/src/extension_system/plugin_spec.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/ic_nel_pill.ico b/code/studio/src/ic_nel_pill.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/ic_nel_pill.ico rename to code/studio/src/ic_nel_pill.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/images/nel_ide_load.png b/code/studio/src/images/nel_ide_load.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/images/nel_ide_load.png rename to code/studio/src/images/nel_ide_load.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/main.cpp b/code/studio/src/main.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/main.cpp rename to code/studio/src/main.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.qrc b/code/studio/src/object_viewer_qt.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.qrc rename to code/studio/src/object_viewer_qt.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.rc b/code/studio/src/object_viewer_qt.rc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.rc rename to code/studio/src/object_viewer_qt.rc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/studio/src/plugins/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt rename to code/studio/src/plugins/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt b/code/studio/src/plugins/bnp_manager/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt rename to code/studio/src/plugins/bnp_manager/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp b/code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp rename to code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h b/code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h rename to code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui b/code/studio/src/plugins/bnp_manager/bnp_dirtree_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui rename to code/studio/src/plugins/bnp_manager/bnp_dirtree_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp b/code/studio/src/plugins/bnp_manager/bnp_file.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp rename to code/studio/src/plugins/bnp_manager/bnp_file.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h b/code/studio/src/plugins/bnp_manager/bnp_file.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h rename to code/studio/src/plugins/bnp_manager/bnp_file.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp b/code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp rename to code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h b/code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h rename to code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui b/code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui rename to code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp b/code/studio/src/plugins/bnp_manager/bnp_filesystem_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp rename to code/studio/src/plugins/bnp_manager/bnp_filesystem_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h b/code/studio/src/plugins/bnp_manager/bnp_filesystem_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h rename to code/studio/src/plugins/bnp_manager/bnp_filesystem_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc b/code/studio/src/plugins/bnp_manager/bnp_manager.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc rename to code/studio/src/plugins/bnp_manager/bnp_manager.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h b/code/studio/src/plugins/bnp_manager/bnp_manager_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h rename to code/studio/src/plugins/bnp_manager/bnp_manager_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp rename to code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h rename to code/studio/src/plugins/bnp_manager/bnp_manager_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp b/code/studio/src/plugins/bnp_manager/bnp_manager_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp rename to code/studio/src/plugins/bnp_manager/bnp_manager_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h b/code/studio/src/plugins/bnp_manager/bnp_manager_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h rename to code/studio/src/plugins/bnp_manager/bnp_manager_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui b/code/studio/src/plugins/bnp_manager/bnp_manager_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui rename to code/studio/src/plugins/bnp_manager/bnp_manager_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp b/code/studio/src/plugins/bnp_manager/bnp_proxy_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp rename to code/studio/src/plugins/bnp_manager/bnp_proxy_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h b/code/studio/src/plugins/bnp_manager/bnp_proxy_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h rename to code/studio/src/plugins/bnp_manager/bnp_proxy_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_bnp_make.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_bnp_make.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_export.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_export.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_new.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_new.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_new.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_new.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_reset_all.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_reset_all.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml b/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml rename to code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/CMakeLists.txt b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/CMakeLists.txt rename to code/studio/src/plugins/disp_sheet_id/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp rename to code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h rename to code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml b/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml rename to code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.cpp b/code/studio/src/plugins/disp_sheet_id/sheet_id_view.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.cpp rename to code/studio/src/plugins/disp_sheet_id/sheet_id_view.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.h b/code/studio/src/plugins/disp_sheet_id/sheet_id_view.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.h rename to code/studio/src/plugins/disp_sheet_id/sheet_id_view.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.ui b/code/studio/src/plugins/disp_sheet_id/sheet_id_view.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.ui rename to code/studio/src/plugins/disp_sheet_id/sheet_id_view.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/CMakeLists.txt b/code/studio/src/plugins/example/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/CMakeLists.txt rename to code/studio/src/plugins/example/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.cpp b/code/studio/src/plugins/example/example_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.cpp rename to code/studio/src/plugins/example/example_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.h b/code/studio/src/plugins/example/example_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.h rename to code/studio/src/plugins/example/example_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.cpp b/code/studio/src/plugins/example/example_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.cpp rename to code/studio/src/plugins/example/example_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.h b/code/studio/src/plugins/example/example_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.h rename to code/studio/src/plugins/example/example_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.ui b/code/studio/src/plugins/example/example_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.ui rename to code/studio/src/plugins/example/example_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/ovqt_plugin_example.xml b/code/studio/src/plugins/example/ovqt_plugin_example.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/ovqt_plugin_example.xml rename to code/studio/src/plugins/example/ovqt_plugin_example.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.cpp b/code/studio/src/plugins/example/qnel_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.cpp rename to code/studio/src/plugins/example/qnel_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.h b/code/studio/src/plugins/example/qnel_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.h rename to code/studio/src/plugins/example/qnel_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.cpp b/code/studio/src/plugins/example/simple_viewer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.cpp rename to code/studio/src/plugins/example/simple_viewer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.h b/code/studio/src/plugins/example/simple_viewer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.h rename to code/studio/src/plugins/example/simple_viewer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt rename to code/studio/src/plugins/georges_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/studio/src/plugins/georges_editor/actions.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp rename to code/studio/src/plugins/georges_editor/actions.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/studio/src/plugins/georges_editor/actions.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h rename to code/studio/src/plugins/georges_editor/actions.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.cpp b/code/studio/src/plugins/georges_editor/expandable_headerview.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.cpp rename to code/studio/src/plugins/georges_editor/expandable_headerview.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.h b/code/studio/src/plugins/georges_editor/expandable_headerview.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.h rename to code/studio/src/plugins/georges_editor/expandable_headerview.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp b/code/studio/src/plugins/georges_editor/formdelegate.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp rename to code/studio/src/plugins/georges_editor/formdelegate.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h b/code/studio/src/plugins/georges_editor/formdelegate.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h rename to code/studio/src/plugins/georges_editor/formdelegate.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/studio/src/plugins/georges_editor/formitem.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp rename to code/studio/src/plugins/georges_editor/formitem.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/studio/src/plugins/georges_editor/formitem.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h rename to code/studio/src/plugins/georges_editor/formitem.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.cpp b/code/studio/src/plugins/georges_editor/georges.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.cpp rename to code/studio/src/plugins/georges_editor/georges.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.h b/code/studio/src/plugins/georges_editor/georges.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.h rename to code/studio/src/plugins/georges_editor/georges.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_dirtree_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.cpp rename to code/studio/src/plugins/georges_editor/georges_dirtree_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.h b/code/studio/src/plugins/georges_editor/georges_dirtree_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.h rename to code/studio/src/plugins/georges_editor/georges_dirtree_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_form.ui b/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_form.ui rename to code/studio/src/plugins/georges_editor/georges_dirtree_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc b/code/studio/src/plugins/georges_editor/georges_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc rename to code/studio/src/plugins/georges_editor/georges_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_constants.h b/code/studio/src/plugins/georges_editor/georges_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_constants.h rename to code/studio/src/plugins/georges_editor/georges_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp b/code/studio/src/plugins/georges_editor/georges_editor_form.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp rename to code/studio/src/plugins/georges_editor/georges_editor_form.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h b/code/studio/src/plugins/georges_editor/georges_editor_form.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h rename to code/studio/src/plugins/georges_editor/georges_editor_form.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.ui b/code/studio/src/plugins/georges_editor/georges_editor_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.ui rename to code/studio/src/plugins/georges_editor/georges_editor_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.cpp b/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.cpp rename to code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.h b/code/studio/src/plugins/georges_editor/georges_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.h rename to code/studio/src/plugins/georges_editor/georges_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.cpp b/code/studio/src/plugins/georges_editor/georges_filesystem_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.cpp rename to code/studio/src/plugins/georges_editor/georges_filesystem_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.h b/code/studio/src/plugins/georges_editor/georges_filesystem_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.h rename to code/studio/src/plugins/georges_editor/georges_filesystem_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp rename to code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h rename to code/studio/src/plugins/georges_editor/georges_treeview_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui b/code/studio/src/plugins/georges_editor/georges_treeview_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui rename to code/studio/src/plugins/georges_editor/georges_treeview_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp rename to code/studio/src/plugins/georges_editor/georgesform_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/studio/src/plugins/georges_editor/georgesform_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h rename to code/studio/src/plugins/georges_editor/georgesform_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_proxy_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp rename to code/studio/src/plugins/georges_editor/georgesform_proxy_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h b/code/studio/src/plugins/georges_editor/georgesform_proxy_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h rename to code/studio/src/plugins/georges_editor/georgesform_proxy_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico b/code/studio/src/plugins/georges_editor/images/array.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico rename to code/studio/src/plugins/georges_editor/images/array.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico b/code/studio/src/plugins/georges_editor/images/header.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico rename to code/studio/src/plugins/georges_editor/images/header.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico b/code/studio/src/plugins/georges_editor/images/hold.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico rename to code/studio/src/plugins/georges_editor/images/hold.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/ic_nel_georges_editor.png b/code/studio/src/plugins/georges_editor/images/ic_nel_georges_editor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/ic_nel_georges_editor.png rename to code/studio/src/plugins/georges_editor/images/ic_nel_georges_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico b/code/studio/src/plugins/georges_editor/images/root.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico rename to code/studio/src/plugins/georges_editor/images/root.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/struct.ico b/code/studio/src/plugins/georges_editor/images/struct.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/struct.ico rename to code/studio/src/plugins/georges_editor/images/struct.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico b/code/studio/src/plugins/georges_editor/images/vstruct.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico rename to code/studio/src/plugins/georges_editor/images/vstruct.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico b/code/studio/src/plugins/georges_editor/images/zfee51.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico rename to code/studio/src/plugins/georges_editor/images/zfee51.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml b/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml rename to code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.cpp b/code/studio/src/plugins/georges_editor/stdpch.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.cpp rename to code/studio/src/plugins/georges_editor/stdpch.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.h b/code/studio/src/plugins/georges_editor/stdpch.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.h rename to code/studio/src/plugins/georges_editor/stdpch.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/CMakeLists.txt rename to code/studio/src/plugins/gui_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.cpp b/code/studio/src/plugins/gui_editor/action_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.cpp rename to code/studio/src/plugins/gui_editor/action_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.h b/code/studio/src/plugins/gui_editor/action_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.h rename to code/studio/src/plugins/gui_editor/action_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.ui b/code/studio/src/plugins/gui_editor/action_editor.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.ui rename to code/studio/src/plugins/gui_editor/action_editor.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.cpp b/code/studio/src/plugins/gui_editor/add_widget_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.cpp rename to code/studio/src/plugins/gui_editor/add_widget_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.h b/code/studio/src/plugins/gui_editor/add_widget_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.h rename to code/studio/src/plugins/gui_editor/add_widget_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.ui b/code/studio/src/plugins/gui_editor/add_widget_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.ui rename to code/studio/src/plugins/gui_editor/add_widget_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.cpp b/code/studio/src/plugins/gui_editor/editor_message_processor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.cpp rename to code/studio/src/plugins/gui_editor/editor_message_processor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.h b/code/studio/src/plugins/gui_editor/editor_message_processor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.h rename to code/studio/src/plugins/gui_editor/editor_message_processor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.cpp b/code/studio/src/plugins/gui_editor/editor_selection_watcher.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.cpp rename to code/studio/src/plugins/gui_editor/editor_selection_watcher.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.h b/code/studio/src/plugins/gui_editor/editor_selection_watcher.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.h rename to code/studio/src/plugins/gui_editor/editor_selection_watcher.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_constants.h b/code/studio/src/plugins/gui_editor/gui_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_constants.h rename to code/studio/src/plugins/gui_editor/gui_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.cpp b/code/studio/src/plugins/gui_editor/gui_editor_context.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_context.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.h b/code/studio/src/plugins/gui_editor/gui_editor_context.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.h rename to code/studio/src/plugins/gui_editor/gui_editor_context.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.cpp b/code/studio/src/plugins/gui_editor/gui_editor_core_listener.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_core_listener.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.h b/code/studio/src/plugins/gui_editor/gui_editor_core_listener.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.h rename to code/studio/src/plugins/gui_editor/gui_editor_core_listener.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_global.h b/code/studio/src/plugins/gui_editor/gui_editor_global.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_global.h rename to code/studio/src/plugins/gui_editor/gui_editor_global.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.cpp b/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.h b/code/studio/src/plugins/gui_editor/gui_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.h rename to code/studio/src/plugins/gui_editor/gui_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.h rename to code/studio/src/plugins/gui_editor/gui_editor_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.ui b/code/studio/src/plugins/gui_editor/gui_editor_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.ui rename to code/studio/src/plugins/gui_editor/gui_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.cpp b/code/studio/src/plugins/gui_editor/link_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.cpp rename to code/studio/src/plugins/gui_editor/link_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.h b/code/studio/src/plugins/gui_editor/link_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.h rename to code/studio/src/plugins/gui_editor/link_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.ui b/code/studio/src/plugins/gui_editor/link_editor.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.ui rename to code/studio/src/plugins/gui_editor/link_editor.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.cpp b/code/studio/src/plugins/gui_editor/link_list.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.cpp rename to code/studio/src/plugins/gui_editor/link_list.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.h b/code/studio/src/plugins/gui_editor/link_list.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.h rename to code/studio/src/plugins/gui_editor/link_list.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.ui b/code/studio/src/plugins/gui_editor/link_list.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.ui rename to code/studio/src/plugins/gui_editor/link_list.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.cpp rename to code/studio/src/plugins/gui_editor/nel3d_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.h rename to code/studio/src/plugins/gui_editor/nel3d_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.cpp rename to code/studio/src/plugins/gui_editor/nelgui_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.h rename to code/studio/src/plugins/gui_editor/nelgui_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.cpp b/code/studio/src/plugins/gui_editor/new_property_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.cpp rename to code/studio/src/plugins/gui_editor/new_property_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.h b/code/studio/src/plugins/gui_editor/new_property_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.h rename to code/studio/src/plugins/gui_editor/new_property_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.ui b/code/studio/src/plugins/gui_editor/new_property_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.ui rename to code/studio/src/plugins/gui_editor/new_property_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.cpp b/code/studio/src/plugins/gui_editor/new_widget_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.cpp rename to code/studio/src/plugins/gui_editor/new_widget_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.h b/code/studio/src/plugins/gui_editor/new_widget_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.h rename to code/studio/src/plugins/gui_editor/new_widget_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.ui b/code/studio/src/plugins/gui_editor/new_widget_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.ui rename to code/studio/src/plugins/gui_editor/new_widget_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml b/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml rename to code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.cpp b/code/studio/src/plugins/gui_editor/proc_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.cpp rename to code/studio/src/plugins/gui_editor/proc_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.h b/code/studio/src/plugins/gui_editor/proc_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.h rename to code/studio/src/plugins/gui_editor/proc_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.ui b/code/studio/src/plugins/gui_editor/proc_editor.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.ui rename to code/studio/src/plugins/gui_editor/proc_editor.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.cpp b/code/studio/src/plugins/gui_editor/proc_list.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.cpp rename to code/studio/src/plugins/gui_editor/proc_list.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.h b/code/studio/src/plugins/gui_editor/proc_list.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.h rename to code/studio/src/plugins/gui_editor/proc_list.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.ui b/code/studio/src/plugins/gui_editor/proc_list.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.ui rename to code/studio/src/plugins/gui_editor/proc_list.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.cpp b/code/studio/src/plugins/gui_editor/project_file_parser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.cpp rename to code/studio/src/plugins/gui_editor/project_file_parser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.h b/code/studio/src/plugins/gui_editor/project_file_parser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.h rename to code/studio/src/plugins/gui_editor/project_file_parser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.cpp b/code/studio/src/plugins/gui_editor/project_file_serializer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.cpp rename to code/studio/src/plugins/gui_editor/project_file_serializer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.h b/code/studio/src/plugins/gui_editor/project_file_serializer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.h rename to code/studio/src/plugins/gui_editor/project_file_serializer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files.h b/code/studio/src/plugins/gui_editor/project_files.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files.h rename to code/studio/src/plugins/gui_editor/project_files.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files/login.xml b/code/studio/src/plugins/gui_editor/project_files/login.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files/login.xml rename to code/studio/src/plugins/gui_editor/project_files/login.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.cpp b/code/studio/src/plugins/gui_editor/project_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.cpp rename to code/studio/src/plugins/gui_editor/project_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.h b/code/studio/src/plugins/gui_editor/project_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.h rename to code/studio/src/plugins/gui_editor/project_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.ui b/code/studio/src/plugins/gui_editor/project_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.ui rename to code/studio/src/plugins/gui_editor/project_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.cpp rename to code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.h rename to code/studio/src/plugins/gui_editor/property_browser_ctrl.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.cpp b/code/studio/src/plugins/gui_editor/widget_hierarchy.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.cpp rename to code/studio/src/plugins/gui_editor/widget_hierarchy.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.h b/code/studio/src/plugins/gui_editor/widget_hierarchy.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.h rename to code/studio/src/plugins/gui_editor/widget_hierarchy.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.ui b/code/studio/src/plugins/gui_editor/widget_hierarchy.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.ui rename to code/studio/src/plugins/gui_editor/widget_hierarchy.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info.h b/code/studio/src/plugins/gui_editor/widget_info.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info.h rename to code/studio/src/plugins/gui_editor/widget_info.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.cpp b/code/studio/src/plugins/gui_editor/widget_info_serializer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.cpp rename to code/studio/src/plugins/gui_editor/widget_info_serializer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.h b/code/studio/src/plugins/gui_editor/widget_info_serializer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.h rename to code/studio/src/plugins/gui_editor/widget_info_serializer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree.h b/code/studio/src/plugins/gui_editor/widget_info_tree.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree.h rename to code/studio/src/plugins/gui_editor/widget_info_tree.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_node.h b/code/studio/src/plugins/gui_editor/widget_info_tree_node.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_node.h rename to code/studio/src/plugins/gui_editor/widget_info_tree_node.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_visitor.h b/code/studio/src/plugins/gui_editor/widget_info_tree_visitor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_visitor.h rename to code/studio/src/plugins/gui_editor/widget_info_tree_visitor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.cpp b/code/studio/src/plugins/gui_editor/widget_properties.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.cpp rename to code/studio/src/plugins/gui_editor/widget_properties.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.h b/code/studio/src/plugins/gui_editor/widget_properties.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.h rename to code/studio/src/plugins/gui_editor/widget_properties.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.ui b/code/studio/src/plugins/gui_editor/widget_properties.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.ui rename to code/studio/src/plugins/gui_editor/widget_properties.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.cpp b/code/studio/src/plugins/gui_editor/widget_properties_parser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.cpp rename to code/studio/src/plugins/gui_editor/widget_properties_parser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.h b/code/studio/src/plugins/gui_editor/widget_properties_parser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.h rename to code/studio/src/plugins/gui_editor/widget_properties_parser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.cpp b/code/studio/src/plugins/gui_editor/widget_serializer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.cpp rename to code/studio/src/plugins/gui_editor/widget_serializer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.h b/code/studio/src/plugins/gui_editor/widget_serializer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.h rename to code/studio/src/plugins/gui_editor/widget_serializer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBase.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBase.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBaseButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlColPick.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlColPick.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlScroll.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlScroll.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTabButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTabButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTabButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlTabButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTextButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml rename to code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar3.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar3.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewDigit.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewDigit.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewNumber.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewQuantity.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewQuantity.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupCell.xml b/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupCell.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupCell.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupContainer.xml b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupContainer.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupEditBox.xml b/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupEditBox.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupFrame.xml b/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupFrame.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHTML.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHTML.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHeader.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHeader.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupList.xml b/code/studio/src/plugins/gui_editor/widgets/GroupList.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupList.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupList.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupMenu.xml b/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupMenu.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupModal.xml b/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupModal.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupModal.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupParagraph.xml b/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupParagraph.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupScrollText.xml b/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupScrollText.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTab.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTab.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupTab.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTable.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTable.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupTable.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTree.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTree.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupTree.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceElement.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceElement.xml rename to code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroup.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroup.xml rename to code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml rename to code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/RootGroup.xml b/code/studio/src/plugins/gui_editor/widgets/RootGroup.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/RootGroup.xml rename to code/studio/src/plugins/gui_editor/widgets/RootGroup.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmap.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewText.xml b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewText.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewText.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextFormated.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextID.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextID.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt b/code/studio/src/plugins/landscape_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt rename to code/studio/src/plugins/landscape_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp b/code/studio/src/plugins/landscape_editor/builder_zone.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp rename to code/studio/src/plugins/landscape_editor/builder_zone.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h b/code/studio/src/plugins/landscape_editor/builder_zone.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h rename to code/studio/src/plugins/landscape_editor/builder_zone.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp b/code/studio/src/plugins/landscape_editor/builder_zone_base.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp rename to code/studio/src/plugins/landscape_editor/builder_zone_base.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.h b/code/studio/src/plugins/landscape_editor/builder_zone_base.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.h rename to code/studio/src/plugins/landscape_editor/builder_zone_base.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp b/code/studio/src/plugins/landscape_editor/builder_zone_region.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp rename to code/studio/src/plugins/landscape_editor/builder_zone_region.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h b/code/studio/src/plugins/landscape_editor/builder_zone_region.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h rename to code/studio/src/plugins/landscape_editor/builder_zone_region.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_grid.png b/code/studio/src/plugins/landscape_editor/icons/ic_grid.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_grid.png rename to code/studio/src/plugins/landscape_editor/icons/ic_grid.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_transition_land.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_transition_land.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_transition_land.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_transition_land.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_world_editor.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_world_editor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_world_editor.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_world_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zone.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_zone.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zone.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_zone.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zonel.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_zonel.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zonel.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_zonel.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zones.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_zones.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zones.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_zones.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_snapshot.png b/code/studio/src/plugins/landscape_editor/icons/ic_snapshot.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_snapshot.png rename to code/studio/src/plugins/landscape_editor/icons/ic_snapshot.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp b/code/studio/src/plugins/landscape_editor/landscape_actions.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp rename to code/studio/src/plugins/landscape_editor/landscape_actions.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h b/code/studio/src/plugins/landscape_editor/landscape_actions.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h rename to code/studio/src/plugins/landscape_editor/landscape_actions.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor.qrc b/code/studio/src/plugins/landscape_editor/landscape_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor.qrc rename to code/studio/src/plugins/landscape_editor/landscape_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_constants.h b/code/studio/src/plugins/landscape_editor/landscape_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_constants.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_global.h b/code/studio/src/plugins/landscape_editor/landscape_editor_global.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_global.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_global.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp rename to code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.h b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp rename to code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h b/code/studio/src/plugins/landscape_editor/landscape_editor_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.ui b/code/studio/src/plugins/landscape_editor/landscape_editor_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.ui rename to code/studio/src/plugins/landscape_editor/landscape_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp b/code/studio/src/plugins/landscape_editor/landscape_scene.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp rename to code/studio/src/plugins/landscape_editor/landscape_scene.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h b/code/studio/src/plugins/landscape_editor/landscape_scene.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h rename to code/studio/src/plugins/landscape_editor/landscape_scene.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp b/code/studio/src/plugins/landscape_editor/landscape_scene_base.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp rename to code/studio/src/plugins/landscape_editor/landscape_scene_base.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.h b/code/studio/src/plugins/landscape_editor/landscape_scene_base.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.h rename to code/studio/src/plugins/landscape_editor/landscape_scene_base.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp b/code/studio/src/plugins/landscape_editor/landscape_view.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp rename to code/studio/src/plugins/landscape_editor/landscape_view.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.h b/code/studio/src/plugins/landscape_editor/landscape_view.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.h rename to code/studio/src/plugins/landscape_editor/landscape_view.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp b/code/studio/src/plugins/landscape_editor/list_zones_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp rename to code/studio/src/plugins/landscape_editor/list_zones_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.h b/code/studio/src/plugins/landscape_editor/list_zones_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.h rename to code/studio/src/plugins/landscape_editor/list_zones_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp b/code/studio/src/plugins/landscape_editor/list_zones_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp rename to code/studio/src/plugins/landscape_editor/list_zones_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h b/code/studio/src/plugins/landscape_editor/list_zones_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h rename to code/studio/src/plugins/landscape_editor/list_zones_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.ui b/code/studio/src/plugins/landscape_editor/list_zones_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.ui rename to code/studio/src/plugins/landscape_editor/list_zones_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml rename to code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp b/code/studio/src/plugins/landscape_editor/pixmap_database.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp rename to code/studio/src/plugins/landscape_editor/pixmap_database.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.h b/code/studio/src/plugins/landscape_editor/pixmap_database.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.h rename to code/studio/src/plugins/landscape_editor/pixmap_database.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp b/code/studio/src/plugins/landscape_editor/project_settings_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp rename to code/studio/src/plugins/landscape_editor/project_settings_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.h b/code/studio/src/plugins/landscape_editor/project_settings_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.h rename to code/studio/src/plugins/landscape_editor/project_settings_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.ui b/code/studio/src/plugins/landscape_editor/project_settings_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.ui rename to code/studio/src/plugins/landscape_editor/project_settings_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/shapshot_dialog.ui b/code/studio/src/plugins/landscape_editor/shapshot_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/shapshot_dialog.ui rename to code/studio/src/plugins/landscape_editor/shapshot_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp b/code/studio/src/plugins/landscape_editor/snapshot_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp rename to code/studio/src/plugins/landscape_editor/snapshot_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.h b/code/studio/src/plugins/landscape_editor/snapshot_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.h rename to code/studio/src/plugins/landscape_editor/snapshot_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp b/code/studio/src/plugins/landscape_editor/zone_region_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp rename to code/studio/src/plugins/landscape_editor/zone_region_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h b/code/studio/src/plugins/landscape_editor/zone_region_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h rename to code/studio/src/plugins/landscape_editor/zone_region_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/CMakeLists.txt b/code/studio/src/plugins/log/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/CMakeLists.txt rename to code/studio/src/plugins/log/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_form.ui b/code/studio/src/plugins/log/log_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_form.ui rename to code/studio/src/plugins/log/log_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.cpp rename to code/studio/src/plugins/log/log_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.h b/code/studio/src/plugins/log/log_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.h rename to code/studio/src/plugins/log/log_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.cpp b/code/studio/src/plugins/log/log_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.cpp rename to code/studio/src/plugins/log/log_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.h b/code/studio/src/plugins/log/log_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.h rename to code/studio/src/plugins/log/log_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.ui b/code/studio/src/plugins/log/log_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.ui rename to code/studio/src/plugins/log/log_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/ovqt_plugin_log.xml b/code/studio/src/plugins/log/ovqt_plugin_log.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/ovqt_plugin_log.xml rename to code/studio/src/plugins/log/ovqt_plugin_log.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.cpp b/code/studio/src/plugins/log/qt_displayer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.cpp rename to code/studio/src/plugins/log/qt_displayer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.h b/code/studio/src/plugins/log/qt_displayer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.h rename to code/studio/src/plugins/log/qt_displayer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/CMakeLists.txt b/code/studio/src/plugins/mission_compiler/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/CMakeLists.txt rename to code/studio/src/plugins/mission_compiler/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-left-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-left-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-double-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-left-double-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-double-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-left-double-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-right-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-right-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-double-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-right-double-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-double-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-right-double-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/document-export-4.png b/code/studio/src/plugins/mission_compiler/images/document-export-4.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/document-export-4.png rename to code/studio/src/plugins/mission_compiler/images/document-export-4.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_add_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_add_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_delete_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_delete_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_down_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_down_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_down_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_down_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_generic_settings.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_generic_settings.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_generic_settings.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_generic_settings.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_reset_all.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_reset_all.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_reset_all.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_reset_all.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_up_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_up_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_up_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_up_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/news-subscribe-2.png b/code/studio/src/plugins/mission_compiler/images/news-subscribe-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/news-subscribe-2.png rename to code/studio/src/plugins/mission_compiler/images/news-subscribe-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/run-build-2.png b/code/studio/src/plugins/mission_compiler/images/run-build-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/run-build-2.png rename to code/studio/src/plugins/mission_compiler/images/run-build-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler.qrc b/code/studio/src/plugins/mission_compiler/mission_compiler.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler.qrc rename to code/studio/src/plugins/mission_compiler/mission_compiler.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.cpp rename to code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.h b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.ui b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.ui rename to code/studio/src/plugins/mission_compiler/mission_compiler_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.cpp rename to code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.h b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin_constants.h b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin_constants.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_plugin_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.cpp rename to code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.h b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.ui b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.ui rename to code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml b/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml rename to code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.cpp b/code/studio/src/plugins/mission_compiler/server_entry_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.cpp rename to code/studio/src/plugins/mission_compiler/server_entry_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.h b/code/studio/src/plugins/mission_compiler/server_entry_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.h rename to code/studio/src/plugins/mission_compiler/server_entry_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.ui b/code/studio/src/plugins/mission_compiler/server_entry_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.ui rename to code/studio/src/plugins/mission_compiler/server_entry_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.cpp b/code/studio/src/plugins/mission_compiler/validation_file.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.cpp rename to code/studio/src/plugins/mission_compiler/validation_file.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.h b/code/studio/src/plugins/mission_compiler/validation_file.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.h rename to code/studio/src/plugins/mission_compiler/validation_file.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/CMakeLists.txt b/code/studio/src/plugins/object_viewer/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/CMakeLists.txt rename to code/studio/src/plugins/object_viewer/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.cpp b/code/studio/src/plugins/object_viewer/graphics_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.cpp rename to code/studio/src/plugins/object_viewer/graphics_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.h b/code/studio/src/plugins/object_viewer/graphics_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.h rename to code/studio/src/plugins/object_viewer/graphics_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.ui b/code/studio/src/plugins/object_viewer/graphics_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.ui rename to code/studio/src/plugins/object_viewer/graphics_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.cpp b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.cpp rename to code/studio/src/plugins/object_viewer/graphics_viewport.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.h b/code/studio/src/plugins/object_viewer/graphics_viewport.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.h rename to code/studio/src/plugins/object_viewer/graphics_viewport.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_add_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_add_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_anim.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_anim.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_anim.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_anim.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_animset.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_animset.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_animset.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_animset.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_append_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_append_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_append_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_append_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_bgcolor.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_bgcolor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_bgcolor.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_bgcolor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_add.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_add.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_add.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_add.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_del.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_del.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_del.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_del.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_fps.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_fps.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_fps.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_fps.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_daynight.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_daynight.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_daynight.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_daynight.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_delete_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_delete_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_down_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_down_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_down_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_down_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_framedelay.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_framedelay.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_framedelay.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_framedelay.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_insert_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_insert_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_insert_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_insert_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mixer.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_mixer.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mixer.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_mixer.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_new.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_new.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_new.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_new.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_open.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_open.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_open.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_open.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particles.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_particles.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particles.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_particles.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_pill.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_pill.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_pill.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_pill.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_reset_all.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_reset_all.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_reset_all.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_reset_all.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_reset_camera.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_reset_camera.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_reset_camera.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_reset_camera.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_save.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_save.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save_as.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_save_as.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save_as.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_save_as.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_skelscale.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_skelscale.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_skelscale.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_skelscale.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_sound.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_sound.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_sound.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_sound.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_up_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_up_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_up_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_up_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_veget.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_veget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_veget.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_veget.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_vegetset.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_vegetset.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_vegetset.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_vegetset.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_water.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_water.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_water.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_water.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_wind.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_wind.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_wind.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_wind.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_workspace_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_workspace_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_workspace_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_workspace_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/dqynight.png b/code/studio/src/plugins/object_viewer/images/dqynight.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/dqynight.png rename to code/studio/src/plugins/object_viewer/images/dqynight.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/ico_mrm_mesh.png b/code/studio/src/plugins/object_viewer/images/ico_mrm_mesh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/ico_mrm_mesh.png rename to code/studio/src/plugins/object_viewer/images/ico_mrm_mesh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/mixer.png b/code/studio/src/plugins/object_viewer/images/mixer.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/mixer.png rename to code/studio/src/plugins/object_viewer/images/mixer.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/nel.png b/code/studio/src/plugins/object_viewer/images/nel.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/nel.png rename to code/studio/src/plugins/object_viewer/images/nel.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pause.png b/code/studio/src/plugins/object_viewer/images/pause.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pause.png rename to code/studio/src/plugins/object_viewer/images/pause.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/play.png b/code/studio/src/plugins/object_viewer/images/play.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/play.png rename to code/studio/src/plugins/object_viewer/images/play.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/polymode.png b/code/studio/src/plugins/object_viewer/images/polymode.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/polymode.png rename to code/studio/src/plugins/object_viewer/images/polymode.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pqrticles.png b/code/studio/src/plugins/object_viewer/images/pqrticles.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pqrticles.png rename to code/studio/src/plugins/object_viewer/images/pqrticles.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/refresh.png b/code/studio/src/plugins/object_viewer/images/refresh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/refresh.png rename to code/studio/src/plugins/object_viewer/images/refresh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmfill.png b/code/studio/src/plugins/object_viewer/images/rmfill.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmfill.png rename to code/studio/src/plugins/object_viewer/images/rmfill.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmline.png b/code/studio/src/plugins/object_viewer/images/rmline.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmline.png rename to code/studio/src/plugins/object_viewer/images/rmline.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmpoints.png b/code/studio/src/plugins/object_viewer/images/rmpoints.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmpoints.png rename to code/studio/src/plugins/object_viewer/images/rmpoints.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-backward.png b/code/studio/src/plugins/object_viewer/images/seek-backward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-backward.png rename to code/studio/src/plugins/object_viewer/images/seek-backward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-forward.png b/code/studio/src/plugins/object_viewer/images/seek-forward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-forward.png rename to code/studio/src/plugins/object_viewer/images/seek-forward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-backward.png b/code/studio/src/plugins/object_viewer/images/skip-backward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-backward.png rename to code/studio/src/plugins/object_viewer/images/skip-backward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-forward.png b/code/studio/src/plugins/object_viewer/images/skip-forward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-forward.png rename to code/studio/src/plugins/object_viewer/images/skip-forward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/sound.png b/code/studio/src/plugins/object_viewer/images/sound.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/sound.png rename to code/studio/src/plugins/object_viewer/images/sound.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/stop.png b/code/studio/src/plugins/object_viewer/images/stop.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/stop.png rename to code/studio/src/plugins/object_viewer/images/stop.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/water.png b/code/studio/src/plugins/object_viewer/images/water.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/water.png rename to code/studio/src/plugins/object_viewer/images/water.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/wind.png b/code/studio/src/plugins/object_viewer/images/wind.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/wind.png rename to code/studio/src/plugins/object_viewer/images/wind.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp rename to code/studio/src/plugins/object_viewer/main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.h b/code/studio/src/plugins/object_viewer/main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.h rename to code/studio/src/plugins/object_viewer/main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.cpp b/code/studio/src/plugins/object_viewer/modules.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.cpp rename to code/studio/src/plugins/object_viewer/modules.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.h b/code/studio/src/plugins/object_viewer/modules.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.h rename to code/studio/src/plugins/object_viewer/modules.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.cpp b/code/studio/src/plugins/object_viewer/object_viewer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.cpp rename to code/studio/src/plugins/object_viewer/object_viewer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.h b/code/studio/src/plugins/object_viewer/object_viewer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.h rename to code/studio/src/plugins/object_viewer/object_viewer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.qrc b/code/studio/src/plugins/object_viewer/object_viewer.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.qrc rename to code/studio/src/plugins/object_viewer/object_viewer.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_constants.h b/code/studio/src/plugins/object_viewer/object_viewer_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_constants.h rename to code/studio/src/plugins/object_viewer/object_viewer_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.cpp b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.cpp rename to code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.h b/code/studio/src/plugins/object_viewer/object_viewer_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.h rename to code/studio/src/plugins/object_viewer/object_viewer_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml b/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml rename to code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_form.ui b/code/studio/src/plugins/object_viewer/particle_system/attrib_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/attrib_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/attrib_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/attrib_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.h b/code/studio/src/plugins/object_viewer/particle_system/attrib_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/attrib_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_form.ui b/code/studio/src/plugins/object_viewer/particle_system/auto_lod_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/auto_lod_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_form.ui b/code/studio/src/plugins/object_viewer/particle_system/basic_edit_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/basic_edit_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.h b/code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui b/code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h b/code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/curve_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/curve_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/curve_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/curve_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_form.ui b/code/studio/src/plugins/object_viewer/particle_system/curve_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/curve_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_form.ui b/code/studio/src/plugins/object_viewer/particle_system/direction_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/direction_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/direction_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/direction_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.h b/code/studio/src/plugins/object_viewer/particle_system/direction_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/direction_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.cpp b/code/studio/src/plugins/object_viewer/particle_system/dup_ps.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.cpp rename to code/studio/src/plugins/object_viewer/particle_system/dup_ps.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.h b/code/studio/src/plugins/object_viewer/particle_system/dup_ps.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.h rename to code/studio/src/plugins/object_viewer/particle_system/dup_ps.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_form.ui b/code/studio/src/plugins/object_viewer/particle_system/emitter_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/emitter_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/emitter_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/emitter_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.h b/code/studio/src/plugins/object_viewer/particle_system/emitter_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.h rename to code/studio/src/plugins/object_viewer/particle_system/emitter_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_form.ui b/code/studio/src/plugins/object_viewer/particle_system/located_bindable_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/located_bindable_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.h b/code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.h rename to code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_form.ui b/code/studio/src/plugins/object_viewer/particle_system/located_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/located_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/located_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/located_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.h b/code/studio/src/plugins/object_viewer/particle_system/located_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.h rename to code/studio/src/plugins/object_viewer/particle_system/located_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_form.ui b/code/studio/src/plugins/object_viewer/particle_system/mesh_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/mesh_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/mesh_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/mesh_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.h b/code/studio/src/plugins/object_viewer/particle_system/mesh_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/mesh_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_form.ui b/code/studio/src/plugins/object_viewer/particle_system/morph_mesh_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/morph_mesh_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_form.ui b/code/studio/src/plugins/object_viewer/particle_system/multi_tex_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/multi_tex_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_control_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_control_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.h b/code/studio/src/plugins/object_viewer/particle_system/particle_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_force_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_force_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_force_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_force_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_force_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_force_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_light_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_light_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_light_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_light_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_light_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_light_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.h b/code/studio/src/plugins/object_viewer/particle_system/particle_node.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_node.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_sound_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_sound_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_system_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_system_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_system_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_system_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_system_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_system_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.h b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.h b/code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_zone_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_zone_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp b/code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp rename to code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.h b/code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.h rename to code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_form.ui b/code/studio/src/plugins/object_viewer/particle_system/ps_mover_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/ps_mover_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.h b/code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.h rename to code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_wrapper.h b/code/studio/src/plugins/object_viewer/particle_system/ps_wrapper.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_wrapper.h rename to code/studio/src/plugins/object_viewer/particle_system/ps_wrapper.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_form.ui b/code/studio/src/plugins/object_viewer/particle_system/scheme_bank_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/scheme_bank_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.cpp b/code/studio/src/plugins/object_viewer/particle_system/scheme_manager.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.cpp rename to code/studio/src/plugins/object_viewer/particle_system/scheme_manager.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.h b/code/studio/src/plugins/object_viewer/particle_system/scheme_manager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.h rename to code/studio/src/plugins/object_viewer/particle_system/scheme_manager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_form.ui b/code/studio/src/plugins/object_viewer/particle_system/tail_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/tail_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.h b/code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_form.ui b/code/studio/src/plugins/object_viewer/particle_system/value_gradient_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/value_gradient_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/workspace_form.ui b/code/studio/src/plugins/object_viewer/particle_system/workspace_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/workspace_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/workspace_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/animation_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/animation_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.h b/code/studio/src/plugins/object_viewer/scene/animation_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.h rename to code/studio/src/plugins/object_viewer/scene/animation_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_form.ui b/code/studio/src/plugins/object_viewer/scene/animation_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_form.ui rename to code/studio/src/plugins/object_viewer/scene/animation_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/animation_set_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/animation_set_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.h b/code/studio/src/plugins/object_viewer/scene/animation_set_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.h rename to code/studio/src/plugins/object_viewer/scene/animation_set_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_form.ui b/code/studio/src/plugins/object_viewer/scene/animation_set_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_form.ui rename to code/studio/src/plugins/object_viewer/scene/animation_set_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.cpp b/code/studio/src/plugins/object_viewer/scene/camera_control.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.cpp rename to code/studio/src/plugins/object_viewer/scene/camera_control.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.h b/code/studio/src/plugins/object_viewer/scene/camera_control.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.h rename to code/studio/src/plugins/object_viewer/scene/camera_control.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/day_night_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/day_night_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.h b/code/studio/src/plugins/object_viewer/scene/day_night_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.h rename to code/studio/src/plugins/object_viewer/scene/day_night_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_form.ui b/code/studio/src/plugins/object_viewer/scene/day_night_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_form.ui rename to code/studio/src/plugins/object_viewer/scene/day_night_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.cpp b/code/studio/src/plugins/object_viewer/scene/entity.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.cpp rename to code/studio/src/plugins/object_viewer/scene/entity.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.h b/code/studio/src/plugins/object_viewer/scene/entity.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.h rename to code/studio/src/plugins/object_viewer/scene/entity.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/global_wind_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/global_wind_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.h b/code/studio/src/plugins/object_viewer/scene/global_wind_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.h rename to code/studio/src/plugins/object_viewer/scene/global_wind_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_form.ui b/code/studio/src/plugins/object_viewer/scene/global_wind_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_form.ui rename to code/studio/src/plugins/object_viewer/scene/global_wind_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.h b/code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.h rename to code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_form.ui b/code/studio/src/plugins/object_viewer/scene/setup_fog_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_form.ui rename to code/studio/src/plugins/object_viewer/scene/setup_fog_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.h b/code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.h rename to code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_form.ui b/code/studio/src/plugins/object_viewer/scene/skeleton_scale_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_form.ui rename to code/studio/src/plugins/object_viewer/scene/skeleton_scale_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.cpp b/code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.cpp rename to code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.h b/code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.h rename to code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_form.ui b/code/studio/src/plugins/object_viewer/scene/slot_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_form.ui rename to code/studio/src/plugins/object_viewer/scene/slot_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.h b/code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.h rename to code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/sun_color_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/sun_color_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.h b/code/studio/src/plugins/object_viewer/scene/sun_color_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.h rename to code/studio/src/plugins/object_viewer/scene/sun_color_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_form.ui b/code/studio/src/plugins/object_viewer/scene/sun_color_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_form.ui rename to code/studio/src/plugins/object_viewer/scene/sun_color_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.h b/code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.h rename to code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_form.ui b/code/studio/src/plugins/object_viewer/scene/tune_mrm_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_form.ui rename to code/studio/src/plugins/object_viewer/scene/tune_mrm_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.h b/code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.h rename to code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_form.ui b/code/studio/src/plugins/object_viewer/scene/tune_timer_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_form.ui rename to code/studio/src/plugins/object_viewer/scene/tune_timer_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/water_pool_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/water_pool_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.h b/code/studio/src/plugins/object_viewer/scene/water_pool_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.h rename to code/studio/src/plugins/object_viewer/scene/water_pool_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_form.ui b/code/studio/src/plugins/object_viewer/scene/water_pool_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_form.ui rename to code/studio/src/plugins/object_viewer/scene/water_pool_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.cpp b/code/studio/src/plugins/object_viewer/sound_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.cpp rename to code/studio/src/plugins/object_viewer/sound_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.h b/code/studio/src/plugins/object_viewer/sound_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.h rename to code/studio/src/plugins/object_viewer/sound_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.ui b/code/studio/src/plugins/object_viewer/sound_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.ui rename to code/studio/src/plugins/object_viewer/sound_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.cpp b/code/studio/src/plugins/object_viewer/sound_system.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.cpp rename to code/studio/src/plugins/object_viewer/sound_system.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.h b/code/studio/src/plugins/object_viewer/sound_system.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.h rename to code/studio/src/plugins/object_viewer/sound_system.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.cpp b/code/studio/src/plugins/object_viewer/stdpch.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.cpp rename to code/studio/src/plugins/object_viewer/stdpch.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.h b/code/studio/src/plugins/object_viewer/stdpch.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.h rename to code/studio/src/plugins/object_viewer/stdpch.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_density_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_density_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_node.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_node.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_node.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_node.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.cpp b/code/studio/src/plugins/object_viewer/vegetable_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.h b/code/studio/src/plugins/object_viewer/vegetable_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.h rename to code/studio/src/plugins/object_viewer/vegetable_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.ui b/code/studio/src/plugins/object_viewer/vegetable_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.ui rename to code/studio/src/plugins/object_viewer/vegetable_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_form.ui b/code/studio/src/plugins/object_viewer/widgets/color_edit_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_form.ui rename to code/studio/src/plugins/object_viewer/widgets/color_edit_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.cpp b/code/studio/src/plugins/object_viewer/widgets/color_edit_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.cpp rename to code/studio/src/plugins/object_viewer/widgets/color_edit_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.h b/code/studio/src/plugins/object_viewer/widgets/color_edit_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.h rename to code/studio/src/plugins/object_viewer/widgets/color_edit_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_float_form.ui b/code/studio/src/plugins/object_viewer/widgets/edit_range_float_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_float_form.ui rename to code/studio/src/plugins/object_viewer/widgets/edit_range_float_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_uint_form.ui b/code/studio/src/plugins/object_viewer/widgets/edit_range_uint_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_uint_form.ui rename to code/studio/src/plugins/object_viewer/widgets/edit_range_uint_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.cpp b/code/studio/src/plugins/object_viewer/widgets/edit_range_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.cpp rename to code/studio/src/plugins/object_viewer/widgets/edit_range_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.h b/code/studio/src/plugins/object_viewer/widgets/edit_range_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.h rename to code/studio/src/plugins/object_viewer/widgets/edit_range_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.cpp b/code/studio/src/plugins/object_viewer/widgets/hoverpoints.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.cpp rename to code/studio/src/plugins/object_viewer/widgets/hoverpoints.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.h b/code/studio/src/plugins/object_viewer/widgets/hoverpoints.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.h rename to code/studio/src/plugins/object_viewer/widgets/hoverpoints.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt rename to code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilder.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilder.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt rename to code/studio/src/plugins/tile_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png b/code/studio/src/plugins/tile_editor/images/add_tile.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png rename to code/studio/src/plugins/tile_editor/images/add_tile.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_image.png b/code/studio/src/plugins/tile_editor/images/delete_image.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_image.png rename to code/studio/src/plugins/tile_editor/images/delete_image.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_tile.png b/code/studio/src/plugins/tile_editor/images/delete_tile.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_tile.png rename to code/studio/src/plugins/tile_editor/images/delete_tile.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png b/code/studio/src/plugins/tile_editor/images/down.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png rename to code/studio/src/plugins/tile_editor/images/down.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png b/code/studio/src/plugins/tile_editor/images/empty_image.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png rename to code/studio/src/plugins/tile_editor/images/empty_image.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_add_item.png b/code/studio/src/plugins/tile_editor/images/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_add_item.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_delete_item.png b/code/studio/src/plugins/tile_editor/images/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_delete_item.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png b/code/studio/src/plugins/tile_editor/images/ic_nel_new.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_new.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_open.png b/code/studio/src/plugins/tile_editor/images/ic_nel_open.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_open.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_open.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save.png b/code/studio/src/plugins/tile_editor/images/ic_nel_save.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_save.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save_as.png b/code/studio/src/plugins/tile_editor/images/ic_nel_save_as.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save_as.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_save_as.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/left.png b/code/studio/src/plugins/tile_editor/images/left.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/left.png rename to code/studio/src/plugins/tile_editor/images/left.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/nel.png b/code/studio/src/plugins/tile_editor/images/nel.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/nel.png rename to code/studio/src/plugins/tile_editor/images/nel.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png b/code/studio/src/plugins/tile_editor/images/replace_image.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png rename to code/studio/src/plugins/tile_editor/images/replace_image.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png b/code/studio/src/plugins/tile_editor/images/reset.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png rename to code/studio/src/plugins/tile_editor/images/reset.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png b/code/studio/src/plugins/tile_editor/images/right.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png rename to code/studio/src/plugins/tile_editor/images/right.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation0.png b/code/studio/src/plugins/tile_editor/images/rotation0.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation0.png rename to code/studio/src/plugins/tile_editor/images/rotation0.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png b/code/studio/src/plugins/tile_editor/images/rotation180.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png rename to code/studio/src/plugins/tile_editor/images/rotation180.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation270.png b/code/studio/src/plugins/tile_editor/images/rotation270.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation270.png rename to code/studio/src/plugins/tile_editor/images/rotation270.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation90.png b/code/studio/src/plugins/tile_editor/images/rotation90.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation90.png rename to code/studio/src/plugins/tile_editor/images/rotation90.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/up.png b/code/studio/src/plugins/tile_editor/images/up.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/up.png rename to code/studio/src/plugins/tile_editor/images/up.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml rename to code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc b/code/studio/src/plugins/tile_editor/tile_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc rename to code/studio/src/plugins/tile_editor/tile_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp rename to code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h rename to code/studio/src/plugins/tile_editor/tile_editor_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui rename to code/studio/src/plugins/tile_editor/tile_editor_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp rename to code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h rename to code/studio/src/plugins/tile_editor/tile_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp rename to code/studio/src/plugins/tile_editor/tile_item.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h rename to code/studio/src/plugins/tile_editor/tile_item.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp b/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp rename to code/studio/src/plugins/tile_editor/tile_item_delegate.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/studio/src/plugins/tile_editor/tile_item_delegate.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h rename to code/studio/src/plugins/tile_editor/tile_item_delegate.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp rename to code/studio/src/plugins/tile_editor/tile_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h rename to code/studio/src/plugins/tile_editor/tile_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt rename to code/studio/src/plugins/translation_manager/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/README b/code/studio/src/plugins/translation_manager/README similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/README rename to code/studio/src/plugins/translation_manager/README diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp b/code/studio/src/plugins/translation_manager/editor_phrase.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp rename to code/studio/src/plugins/translation_manager/editor_phrase.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h b/code/studio/src/plugins/translation_manager/editor_phrase.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h rename to code/studio/src/plugins/translation_manager/editor_phrase.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp b/code/studio/src/plugins/translation_manager/editor_worksheet.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp rename to code/studio/src/plugins/translation_manager/editor_worksheet.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h b/code/studio/src/plugins/translation_manager/editor_worksheet.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h rename to code/studio/src/plugins/translation_manager/editor_worksheet.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp b/code/studio/src/plugins/translation_manager/extract_bot_names.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp rename to code/studio/src/plugins/translation_manager/extract_bot_names.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h b/code/studio/src/plugins/translation_manager/extract_bot_names.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h rename to code/studio/src/plugins/translation_manager/extract_bot_names.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp b/code/studio/src/plugins/translation_manager/extract_new_sheet_names.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp rename to code/studio/src/plugins/translation_manager/extract_new_sheet_names.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h b/code/studio/src/plugins/translation_manager/extract_new_sheet_names.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h rename to code/studio/src/plugins/translation_manager/extract_new_sheet_names.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp b/code/studio/src/plugins/translation_manager/ftp_selection.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp rename to code/studio/src/plugins/translation_manager/ftp_selection.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h b/code/studio/src/plugins/translation_manager/ftp_selection.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h rename to code/studio/src/plugins/translation_manager/ftp_selection.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.qrc b/code/studio/src/plugins/translation_manager/ftp_selection.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.qrc rename to code/studio/src/plugins/translation_manager/ftp_selection.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.ui b/code/studio/src/plugins/translation_manager/ftp_selection.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.ui rename to code/studio/src/plugins/translation_manager/ftp_selection.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/cdtoparent.png b/code/studio/src/plugins/translation_manager/images/cdtoparent.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/cdtoparent.png rename to code/studio/src/plugins/translation_manager/images/cdtoparent.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/dir.png b/code/studio/src/plugins/translation_manager/images/dir.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/dir.png rename to code/studio/src/plugins/translation_manager/images/dir.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/file.png b/code/studio/src/plugins/translation_manager/images/file.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/file.png rename to code/studio/src/plugins/translation_manager/images/file.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml b/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml rename to code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp b/code/studio/src/plugins/translation_manager/source_selection.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp rename to code/studio/src/plugins/translation_manager/source_selection.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h b/code/studio/src/plugins/translation_manager/source_selection.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h rename to code/studio/src/plugins/translation_manager/source_selection.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.ui b/code/studio/src/plugins/translation_manager/source_selection.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.ui rename to code/studio/src/plugins/translation_manager/source_selection.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h b/code/studio/src/plugins/translation_manager/translation_manager_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h rename to code/studio/src/plugins/translation_manager/translation_manager_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h b/code/studio/src/plugins/translation_manager/translation_manager_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h rename to code/studio/src/plugins/translation_manager/translation_manager_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp rename to code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h rename to code/studio/src/plugins/translation_manager/translation_manager_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.ui b/code/studio/src/plugins/translation_manager/translation_manager_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.ui rename to code/studio/src/plugins/translation_manager/translation_manager_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp b/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp rename to code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h b/code/studio/src/plugins/translation_manager/translation_manager_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h rename to code/studio/src/plugins/translation_manager/translation_manager_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp b/code/studio/src/plugins/translation_manager/translation_manager_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp rename to code/studio/src/plugins/translation_manager/translation_manager_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h b/code/studio/src/plugins/translation_manager/translation_manager_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h rename to code/studio/src/plugins/translation_manager/translation_manager_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui b/code/studio/src/plugins/translation_manager/translation_manager_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui rename to code/studio/src/plugins/translation_manager/translation_manager_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt rename to code/studio/src/plugins/world_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_move.png b/code/studio/src/plugins/world_editor/icons/ic_nel_move.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_move.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_move.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_rotate.png b/code/studio/src/plugins/world_editor/icons/ic_nel_rotate.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_rotate.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_rotate.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_scale.png b/code/studio/src/plugins/world_editor/icons/ic_nel_scale.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_scale.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_scale.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_select.png b/code/studio/src/plugins/world_editor/icons/ic_nel_select.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_select.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_select.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_turn.png b/code/studio/src/plugins/world_editor/icons/ic_nel_turn.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_turn.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_turn.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_world_editor.png b/code/studio/src/plugins/world_editor/icons/ic_nel_world_editor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_world_editor.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_world_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml rename to code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp b/code/studio/src/plugins/world_editor/primitive_item.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp rename to code/studio/src/plugins/world_editor/primitive_item.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h b/code/studio/src/plugins/world_editor/primitive_item.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h rename to code/studio/src/plugins/world_editor/primitive_item.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp b/code/studio/src/plugins/world_editor/primitives_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp rename to code/studio/src/plugins/world_editor/primitives_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h b/code/studio/src/plugins/world_editor/primitives_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h rename to code/studio/src/plugins/world_editor/primitives_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp b/code/studio/src/plugins/world_editor/primitives_view.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp rename to code/studio/src/plugins/world_editor/primitives_view.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h b/code/studio/src/plugins/world_editor/primitives_view.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h rename to code/studio/src/plugins/world_editor/primitives_view.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp b/code/studio/src/plugins/world_editor/project_settings_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp rename to code/studio/src/plugins/world_editor/project_settings_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.h b/code/studio/src/plugins/world_editor/project_settings_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.h rename to code/studio/src/plugins/world_editor/project_settings_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.ui b/code/studio/src/plugins/world_editor/project_settings_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.ui rename to code/studio/src/plugins/world_editor/project_settings_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.cpp rename to code/studio/src/plugins/world_editor/property_editor_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.h rename to code/studio/src/plugins/world_editor/property_editor_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.ui b/code/studio/src/plugins/world_editor/property_editor_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.ui rename to code/studio/src/plugins/world_editor/property_editor_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor.qrc b/code/studio/src/plugins/world_editor/world_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor.qrc rename to code/studio/src/plugins/world_editor/world_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp b/code/studio/src/plugins/world_editor/world_editor_actions.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp rename to code/studio/src/plugins/world_editor/world_editor_actions.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.h b/code/studio/src/plugins/world_editor/world_editor_actions.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.h rename to code/studio/src/plugins/world_editor/world_editor_actions.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_constants.h b/code/studio/src/plugins/world_editor/world_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_constants.h rename to code/studio/src/plugins/world_editor/world_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_global.h b/code/studio/src/plugins/world_editor/world_editor_global.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_global.h rename to code/studio/src/plugins/world_editor/world_editor_global.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp b/code/studio/src/plugins/world_editor/world_editor_misc.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp rename to code/studio/src/plugins/world_editor/world_editor_misc.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h b/code/studio/src/plugins/world_editor/world_editor_misc.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h rename to code/studio/src/plugins/world_editor/world_editor_misc.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp b/code/studio/src/plugins/world_editor/world_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp rename to code/studio/src/plugins/world_editor/world_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.h b/code/studio/src/plugins/world_editor/world_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.h rename to code/studio/src/plugins/world_editor/world_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp b/code/studio/src/plugins/world_editor/world_editor_scene.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp rename to code/studio/src/plugins/world_editor/world_editor_scene.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.h b/code/studio/src/plugins/world_editor/world_editor_scene.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.h rename to code/studio/src/plugins/world_editor/world_editor_scene.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp b/code/studio/src/plugins/world_editor/world_editor_scene_item.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp rename to code/studio/src/plugins/world_editor/world_editor_scene_item.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.h b/code/studio/src/plugins/world_editor/world_editor_scene_item.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.h rename to code/studio/src/plugins/world_editor/world_editor_scene_item.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp b/code/studio/src/plugins/world_editor/world_editor_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp rename to code/studio/src/plugins/world_editor/world_editor_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.h b/code/studio/src/plugins/world_editor/world_editor_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.h rename to code/studio/src/plugins/world_editor/world_editor_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.ui b/code/studio/src/plugins/world_editor/world_editor_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.ui rename to code/studio/src/plugins/world_editor/world_editor_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp rename to code/studio/src/plugins/world_editor/world_editor_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h b/code/studio/src/plugins/world_editor/world_editor_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h rename to code/studio/src/plugins/world_editor/world_editor_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui b/code/studio/src/plugins/world_editor/world_editor_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui rename to code/studio/src/plugins/world_editor/world_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/CMakeLists.txt b/code/studio/src/plugins/zone_painter/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/CMakeLists.txt rename to code/studio/src/plugins/zone_painter/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-fill.png b/code/studio/src/plugins/zone_painter/images/color-fill.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-fill.png rename to code/studio/src/plugins/zone_painter/images/color-fill.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-picker-black.png b/code/studio/src/plugins/zone_painter/images/color-picker-black.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-picker-black.png rename to code/studio/src/plugins/zone_painter/images/color-picker-black.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/colorize.png b/code/studio/src/plugins/zone_painter/images/colorize.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/colorize.png rename to code/studio/src/plugins/zone_painter/images/colorize.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/draw-brush.png b/code/studio/src/plugins/zone_painter/images/draw-brush.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/draw-brush.png rename to code/studio/src/plugins/zone_painter/images/draw-brush.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-down-7.png b/code/studio/src/plugins/zone_painter/images/go-down-7.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-down-7.png rename to code/studio/src/plugins/zone_painter/images/go-down-7.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-jump-4.png b/code/studio/src/plugins/zone_painter/images/go-jump-4.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-jump-4.png rename to code/studio/src/plugins/zone_painter/images/go-jump-4.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-6.png b/code/studio/src/plugins/zone_painter/images/lock-6.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-6.png rename to code/studio/src/plugins/zone_painter/images/lock-6.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-silver.png b/code/studio/src/plugins/zone_painter/images/lock-silver.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-silver.png rename to code/studio/src/plugins/zone_painter/images/lock-silver.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml b/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml rename to code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.cpp b/code/studio/src/plugins/zone_painter/painter_dock_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.cpp rename to code/studio/src/plugins/zone_painter/painter_dock_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.h b/code/studio/src/plugins/zone_painter/painter_dock_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.h rename to code/studio/src/plugins/zone_painter/painter_dock_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.ui b/code/studio/src/plugins/zone_painter/painter_dock_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.ui rename to code/studio/src/plugins/zone_painter/painter_dock_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.cpp b/code/studio/src/plugins/zone_painter/qnel_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.cpp rename to code/studio/src/plugins/zone_painter/qnel_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.h b/code/studio/src/plugins/zone_painter/qnel_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.h rename to code/studio/src/plugins/zone_painter/qnel_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter.qrc b/code/studio/src/plugins/zone_painter/zone_painter.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter.qrc rename to code/studio/src/plugins/zone_painter/zone_painter.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.cpp b/code/studio/src/plugins/zone_painter/zone_painter_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.h b/code/studio/src/plugins/zone_painter/zone_painter_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.h rename to code/studio/src/plugins/zone_painter/zone_painter_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.ui b/code/studio/src/plugins/zone_painter/zone_painter_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.ui rename to code/studio/src/plugins/zone_painter/zone_painter_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp b/code/studio/src/plugins/zone_painter/zone_painter_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h b/code/studio/src/plugins/zone_painter/zone_painter_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h rename to code/studio/src/plugins/zone_painter/zone_painter_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp b/code/studio/src/plugins/zone_painter/zone_painter_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h b/code/studio/src/plugins/zone_painter/zone_painter_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h rename to code/studio/src/plugins/zone_painter/zone_painter_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.cpp b/code/studio/src/plugins/zone_painter/zone_painter_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.h b/code/studio/src/plugins/zone_painter/zone_painter_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.h rename to code/studio/src/plugins/zone_painter/zone_painter_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.ui b/code/studio/src/plugins/zone_painter/zone_painter_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.ui rename to code/studio/src/plugins/zone_painter/zone_painter_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_de.ts b/code/studio/src/translations/object_viewer_qt_de.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_de.ts rename to code/studio/src/translations/object_viewer_qt_de.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_en.ts b/code/studio/src/translations/object_viewer_qt_en.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_en.ts rename to code/studio/src/translations/object_viewer_qt_en.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_fr.ts b/code/studio/src/translations/object_viewer_qt_fr.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_fr.ts rename to code/studio/src/translations/object_viewer_qt_fr.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_ru.ts b/code/studio/src/translations/object_viewer_qt_ru.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_ru.ts rename to code/studio/src/translations/object_viewer_qt_ru.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/translations.qrc b/code/studio/src/translations/translations.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/translations.qrc rename to code/studio/src/translations/translations.qrc From 3c725986457eb147f0e2b8d38c32a5aadcc139a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 7 May 2014 00:50:57 +0200 Subject: [PATCH 021/282] Readding core plugin that was missing because of a hgignore entry. --HG-- branch : gsoc2014-dfighter --- .hgignore | 2 +- code/studio/src/plugins/core/CMakeLists.txt | 73 +++ .../src/plugins/core/context_manager.cpp | 167 ++++++ .../studio/src/plugins/core/context_manager.h | 76 +++ code/studio/src/plugins/core/core_constants.h | 121 +++++ code/studio/src/plugins/core/core_global.h | 30 ++ code/studio/src/plugins/core/core_plugin.cpp | 104 ++++ code/studio/src/plugins/core/core_plugin.h | 74 +++ .../plugins/core/general_settings_page.cpp | 241 +++++++++ .../src/plugins/core/general_settings_page.h | 74 +++ .../src/plugins/core/general_settings_page.ui | 233 +++++++++ .../plugins/core/icons/ic_nel_add_item.png | Bin 0 -> 3270 bytes .../src/plugins/core/icons/ic_nel_crash.png | Bin 0 -> 6630 bytes .../plugins/core/icons/ic_nel_delete_item.png | Bin 0 -> 1496 bytes .../plugins/core/icons/ic_nel_down_item.png | Bin 0 -> 3812 bytes .../core/icons/ic_nel_generic_settings.png | Bin 0 -> 5633 bytes .../src/plugins/core/icons/ic_nel_new.png | Bin 0 -> 21396 bytes .../src/plugins/core/icons/ic_nel_open.png | Bin 0 -> 4310 bytes .../core/icons/ic_nel_path_settings.png | Bin 0 -> 4557 bytes .../src/plugins/core/icons/ic_nel_pill.png | Bin 0 -> 9291 bytes .../src/plugins/core/icons/ic_nel_redo.png | Bin 0 -> 4694 bytes .../plugins/core/icons/ic_nel_reset_all.png | Bin 0 -> 5938 bytes .../src/plugins/core/icons/ic_nel_save.png | Bin 0 -> 43738 bytes .../src/plugins/core/icons/ic_nel_save_as.png | Bin 0 -> 52871 bytes .../src/plugins/core/icons/ic_nel_undo.png | Bin 0 -> 4714 bytes .../src/plugins/core/icons/ic_nel_up_item.png | Bin 0 -> 3304 bytes code/studio/src/plugins/core/icontext.h | 76 +++ code/studio/src/plugins/core/icore.h | 70 +++ code/studio/src/plugins/core/icore_listener.h | 63 +++ code/studio/src/plugins/core/images/nel.png | Bin 0 -> 15587 bytes .../src/plugins/core/images/preferences.png | Bin 0 -> 10286 bytes code/studio/src/plugins/core/ioptions_page.h | 75 +++ code/studio/src/plugins/core/main_window.cpp | 492 ++++++++++++++++++ code/studio/src/plugins/core/main_window.h | 147 ++++++ code/studio/src/plugins/core/menu_manager.cpp | 96 ++++ code/studio/src/plugins/core/menu_manager.h | 67 +++ .../src/plugins/core/ovqt_plugin_core.xml | 7 + .../src/plugins/core/plugin_view_dialog.cpp | 108 ++++ .../src/plugins/core/plugin_view_dialog.h | 58 +++ .../src/plugins/core/plugin_view_dialog.ui | 135 +++++ code/studio/src/plugins/core/qtwin.cpp | 241 +++++++++ code/studio/src/plugins/core/qtwin.h | 37 ++ .../core/search_paths_settings_page.cpp | 219 ++++++++ .../plugins/core/search_paths_settings_page.h | 74 +++ .../core/search_paths_settings_page.ui | 198 +++++++ .../src/plugins/core/settings_dialog.cpp | 182 +++++++ .../studio/src/plugins/core/settings_dialog.h | 75 +++ .../src/plugins/core/settings_dialog.ui | 126 +++++ 48 files changed, 3740 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/core/CMakeLists.txt create mode 100644 code/studio/src/plugins/core/context_manager.cpp create mode 100644 code/studio/src/plugins/core/context_manager.h create mode 100644 code/studio/src/plugins/core/core_constants.h create mode 100644 code/studio/src/plugins/core/core_global.h create mode 100644 code/studio/src/plugins/core/core_plugin.cpp create mode 100644 code/studio/src/plugins/core/core_plugin.h create mode 100644 code/studio/src/plugins/core/general_settings_page.cpp create mode 100644 code/studio/src/plugins/core/general_settings_page.h create mode 100644 code/studio/src/plugins/core/general_settings_page.ui create mode 100644 code/studio/src/plugins/core/icons/ic_nel_add_item.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_crash.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_delete_item.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_down_item.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_generic_settings.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_new.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_open.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_path_settings.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_pill.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_redo.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_reset_all.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_save.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_save_as.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_undo.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_up_item.png create mode 100644 code/studio/src/plugins/core/icontext.h create mode 100644 code/studio/src/plugins/core/icore.h create mode 100644 code/studio/src/plugins/core/icore_listener.h create mode 100644 code/studio/src/plugins/core/images/nel.png create mode 100644 code/studio/src/plugins/core/images/preferences.png create mode 100644 code/studio/src/plugins/core/ioptions_page.h create mode 100644 code/studio/src/plugins/core/main_window.cpp create mode 100644 code/studio/src/plugins/core/main_window.h create mode 100644 code/studio/src/plugins/core/menu_manager.cpp create mode 100644 code/studio/src/plugins/core/menu_manager.h create mode 100644 code/studio/src/plugins/core/ovqt_plugin_core.xml create mode 100644 code/studio/src/plugins/core/plugin_view_dialog.cpp create mode 100644 code/studio/src/plugins/core/plugin_view_dialog.h create mode 100644 code/studio/src/plugins/core/plugin_view_dialog.ui create mode 100644 code/studio/src/plugins/core/qtwin.cpp create mode 100644 code/studio/src/plugins/core/qtwin.h create mode 100644 code/studio/src/plugins/core/search_paths_settings_page.cpp create mode 100644 code/studio/src/plugins/core/search_paths_settings_page.h create mode 100644 code/studio/src/plugins/core/search_paths_settings_page.ui create mode 100644 code/studio/src/plugins/core/settings_dialog.cpp create mode 100644 code/studio/src/plugins/core/settings_dialog.h create mode 100644 code/studio/src/plugins/core/settings_dialog.ui diff --git a/.hgignore b/.hgignore index 530c92512..5587652fd 100644 --- a/.hgignore +++ b/.hgignore @@ -43,7 +43,7 @@ default_c *.so *.so.* *_debug -core +core.* *.pc *.gch diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt new file mode 100644 index 000000000..5a20ba46c --- /dev/null +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -0,0 +1,73 @@ +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_CORE_PLUGIN_HDR + icore.h + icontext.h + icore_listener.h + ioptions_page.h + core_plugin.h + core.h + main_window.h + menu_manager.h + context_manager.h + settings_dialog.h + search_paths_settings_page.h + general_settings_page.h + plugin_view_dialog.h +) + +SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui + plugin_view_dialog.ui + general_settings_page.ui + search_paths_settings_page.ui +) + +SET(OVQT_CORE_PLUGIN_RCS core.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_ADD_RESOURCES(OVQT_CORE_PLUGIN_RC_SRCS ${OVQT_CORE_PLUGIN_RCS}) +QT4_WRAP_CPP(OVQT_CORE_PLUGIN_MOC_SRC ${OVQT_CORE_PLUGIN_HDR}) +QT4_WRAP_UI(OVQT_CORE_PLUGIN_UI_HDRS ${OVQT_CORE_PLUGIN_UIS}) + +SOURCE_GROUP(QtResources FILES ${OVQT_CORE_PLUGIN_UIS} ${OVQT_CORE_PLUGIN_RCS}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_CORE_PLUGIN_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) +SOURCE_GROUP("Core Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) + +NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) +NL_ADD_LIB_SUFFIX(ovqt_plugin_core) + +ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +IF(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ELSE(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ENDIF(WIN32) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) + diff --git a/code/studio/src/plugins/core/context_manager.cpp b/code/studio/src/plugins/core/context_manager.cpp new file mode 100644 index 000000000..8355b5cb8 --- /dev/null +++ b/code/studio/src/plugins/core/context_manager.cpp @@ -0,0 +1,167 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "context_manager.h" +#include "icontext.h" +#include "main_window.h" + +// NeL includes +#include + +// Qt includes +#include +#include + +namespace Core +{ + +struct ContextManagerPrivate +{ + explicit ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget); + Core::MainWindow *m_mainWindow; + QTabWidget *m_tabWidget; + QVector m_contexts; + int m_oldCurrent; +}; + +ContextManagerPrivate::ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget) + : m_mainWindow(mainWindow), + m_tabWidget(tabWidget), + m_oldCurrent(-1) +{ +} + +ContextManager::ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget) + : d(new ContextManagerPrivate(mainWindow, tabWidget)) +{ + QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(objectAdded(QObject *)), + this, SLOT(objectAdded(QObject *))); + QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(aboutToRemoveObject(QObject *)), + this, SLOT(aboutToRemoveObject(QObject *))); + + QObject::connect(d->m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); +} + +ContextManager::~ContextManager() +{ + delete d; +} + +Core::IContext *ContextManager::currentContext() const +{ + int currentIndex = d->m_tabWidget->currentIndex(); + if (currentIndex < 0) + return 0; + return d->m_contexts.at(currentIndex); +} + +Core::IContext *ContextManager::context(const QString &id) const +{ + const int index = indexOf(id); + if (index >= 0) + return d->m_contexts.at(index); + return 0; +} + +void ContextManager::registerUndoStack(QUndoStack *stack) +{ + nlassert(stack); + d->m_mainWindow->undoGroup()->addStack(stack); +} + +void ContextManager::unregisterUndoStack(QUndoStack *stack) +{ + nlassert(stack); + d->m_mainWindow->undoGroup()->removeStack(stack); +} + +void ContextManager::activateContext(const QString &id) +{ + const int index = indexOf(id); + if (index >= 0) + d->m_tabWidget->setCurrentIndex(index); +} + +void ContextManager::updateCurrentContext() +{ + d->m_mainWindow->updateContext(currentContext()); +} + +void ContextManager::objectAdded(QObject *obj) +{ + IContext *context = qobject_cast(obj); + if (context) + addContextObject(context); +} + +void ContextManager::aboutToRemoveObject(QObject *obj) +{ + IContext *context = qobject_cast(obj); + if (context) + removeContextObject(context); +} + +void ContextManager::addContextObject(IContext *context) +{ + d->m_contexts.push_back(context); + d->m_mainWindow->addContextObject(context); + + QWidget *tabWidget = new QWidget(d->m_tabWidget); + d->m_tabWidget->addTab(tabWidget, context->icon(), context->trName()); + QGridLayout *gridLayout = new QGridLayout(tabWidget); + gridLayout->setObjectName(QString::fromUtf8("gridLayout_") + context->id()); + gridLayout->setContentsMargins(0, 0, 0, 0); + gridLayout->addWidget(context->widget(), 0, 0, 1, 1); +} + +void ContextManager::removeContextObject(IContext *context) +{ + d->m_mainWindow->removeContextObject(context); + + const int index = indexOf(context->id()); + QWidget *widget = d->m_tabWidget->widget(index); + d->m_tabWidget->removeTab(index); + d->m_contexts.remove(index); + delete widget; +} + +void ContextManager::currentTabChanged(int index) +{ + if (index >= 0) + { + IContext *context = d->m_contexts.at(index); + IContext *oldContext = 0; + if (d->m_oldCurrent >= 0) + oldContext = d->m_contexts.at(d->m_oldCurrent); + d->m_oldCurrent = index; + Q_EMIT currentContextChanged(context, oldContext); + } +} + +int ContextManager::indexOf(const QString &id) const +{ + for (int i = 0; i < d->m_contexts.count(); ++i) + { + if (d->m_contexts.at(i)->id() == id) + return i; + } + nlwarning(QString("Warning, no such context: %1").arg(id).toUtf8().constData()); + return -1; +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/context_manager.h b/code/studio/src/plugins/core/context_manager.h new file mode 100644 index 000000000..8151648e7 --- /dev/null +++ b/code/studio/src/plugins/core/context_manager.h @@ -0,0 +1,76 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CONTEXT_MANAGER_H +#define CONTEXT_MANAGER_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include + +QT_BEGIN_NAMESPACE +class QTabWidget; +class QUndoStack; +QT_END_NAMESPACE + +namespace Core +{ +class IContext; +class MainWindow; +struct ContextManagerPrivate; + +class CORE_EXPORT ContextManager : public QObject +{ + Q_OBJECT + +public: + explicit ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget); + virtual ~ContextManager(); + + Core::IContext *currentContext() const; + Core::IContext *context(const QString &id) const; + + // temporary solution for multiple undo stacks per context + void registerUndoStack(QUndoStack *stack); + void unregisterUndoStack(QUndoStack *stack); + +Q_SIGNALS: + // the default argument '=0' is important for connects without the oldContext argument. + void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0); + +public Q_SLOTS: + void activateContext(const QString &id); + void updateCurrentContext(); + +private Q_SLOTS: + void objectAdded(QObject *obj); + void aboutToRemoveObject(QObject *obj); + void addContextObject(IContext *context); + void removeContextObject(IContext *context); + void currentTabChanged(int index); + +private: + int indexOf(const QString &id) const; + + ContextManagerPrivate *d; +}; + +} // namespace Core + +#endif // CONTEXT_MANAGER_H diff --git a/code/studio/src/plugins/core/core_constants.h b/code/studio/src/plugins/core/core_constants.h new file mode 100644 index 000000000..8bf6d5fcd --- /dev/null +++ b/code/studio/src/plugins/core/core_constants.h @@ -0,0 +1,121 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2010 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_CONSTANTS_H +#define CORE_CONSTANTS_H + +namespace Core +{ +namespace Constants +{ + +const char *const OVQT_VERSION_LONG = "0.8"; +const char *const OVQT_VENDOR = "Ryzom Core"; +const char *const OVQT_YEAR = "2010, 2011"; +const char *const OVQT_CORE_PLUGIN = "Core"; + +//mainwindow +const char *const MAIN_WINDOW = "ObjectViewerQt.MainWindow"; + +//menubar +const char *const MENU_BAR = "ObjectViewerQt.MenuBar"; + +//menus +const char *const M_FILE = "ObjectViewerQt.Menu.File"; +const char *const M_EDIT = "ObjectViewerQt.Menu.Edit"; +const char *const M_VIEW = "ObjectViewerQt.Menu.View"; +const char *const M_SCENE = "ObjectViewerQt.Menu.Scene"; +const char *const M_TOOLS = "ObjectViewerQt.Menu.Tools"; +const char *const M_WINDOW = "ObjectViewerQt.Menu.Window"; +const char *const M_HELP = "ObjectViewerQt.Menu.Help"; + +const char *const M_FILE_RECENTFILES = "ObjectViewerQt.Menu.File.RecentFiles"; +const char *const M_SHEET = "ObjectViewerQt.Menu.Sheet"; + +//actions +const char *const NEW = "ObjectViewerQt.New"; +const char *const OPEN = "ObjectViewerQt.Open"; +const char *const SAVE = "ObjectViewerQt.Save"; +const char *const SAVE_AS = "ObjectViewerQt.SaveAs"; +const char *const SAVE_ALL = "ObjectViewerQt.SaveAll"; +const char *const EXIT = "ObjectViewerQt.Exit"; + +const char *const UNDO = "ObjectViewerQt.Undo"; +const char *const REDO = "ObjectViewerQt.Redo"; +const char *const CUT = "ObjectViewerQt.Cut"; +const char *const COPY = "ObjectViewerQt.Copy"; +const char *const PASTE = "ObjectViewerQt.Paste"; +const char *const DEL = "ObjectViewerQt.Del"; +const char *const FIND = "ObjectViewerQt.Find"; +const char *const SELECT_ALL = "ObjectViewerQt.SelectAll"; +const char *const GOTO_POS = "ObjectViewerQt.Goto"; + +const char *const SETTINGS = "ObjectViewerQt.Settings"; +const char *const TOGGLE_FULLSCREEN = "ObjectViewerQt.ToggleFullScreen"; + +const char *const CLOSE = "ObjectViewerQt.Close"; +const char *const CLOSEALL = "ObjectViewerQt.CloseAll"; +const char *const CLOSEOTHERS = "ObjectViewerQt.CloseOthers"; +const char *const ABOUT = "ObjectViewerQt.About"; +const char *const ABOUT_PLUGINS = "ObjectViewerQt.AboutPlugins"; +const char *const ABOUT_QT = "ObjectViewerQt.AboutQt"; + +//settings +const char *const SETTINGS_CATEGORY_GENERAL = "general"; +const char *const SETTINGS_CATEGORY_GENERAL_ICON = ":/icons/ic_nel_generic_settings.png"; +const char *const SETTINGS_TR_CATEGORY_GENERAL = QT_TR_NOOP("General"); + +const char *const MAIN_WINDOW_SECTION = "MainWindow"; +const char *const MAIN_WINDOW_STATE = "WindowState"; +const char *const MAIN_WINDOW_GEOMETRY = "WindowGeometry"; +const char *const QT_STYLE = "QtStyle"; +const char *const QT_PALETTE = "QtPalette"; + +const char *const LANGUAGE = "Language"; +const char *const PLUGINS_PATH = "PluginPath"; +const char *const DATA_PATH_SECTION = "DataPath"; +const char *const SEARCH_PATHS = "SearchPaths"; +const char *const RECURSIVE_SEARCH_PATHS = "RecursiveSearchPathes"; +const char *const LEVELDESIGN_PATH = "LevelDesignPath"; +const char *const PRIMITIVES_PATH = "PrimitivesPath"; +const char *const ASSETS_PATH = "AssetsPath"; +const char *const LIGOCONFIG_FILE = "LigoConfigFile"; +const char *const REMAP_EXTENSIONS = "RemapExtensions"; + +const char *const LOG_SECTION = "LogSettings"; +const char *const LOG_ERROR = "LogError"; +const char *const LOG_WARNING = "LogWarning"; +const char *const LOG_DEBUG = "LogDebug"; +const char *const LOG_ASSERT = "LogAssert"; +const char *const LOG_INFO = "LogInfo"; + +//resources +const char *const ICON_NEL = ":/core/images/nel.png"; +const char *const ICON_SETTINGS = ":/core/images/preferences.png"; +const char *const ICON_PILL = ":/core/icons/ic_nel_pill.png"; +const char *const ICON_OPEN = ":/core/icons/ic_nel_open.png"; +const char *const ICON_NEW = ":/core/icons/ic_nel_new.png"; +const char *const ICON_SAVE = ":/core/icons/ic_nel_save.png"; +const char *const ICON_SAVE_AS = ":/core/icons/ic_nel_save_as.png"; +const char *const ICON_CRASH = ":/core/icons/ic_nel_crash.png"; +const char *const ICON_UNDO = ":/core/icons/ic_nel_undo.png"; +const char *const ICON_REDO = ":/core/icons/ic_nel_redo.png"; + +} // namespace Constants +} // namespace Core + +#endif // CORE_CONSTANTS_H diff --git a/code/studio/src/plugins/core/core_global.h b/code/studio/src/plugins/core/core_global.h new file mode 100644 index 000000000..48fe0ece9 --- /dev/null +++ b/code/studio/src/plugins/core/core_global.h @@ -0,0 +1,30 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_GLOBAL_H +#define CORE_GLOBAL_H + +#include + +#if defined(CORE_LIBRARY) +# define CORE_EXPORT Q_DECL_EXPORT +#else +# define CORE_EXPORT Q_DECL_IMPORT +#endif + +#endif // CORE_GLOBAL_H diff --git a/code/studio/src/plugins/core/core_plugin.cpp b/code/studio/src/plugins/core/core_plugin.cpp new file mode 100644 index 000000000..a72a68ccc --- /dev/null +++ b/code/studio/src/plugins/core/core_plugin.cpp @@ -0,0 +1,104 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2010 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "core_plugin.h" +#include "settings_dialog.h" +#include "core_constants.h" +#include "search_paths_settings_page.h" +#include "general_settings_page.h" +#include "../../extension_system/iplugin_spec.h" + +// NeL includes +#include "nel/misc/debug.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +using namespace Core; + +CorePlugin::CorePlugin() + : m_plugMan(0), + m_mainWindow(0) +{ +} + +CorePlugin::~CorePlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); + + if (m_mainWindow) + delete m_mainWindow; +} + +bool CorePlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + + m_mainWindow = new MainWindow(pluginManager); + bool success = m_mainWindow->initialize(errorString); + + GeneralSettingsPage *generalSettings = new GeneralSettingsPage(this); + SearchPathsSettingsPage *searchPathPage = new SearchPathsSettingsPage(false, this); + SearchPathsSettingsPage *recureseSearchPathPage = new SearchPathsSettingsPage(true, this); + + generalSettings->applyGeneralSettings(); + searchPathPage->applySearchPaths(); + recureseSearchPathPage->applySearchPaths(); + addAutoReleasedObject(generalSettings); + addAutoReleasedObject(searchPathPage); + addAutoReleasedObject(recureseSearchPathPage); + return success; +} + +void CorePlugin::extensionsInitialized() +{ + m_mainWindow->extensionsInitialized(); +} + +void CorePlugin::shutdown() +{ +} + +void CorePlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_libContext = new NLMISC::CLibraryContext(*nelContext); +} + +void CorePlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +Q_EXPORT_PLUGIN(CorePlugin) diff --git a/code/studio/src/plugins/core/core_plugin.h b/code/studio/src/plugins/core/core_plugin.h new file mode 100644 index 000000000..5062227e3 --- /dev/null +++ b/code/studio/src/plugins/core/core_plugin.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2010 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_PLUGIN_H +#define CORE_PLUGIN_H + +#include "../../extension_system/iplugin.h" +#include "main_window.h" + +#include "nel/misc/app_context.h" + +#include + +namespace NLMISC +{ +class CLibraryContext; +} + +namespace ExtensionSystem +{ +class IPluginSpec; +} + +namespace Core +{ + +class CorePlugin : public QObject, public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_INTERFACES(ExtensionSystem::IPlugin) +public: + + CorePlugin(); + virtual ~CorePlugin(); + + bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); + void extensionsInitialized(); + void shutdown(); + + void setNelContext(NLMISC::INelContext *nelContext); + + void addAutoReleasedObject(QObject *obj); + + ExtensionSystem::IPluginManager *pluginManager() const + { + return m_plugMan; + } + +protected: + NLMISC::CLibraryContext *m_libContext; + +private: + ExtensionSystem::IPluginManager *m_plugMan; + MainWindow *m_mainWindow; + QList m_autoReleaseObjects; +}; + +} // namespace Core + +#endif // CORE_PLUGIN_H diff --git a/code/studio/src/plugins/core/general_settings_page.cpp b/code/studio/src/plugins/core/general_settings_page.cpp new file mode 100644 index 000000000..bfbb06d66 --- /dev/null +++ b/code/studio/src/plugins/core/general_settings_page.cpp @@ -0,0 +1,241 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "general_settings_page.h" +#include "core_constants.h" +#include "icore.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +namespace Core +{ + +GeneralSettingsPage::GeneralSettingsPage(QObject *parent) + : IOptionsPage(parent), + m_page(0) +{ + m_originalPalette = QApplication::palette(); +} + +GeneralSettingsPage::~GeneralSettingsPage() +{ +} + +QString GeneralSettingsPage::id() const +{ + return QLatin1String("general_settings"); +} + +QString GeneralSettingsPage::trName() const +{ + return tr("General"); +} + +QString GeneralSettingsPage::category() const +{ + return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); +} + +QString GeneralSettingsPage::trCategory() const +{ + return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); +} + +QIcon GeneralSettingsPage::categoryIcon() const +{ + return QIcon(); +} + +void GeneralSettingsPage::applyGeneralSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + QApplication::setStyle(QStyleFactory::create(settings->value(Constants::QT_STYLE, "").toString())); + + if (settings->value(Constants::QT_PALETTE, true).toBool()) + QApplication::setPalette(QApplication::style()->standardPalette()); + else + QApplication::setPalette(m_originalPalette); + settings->endGroup(); + + QString levelDesignPrefix; +#if defined(_DEBUG) && defined(NL_OS_WINDOWS) + levelDesignPrefix = "l:"; +#else + levelDesignPrefix = QString("%1/data_leveldesign").arg(RYZOM_SHARE_PREFIX); +#endif + + // Add primitives path and ligo config file to CPath + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + QString primitivePath = settings->value(Core::Constants::PRIMITIVES_PATH, QString("%1/primitives").arg(levelDesignPrefix)).toString(); + QString ligoConfigFile = settings->value(Core::Constants::LIGOCONFIG_FILE, QString("%1/leveldesign/world_editor_files/world_editor_classes.xml").arg(levelDesignPrefix)).toString(); + QString leveldesignPath = settings->value(Core::Constants::LEVELDESIGN_PATH, QString("%1/leveldesign").arg(levelDesignPrefix)).toString(); + NLMISC::CPath::addSearchPath(primitivePath.toUtf8().constData(), true, false); + NLMISC::CPath::display(); + NLMISC::CPath::addSearchFile(ligoConfigFile.toUtf8().constData()); + NLMISC::CPath::addSearchPath(leveldesignPath.toUtf8().constData(), true, false); + settings->endGroup(); +} + +QWidget *GeneralSettingsPage::createPage(QWidget *parent) +{ + m_page = new QWidget(parent); + m_ui.setupUi(m_page); + + readSettings(); + connect(m_ui.languageComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(changeLanguage(QString))); + connect(m_ui.pluginsPathButton, SIGNAL(clicked()), this, SLOT(setPluginsPath())); + connect(m_ui.leveldesignPathButton, SIGNAL(clicked()), this, SLOT(setLevelDesignPath())); + connect(m_ui.assetsPathButton, SIGNAL(clicked()), this, SLOT(setAssetsPath())); + connect(m_ui.primitivesPathButton, SIGNAL(clicked()), this, SLOT(setPrimitivesPath())); + connect(m_ui.ligoConfigFileButton, SIGNAL(clicked()), this, SLOT(setLigoConfigFile())); + return m_page; +} + +void GeneralSettingsPage::apply() +{ + writeSettings(); + applyGeneralSettings(); +} + +void GeneralSettingsPage::finish() +{ + delete m_page; + m_page = 0; +} + +void GeneralSettingsPage::changeLanguage(const QString &lang) +{ + QMessageBox::information(0, tr("Restart required"), + tr("The language change will take effect after a restart of Object Viewer Qt.")); +} + +void GeneralSettingsPage::setPluginsPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the plugins path"), + m_ui.pluginsPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.pluginsPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::setLevelDesignPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the level design path"), + m_ui.leveldesignPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.leveldesignPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::setPrimitivesPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the primitives path"), + m_ui.primitivesPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.primitivesPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::setLigoConfigFile() +{ + QString newFile = QFileDialog::getOpenFileName(0, tr("Set the ligo config file"), + m_ui.ligoConfigFileLineEdit->text()); + if (!newFile.isEmpty()) + { + m_ui.ligoConfigFileLineEdit->setText(newFile); + } +} + + +void GeneralSettingsPage::setAssetsPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the assets path"), + m_ui.assetsPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.assetsPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + m_ui.pluginsPathLineEdit->setText(settings->value(Core::Constants::PLUGINS_PATH, "./plugins").toString()); + + settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + m_ui.styleComboBox->addItems(QStyleFactory::keys()); + QString style = settings->value(Constants::QT_STYLE, "").toString(); + if (style == "") + m_ui.styleComboBox->setCurrentIndex(0); + else + m_ui.styleComboBox->setCurrentIndex(m_ui.styleComboBox->findText(style)); + m_ui.paletteCheckBox->setChecked(settings->value(Constants::QT_PALETTE, true).toBool()); + settings->endGroup(); + + QStringList paths; + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + m_ui.leveldesignPathLineEdit->setText(settings->value(Core::Constants::LEVELDESIGN_PATH, "l:/leveldesign").toString()); + m_ui.assetsPathLineEdit->setText(settings->value(Core::Constants::ASSETS_PATH, "w:/database").toString()); + m_ui.primitivesPathLineEdit->setText(settings->value(Core::Constants::PRIMITIVES_PATH, "l:/primitives").toString()); + m_ui.ligoConfigFileLineEdit->setText(settings->value(Core::Constants::LIGOCONFIG_FILE, "l:/leveldesign/world_editor_files/world_editor_classes.xml").toString()); + settings->endGroup(); +} + +void GeneralSettingsPage::writeSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + settings->setValue(Core::Constants::PLUGINS_PATH, m_ui.pluginsPathLineEdit->text()); + + settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + if (m_ui.styleComboBox->currentIndex() == 0) + settings->setValue(Constants::QT_STYLE, ""); + else + settings->setValue(Constants::QT_STYLE, m_ui.styleComboBox->currentText()); + settings->setValue(Constants::QT_PALETTE, m_ui.paletteCheckBox->isChecked()); + settings->endGroup(); + + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + settings->setValue(Core::Constants::LEVELDESIGN_PATH, m_ui.leveldesignPathLineEdit->text()); + settings->setValue(Core::Constants::ASSETS_PATH, m_ui.assetsPathLineEdit->text()); + settings->setValue(Core::Constants::PRIMITIVES_PATH, m_ui.primitivesPathLineEdit->text()); + settings->setValue(Core::Constants::LIGOCONFIG_FILE, m_ui.ligoConfigFileLineEdit->text()); + settings->endGroup(); + settings->sync(); +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/general_settings_page.h b/code/studio/src/plugins/core/general_settings_page.h new file mode 100644 index 000000000..66eacd189 --- /dev/null +++ b/code/studio/src/plugins/core/general_settings_page.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef GENERAL_SETTINGS_PAGE_H +#define GENERAL_SETTINGS_PAGE_H + +#include + +#include "ioptions_page.h" + +#include "ui_general_settings_page.h" + +class QWidget; + +namespace Core +{ +/** +@class GeneralSettingsPage +*/ +class GeneralSettingsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + explicit GeneralSettingsPage(QObject *parent = 0); + ~GeneralSettingsPage(); + + QString id() const; + QString trName() const; + QString category() const; + QString trCategory() const; + QIcon categoryIcon() const; + QWidget *createPage(QWidget *parent); + + void apply(); + void finish(); + + void applyGeneralSettings(); + +private Q_SLOTS: + void changeLanguage(const QString &lang); + void setPluginsPath(); + void setLevelDesignPath(); + void setAssetsPath(); + void setPrimitivesPath(); + void setLigoConfigFile(); + +private: + void readSettings(); + void writeSettings(); + + QPalette m_originalPalette; + QWidget *m_page; + Ui::GeneralSettingsPage m_ui; +}; + +} // namespace Core + +#endif // GENERAL_SETTINGS_H diff --git a/code/studio/src/plugins/core/general_settings_page.ui b/code/studio/src/plugins/core/general_settings_page.ui new file mode 100644 index 000000000..7d40b65df --- /dev/null +++ b/code/studio/src/plugins/core/general_settings_page.ui @@ -0,0 +1,233 @@ + + + GeneralSettingsPage + + + + 0 + 0 + 267 + 282 + + + + Form + + + + 6 + + + 3 + + + + + Qt Style + + + + 6 + + + 6 + + + + + + default + + + + + + + + Use style's standard palette + + + + + + + + + + Language + + + + 6 + + + + + false + + + + English + + + + + German + + + + + French + + + + + Russian + + + + + + + + + + + Paths + + + + 6 + + + 6 + + + + + Plugins + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + Sheets + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + Assets Database: + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + Primitives + + + + + + + + + + ... + + + + + + + + + + Ligo Config File + + + + + + + ... + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/code/studio/src/plugins/core/icons/ic_nel_add_item.png b/code/studio/src/plugins/core/icons/ic_nel_add_item.png new file mode 100644 index 0000000000000000000000000000000000000000..bde338f7851d2675b29272c7dcf9471196a8f6cc GIT binary patch literal 3270 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 Eg5p97)c^nh literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_crash.png b/code/studio/src/plugins/core/icons/ic_nel_crash.png new file mode 100644 index 0000000000000000000000000000000000000000..5e1f6380bad86acca278838ce7a1c6499eb2660f GIT binary patch literal 6630 zcmVN2bPDNB8 zb~7$DE;i7Ety%y88DmLAK~#8N?OO+UjpyHf-g8cd6+433RH;#Itx^OZ zEkzMssJ&P1T9FX3g&>GXh>>B7Q7a*fNFsZk`@4VdIY(3d_urD}_w~BIT-Wb<$2sSD zpZosp=Y68o|NlKX2Hd|>rh<;XY@{+Q{YDuJI?n&f@3&4;l?(ddZ4*_Q%@b7FH6xXM zLC5+>f4_aQs<>mSTDoo0qfOj(cJII~&d)JEk&Vhn{buO~jnx-m-gok{RJRm!1d3VUWNoZO@#!bjo4cFi2& zYskBDz>xQAfFbX8u)!P?YCzm6BN9#z#5(5q_Hi8y_3;gY=joSB5 zeDa0yfW33ofQ!4d%zg6}sC9zTuzQXXzOyv!nxWt~S7HA`$|4O1e&%rj@69*h*!m)f z@OMGX#YV_VeF?~G4Rda5oZnkkC*fv*cK@W8dbTj;_(aB_32OxO@#WnrXU`mky>ktS zI$a&+?B)R40_JAOO=*Jru}zQ=)fo3~H9<;T6PUA}=jW{{?I;~6T_~?o+EZMSo6(%s zV8nhB8Xuzh@0#*|FeA{fwZP?S@RdC(Tg=yQo&jlbjjW&q*q;fB5po`gE6-n{bhVNp z*X@yXs{wpxXgJ}n%t>dpAx}huk2~nQs$rMJ1Ai?#Hb|>is9+u*Y}E*5+{6NeAnlmT z9hkBlw@g${Jg>#n)s8`KQp64wb9}7=Kf|FF4oJNtW-n$d@-SGrw)pjLnwRS#lm(O( zhzV_p(;JF00Di^m9#%{EJqecsD`Pj^Eb^dscg!aOTF7Wad7Uz!;*R)}uOf7{hO2(h@Ol|# zI7MQCScuIEECfaza>h<(m`l4<%9Y*P$6F^np}@$B%!Oc61C}T-x9flv+{|WH;Q2K!=QiMC$~GXPO`AsLJMU533vu^sPaS;7Dy1KzLxr4al(($EwZ#Lg z1<^$=1y_Rmwzc1%=Sp}WPw#cJQ-Uo2)Gw8jA`u?^{?tsc_04ZJPd z3wQx46SooYN1q1zA~LX+4*bN*-{i7ybv{GfVmf80l?Vxpzjuc#K~I71h!Y+f?wmGc zvshYB7cJbfnHv8hgnrIgfP`yx@&UJjZTrwYOX{+iy_l~|T=IH1>$%km%fM_GFuF=PZR)JFXL zMIl)OYxbHa)~FmIAnjhghcy2%_}?P7g#?+bkRaOcMnGM0FRBTWZ#PER_OkFA&q|T0 z^WyHxI7TZAbvGgT))zW>z!UN3d(k>HTs!m}Nf^U>5;MA6$(3h|tF%GfWo8FfoHEBl zbk}nmRi4ijHD~RpLLh;ez%k5I-HYF3bB`~@cYmHHfHWy)VlUN5^jaG;OAp0ZLOd`;!%WIM0W{F-kU&rUj(du3hTzw z0z4EpPgJ!Fg#Z>n%YxaPUkfeCht;OkvPw-JZ6f#hnYjVZ?X84~JrzE$qtLggLRY0Q z^Cf$Pk0^(bA?0xF%Q9Hdt{6I#m>;?r5PL;P5JGDqJGC~Bu#FZA2w7#oWglnO7~k@< zPbs|#bTsZpbi{=n&bS@+0Ig3DfGFurFseA%=p zdOB$sUC)S5s~B|f&k1;g!fUjImOKt_Y9S#qq_}n53OtslNbKo{i0$Qm7aKxXn{bOJ zpPMeRKmxJ2QGM)P<^a!eB<2^jt-u6q`biaI8jP068h23$5Wp@JnVd{aj=avUh>%Ie z@qS5#VK12wFzY>JA6rUUhNvAAF|AKM3~5mu9cc+K5V&aG)ltLpRwiufWQQ4zj5--Z zUs4G3DMD=usq&n1lrofVxPIi>2Lyz<+aWdjZQhsq;A2V;q{X*J=DijO-&z`Lzh~vT z(r|sn$O10Svk+<|3lR*2NV{9w3R-}Rh<0Rx6>vYKEEaY!p*J-5y&IgV0RkIRk&zR7d1WazI!Mmdo-u#`Hs{x->qE+zsKfS5p-c631!)N62 z8RoLc$*6);Ud40*Bum`8EGf{9GLrHQWfZO*tb;3lRdMZb1AXc3=o&+==lBA4jI7i~ za8;MRzCvD>XhHznfS0upk>QNfQ;Xt*VhV2(n54ZgpR>pGcj_Tw-)y8GUV^m4i*aY~ zEX?cw0={Zm9BoL#a1!O!-hg#&G+ zz(rgs_NI&E4dSzZ@77aE@GAd zJkUzODBL~Y)@mKUHC2)+&TQ6l(k|JxeXLkO^Y6e$D3?dvIxQJMEWjpohg@1hMp*>R zD2g}ezaP^71HUpM)XffoLrfT0S;Mf_PFOpvBa-~*>jb0(E=2sEnIxe(K5tSCE$kHD zDXY-Gyg~z-KU+C8;8^u}Y*$=i{veV=f8NekJS)C9Qg1lIoK6CArT!R3OBhCX=zy@b zc7Gs1GR5v$>9q}v) z?CHctiDRu~VYG%W;pwU{{#k|Y%p7CrCRYwR0x2XQl>{*ENOgGQNP|BRaPP8Zsm+}G z0YWzv*9q`qT0FAakmvWaTD|r=Rp!5vK<(SJ`8gB7fFtIA>7bnjv<|!^&5o1ErDT=H z-lY!cMGNR$O2fW^CioB3uz!HU;`WU61jUt0^dLF?SqYBp;EWA!-I1_=j!rwZ=O&>~#``RV4w<7#G@b(w(TiZX}_h!mG3rx8{ug5d@!1xnGP$Pjj5#TIzQM zob+_yeF>0^4|#17%Gkw@7TzRb%T$e)V2X7AR?Yl*h$``?BzTWkUHD!uPr$PdK+IV( zpGWgE6SNMV=ee9jwiDvcI>GG|Cp=Td8N(O|x4ps1cT{M@ASU2@ms0qJRo;>p4H*5r zBSyA&rX_U4U1o>7`{(Lp#P6Mn6<@T$J2mZfi}}7L{l2ZjhR#$#54vD4S{UO?Hxe|o zKGzL4*mK#;0l^*yeVI-&gZR71DQ_;SntL*Z)<ds2QGqMiXE*W1>tDJ6 z37B$XwFSILQX~VQfX)%$lN3Y}a`>Puo~M^Vd_--$_gZPxwbSrXMTIWZxCF81skQm^ z<>hRD#jlq(GhxJYMKG$P3pS4Ffq2#iLc(2=5aT;tj|tt&8_|eBzkiwpbfMPRRIQ>V zbYrmW!ZF|En4i}osl(_ZKPs%F9Qwt8!>kRYSd$}CSW4eF;pApbcVS7NXEvzwd};I7 z;1>;64(rFNrpH&SSTP-u`_TkXZ6imH1fESoH2a6Yz^<%r z5PeF5M_MewXGqj10itmsA(Oc{gRwyuo~M<7Ii?DB|KN;P^ndZ?-i+!(fPi1Xf@eNc zTxUjfu2P^gQ{HD*65PM;h-kV%ED4BZP`ti*JSM+U4=)zcP*W;H%I3aY>grE(evdT) zWfrT)zO;yibOpq44g`&4l96n{&BGSc=dxII&@%OSZ;+TO9Qb}eMhHm0N$_b*gXuy9 z3DC8kkAQUgTpF*FOCsl5HEift6fd*NlWy-bYDx!BpZ2XhGf+nRCE=`?*C0qOR< zrle6)sfmO#NC|hr>K-ON6G+qZ2783Qw1%f?`qivyaUQ|XrA()f_pfS?(XUj(Ql`Tj z+a~HRAtYQ}{~gA(uZ9K;d{QO8Pclc=!M zTE;cOg1sp5nXSBhI9U7{f=*`Hd!J=610K?>79g4z@EO))D(i)0l5nRCQcpT#T^~E0 z1aSw^x_}pLe(OT;1Tx1eQ%SqKq3i9ViR;< ztbq>|lTQ=i1g*P(SOCvcc}${(#Fs|Kh4R??sUzCb-z6}L?>8in84Qjy=mN8u?}dcf zB;Ygl1Fu(d#OO|yG5doixUg=Fo)vD9gi|YrxES#jv=lk(x<5j8CQh>3wSwl z8H`<_%3}ni9viZ5#c8$#?n&=NG1U(d}ykT02^?EPZI*zHQwhjK}aZt z+-nuEf2y*vqdQl|q+WFq_RCN` zD@0Nb&l`yMY8H8rVd~o(uxc6?XJYs)A%K#3-O@3#fs-Qc(IfxEjIprz;n+G2m-ew2 zNFi_`Ac-!(GF12XRBB$dF50(QK#CB+?Fa_z&Sg-~pn-M@ zmS~{Eq7O@Gaf|7U5fd2cJ3E;$yp1#5I#t3Lk?AGRRW=F#QPu zy$h&+rAWZ&P`1Q7^}Roqnpz$p8=-bFJ4mCkgU!fMKJe~2f)&%ZffoWqq(Het65?n< zBmq%na3`!P2KIGE?aD5wYBcBs$h(8dbcv~ShiMFu(@8)(F0H*)g>`~!c{Wky@ICtt z_mNeRdYtbBV@R@qkF!cFeV@wGU*ofaB>`U+m;eqk>NwW}Wl+hj@|v7`^)8?GQr^ec ztCci0U#6TpvSujcNb`{$ZzbXZ0TQ8kFJ4Gs+=!+%M3zR(@fvvlO}az1il}KcVsv>; zj|Y<|5+p~lkC2GphVC({xhDbTl7MWo$!OYGRw}nhb{cDzYfI_}#J!Fka5BF4=C#a}^h02F(iA4%z1th?g z%ga}pTi;?&{a?4N^ShNu)Lu3o`tHxHTLdoz=pg}f(71LP^lV)O!9P17-ros%kwP5Dh#`rw7R{$!w(c^W%T{-zx*51c z4d5JPlXVqJEABF{z_z}0fe2tOb*2>kyMxG%GA>8&JU{{h*+}JziHi26O0!mKh$n~` zW``)ogc~K1d&LDwr)%LHH%HC;(HYZ6*kRjz6Yhj?#pgOTEx@g&Zu9r-8wv-x2;xt< z=%cpF2JF8($4C0!>LHK5`-=Iu9CwtQk(d$T`yU99oE=LNZqW)N1*8+qH)su!BqWM} zBPme~aM1)#|JKD8=y)_ov)uKP-Ke_e*YLfi<0FCkC%();)Plh=PqM`QOZl{KEmsjI zS`~mcu>uva1c;b?*ESNY$H)LnKtAK8_U@kXe-OM7>^+VzRF|uDvR_Ajx~GptxXL@Ymk|1R=*(t3wBv6)x}ntzNfTK<+JWyF0D$>pne@>HisW zZmVpDw%ofJ$n7)76@#I|?IZHf7M9JLNBMHp|7X?bpO}AvpFv;!JdD+uMC&}!B3&St zK7N$|C5UZj{+2i)|6dR&yFFxSo13DzDNEn?C!a}CV-vZS%9N>=yKepke=JZc(_gb> z;um)C{o-K@8B#vWjuY-X$l~WG!#8Rx`4(yd-{y`W_-{$VjMLuAm#aGQEWjR+p%cI& zhh+8t7r-=;7H3V?- z9aylK*`i)&NzG;c$NSqgUD{kXsRmiO@#DM?-zdb>=i zu*@RTd8@_pvUxpuxyoG1>Bsxw?uX}jKHujL_-0@|T~w8{l>h*Ms+%k3&``sHb<81=-~(e+|N^9C&_KHVw5X^3IM3J{S1(sAHJ}8!egC%W4+FY#L`JIX8~B! zIZ7C+< z6bcMhk7Jz$z zt<~^Npzeyeat^;b(tkMW#bRkwb5S`|-P(cZ{!1geIKC7Tzpi^Q9XhN7r*| zh)Tmw?h}4)r(e%EPx*~jbiDn>W9k_F^gyx#1J1b!&uZuD!J$Duh_I|$-B|3)pjcABT`DZr@@$gnJ?g*7niqC zPg~-q=_uM61|+bWZC}wlE4;C-L;LVrU6J(R@D0Z4=p`kt`4==LnW(d8wXiBZND)3NugXyk}j`B>QSp`rx>7I47#1U z_C?Zqn_!w_iq*Q=7#33$KOO+R;CW!bcdn#k;~tqqg>*o8s|#;{%M1@^2B=`1X*QOW z`~~EL<8YMd;Wk~hP%ln9+T{3weTCGPC>#3IdbbgtfSL(^;<-$(&+()%CWY(ZY}rUs zYZ^=Sws7E+dDpj6e_>>!qz;jFg;SMzWx6GvaM=_CJv#h+^qF(IggsR{8BYMQlBT|c zLR(J;=NJUkn>YRLcdDtY?zXt@zIEUuTe=1hEndEU6|7%)i#=`5cs5S}P9Mh=PcJfo z{ZbSwueq|yZyG~GMGk&1;XI&33fgfyu~6eIQgk!Fkv4<^W8F=|9U5oXINb+#fCen_ z{sB?u3Xfi@SxqMAC%ZI%1BJIf0uMiCx!yXz62rndMv z$=6toP8$LinV$s7C|ZjMS5+@W1rn4NxN=o7bmp|tGx-1vXy7V6(LK7Owl1b<1|o_O z>bY9rcsZ;+(mT(U8Vqy|@K*SC7Xeg!@WG?ntw{ZC`G3Vh1-90Bf1vJ=9f)jI$P4Q6YBQ@Z8;^^H#>9pe+1$q6DXU$-5VbBeJ(3kUiuh943T}3C$!G=4Zw&rX zIZx;etQ%$b10W;H`0fD|-g&n~Eq? zJZ zC}pc4u@0qD`7mQX=zMD+8o3Hi#&31p7{mxJ*6-KkigeYIgt}@Xn1a05YyE6U8VHU~ z8PL=CTn*0W$(#-|89Sz`9P!(hY?pOfm^ZQVXfjUeBhD+B#yUg0vkok?_%`$Xq0`=> g{}tB1bjDO$2a)_&SEAML{IoE@&Dj&vfF`E?18{b*hyVZp literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_down_item.png b/code/studio/src/plugins/core/icons/ic_nel_down_item.png new file mode 100644 index 0000000000000000000000000000000000000000..fc86c4f6db072ec99ee76b81b8ea21d607226dd7 GIT binary patch literal 3812 zcmVN2bPDNB8 zb~7$DE;i7Ety%y84q-_|K~#8N?VAa7RMi>B-!e;PGRY*9l{F!dKnMxh6Cl83lFVc! z`@XO2C{P3sXk)F)QbADK(~8RxS!72<1VyA++|a7^C|Hl@s7Nb%tf#G75&8Ok_r8~z zutuAwCl=26pZng+%gz1$zwdtUzB_{;T>p37f$I)jcR*7I96CX8`lCh&Le5ldn*_nN zOppqHFBwaA>dh5L^}Y>n8-hDNFokxWwhZY!6A;$?rpdqPVL_ZSSrF1hO^2sl=gx9L zF4}1d?l@@;U+_h6%qT{p=OpvAcJ0QfVb7AW`0e1>Zji0@ptsh6;8h8-xeBboEf5qw7lw`hB}8Ye zf`qK~kdXTzq?K<4N7Lhw-?1068@J)lRsv=W8q)c>AWR9?aHv{zohHeay3f6W+Q8Ly z1S%H44sCb54;?E{!^|~jVa~eGU^Z%&s&`Ox*=s*#W(0@L0?Ax~nNzY#!@+9N zbylb)q~mMfK{GB3?-~7>2ulVK^c*x`4uj_kPrMEE<`U3*m+#kNlp6Nw80r(+`5)Wx zS-lM4kRGY;F$GlUS@)d9>A($0$X*Acu?R%(n&TP{R*SA3BhY|vf+OZ$GyPcxu=$VX zuw#BsMkMEL071$H$*=LG7NgX#Pe-IBxbxhQsQEnxs1fc}{L~CUXjT}}fSGID2Bem4 z#wS5G=>6-@XgF9cy3UL?1$KNJ7PIJ*47k_;$^duztMHTopMt$%FB;$gqpjf+Ek>zf zpN=?VV8?eOVwYTEK(Fdg8K9&;ncz-;Za_}k0cLp{)qiK2e)r#?3)@a?JAQM9seQ$1wmNKI@e#Bw z{}5X5`iQCJ&JUPe9h3nMF!;9&JOczTmliQ*HOVP=l)e8yIy4{>Uw8B8zXExvTuFUHSa~#%S!tqIOo2^ zl!C9wWB^X5foFi;zXirjSjw9f4)@INC6N*~(n9g5-tXan)sf1R7 zWI+4CGr(vg1J*(o0y-3BA+Tc>p3gjnfX_2!&iErrZRz+JJGW0i2JzD#MFZ?026PNG z1MF!gTQfvWxfkpRXh&euR6L$K9nYs9W#Ci0o`Wf!M-@GH(fLsrU-SqXFcqYMXn;AW z86va)08D5>KJ0v}1N_rM1wj4%1t+a<>Li00B_u!k`LD9SVHPKWK2^BkFB7*j) zUjqcaTxT7l9@0Ch!@t z7koY1jPQD7FP4FVnBu{O4*AgpW0KVz~(RU zQT8n@X>n^CEFsfz+j=JGP)6M9vV=|tpOAJi2R4DuS_7iF93(?A=q;t-WoyLk?uC$C zw;v|7A{+?;Co~^|2~7uCn~rUI(;-M}Bpp=5&r=%?q7Fbz-a}xtlw3ijcwLoxPqA{X z3|mqu7`#gmIty@@8uYf7BZ4s5>na9JG>C?x_hm~J+lZiLs32y8DCdBz%LUm~2Ik;q zunnIH0g;PfNWyI}a^f1C>-R%^$yP|J+QSA;(M=~vYEfwl@PuZ9C)lUheH@g-rqt6l zeon_J_550L-GNKwc|EE2NxY9Msdhi=N#*`0A+hEO2#Na@GXR&<9}8kmSRc~gQ6l-& zohSH^n57V3x`TC21&bH0!#(XJj4YqKZm}pUO2sHMu?RnfI-rOfz~N}{mqOCd2*y*1 zHTw~YL%K!hPcS9c>{G;#!!zy$QOW|@x9(d(m!I7Sc)GstJm;AL6U_0YBf5Ege73L_b%L zqw_c7l*|XoRCYo1u3Xkfc=fi)UXpLkvoaPkFW)Lise6J!tKtRB9cezFx!mcEQKcxe zNOO3q3CY+Oj~JyWfpZWJLjW99J$7H?;3_;_A7A-6YA;^f%Ubm~wrmF&{cAzQ0Lngf z`vf6F|2++$+cQJ-*2Yt!p%ARYX2C=RR>9SjSAo^m6FvpOlW1NdJk8A%glFJNnsP9T z9FHbRg;PPP<&a$Jb@w%b-UD$JyL-t8$18}K`hE@XVMd4i0C?qB#LPIofAeRelI8bYh0!lXba)$%#YL3rAFLS72U!Q(3SUO^l_wtQEQg2&y8@VJNITle6Z-R@^FFK}E5IM?Hq>P!Z(xvoT=3RPT% zI&a;;SAr+tn9^N6a-Z*D;G`%VkI{-n57#O>|EA}0v4gAFe*c%Dlf26|=)9{z?^6M> zrQ3QQZ7l7TXEC+$G|zh;PkSK&qaKfoBwnz{04iD+M|u~FIKiq>rsJ_CJDEI>$ChyL zu_fCfx_BG-48@{{sc#5uJ0psY;r)*8?$B=3nJW*-xa>9g*CW{Oo~WxP#ACF_v*N~6 zK3;*RIqzAl_#E~WkFpBe8M{rakch@_XPI@RijVfW2O-_H(<=P$6$2PRv0p2 z4U4?aTKAn~t?j>}cWoE#Lu5TdZamcZ}@G@ zfbgshAXCvZm*M9I%^L(^l6>uP_v;<@QIe(hV|+&kYuH?66^4;liX26qN1i{UdBmxu z%FR=s;3=Y>k#?s!haX);z}y5n9$oYpMCNbeMNglHso(x0zPFhB6|K*miJ1wKwE-7O zPOwER=&A0M_6gOP`jxwS44^sBt2Qra7e`)Aa~0MNOwe3Wg^xj0!B*T8n2j$vIau^M zPUG8ZU*7QgjP$*4#8>4kTr&Sl#MkD)s3n*QyCD(b6RUQi0Xsc1fWR*gPZ{6|?g>xF z3|x_I>@ED$qJWmKL_=}b_a3kozaWY^WqQAcbF_C5j7#Q}+MSS8y%V4P+yM82#U1&J zQ(c|sSByLwFer63i@fYx3-~m;+Rly^nAhl&_U8QXy<5tJVaeT)TC;i`#$uEI&-M= zcjkcN3%JV+!%|iv__m(4yZTt`^>{;Y_KYvsqG&S&CoV_$98CZE^O8?>oAv|m&%fZ6 zVDJtu-00w;<^X_*Z598dnR##DVy= z`2>T}uVRK6zE&#B7Q^EU~4@oNUoqCdB9ryIftLY zr{S31T+K}2nZQlpqR4Mz@(H^US9(tTK(zTEf}9(t#b|z_J{>lLU(*SlH)evE2cZdf z!59U8H16m`7j1$dw#>yfzJJ|0ovFC=CmN`hf7UTrZ)<)_NAnv~JSeUkP1uau1Vd7n z^R&m^CcU*BKgh@!h()h2=4FK&gIiDPyvy+s=K?=`iyS&(1y+27w-kaYq+*jGr2p9O z_I(+6f8LWd+!)k+N;c6axBNp`gUJa)ql=%Ht;s*pyM2H1^{Fq%2tz>ayRr$N^gZ$&5MeHIg!(${Zp{A}N2bPDNB8 zb~7$DE;i7Ety%y86@E!XK~#8N?OS(Ll~=aEC}6=t@4bWcdK(um9qy&~-W9MRV#5Z; zo>;IX8Uu>m*c*1ECZ@kkl1Zk|WLoCUn)mYFJZH_U>A$!4aXua*Du}w?A7QP%zVBYX za(=(P&u-^jne5xYZyETOffvC*P*Bh!yyc zJ?R^e)$QmSzuDe7F78E)=Y_u`EiLVvpx_X=d8**(ngD0_WO(@K;2V&QpwL1@$jgzG zHXHsy*{v^paL@aNw)WvhF&f=JoLtqIF>?!!o%{@aSAT}A`7eBc&-;b`L3tbegK{x@ z-p)r7aQXVr5f)Vn2iHXX^B&KrpKoIyGtJvSbFY_7B(uwM-dSmUUb~kHv<77`M7cW z>&Frhn=k{`_L_z#kt+S)%06bCyLb9_BKZ6E&hf#+z3-{7vvJUP(jdR4(1m3k2ZRTY zQdUBr-S!0mO&|PV8r+h=&;r&fHf%ckSnzBCafyvQ4L-B5mYY0jkXCjY3v!xohenpb z!6kw2ZMsJ!tDbb=hKD~Lf2x+W6UDo^?j&4bM3mdf! zk+YQt=jfV*l`kE6B6xn@%UjOV^@&hwYCre#%Y0-$Kvv>G&;B7Rz{@W~gijuWK6}AE z8lUp1K|bn62Pe66a$3_@JV%e8{_aCyIII%z z7r<7-&moJrM84wzBIt8iw5sa2uAZsL%w34{mwqgs&;G?PFb73tEANpq&R;A%!as`E6_Y7SMy_VB~Sg3{Z(9MK zJ_m(`Z=#2}&d3{vB97za9l<`<796hmX_jT+) z{2_V|eLzP^-ovgvm!VK)z{l5D2muzN(P;i5m&+By*6>I!q^a-))c{z%{)8CRK-qWj zeWWUM*b?E1Gil-dvP zwI5EUgbLXi?G3*%GAMoJ*!9LObobsB@xHtF9qj43iAZ@4f}_-Uc~>`PE?xn-Hi=9> z5Y%|NI1)@Fx|R~0yG#I2g`WNIJ|MZd^HFSLij&D9LQW(FW2TEGq6kE?k-?n+nXJrN zCbJs&LRXp0$wwxuk292gs2VGSACb}OVU0Hv0);H|v4^|N05R%vytd~pyiSqi^`2X3 zYFUTKxO6lvT!#0){4qA|=|y}NB~Y4pCgAN6fg0|`W>$(x;n8J(p~3?@c3sDwy>HWC z?ucX4>@Ijrv_p@|TMYbgtRD)kCqp?__D#HjEN3|Hped1=WNh&BKq4&5Yy$SHeZ+IB zY^TD0ybV%xbHO3*jow?(7uO2Fht6NYJD>jm8(!-cpRE-2R zJK`~!TPd9V0Sur>8Vne`MLPieJcOL=n(;oh`PpRlvP$k zmz$5!C^@pSsD$?N8hUKrzN*i|A`AW;sVIjcrUnEYc1~JY+N!}x(30i7A{*@5c}2+P zZGEB{As=UmeF_h33bYsDEY8Hdd$i!C`zeo|uNZ59X=4nK=j{tc;(hIJ?>&M`cR#}A zcRv;~zjK`+fF+iaA}w8$Szd#>mW8M%NzS9DY^olq>FG>>^^oHW4p9@}C|KDkg|@i{ z;G~Be8UukdcrIYLkg>Fqqttp5%~Lnj*i3<%=B<;FS;4a+z-u?i6?|g_eH{ZcaU9Sme`10<(ICAlt_+FB(y@wD-ej_P4nF(+i za(odHayYw$AR&3W&@O`>3OIw`vi%Z@%R69g9*Bi*=7NBj@rGpnV_$S~{;6xXar)XVoPX;bT)6!nF5G#a$oSv^8TcKax2;-F(<2`7@$sB3 z4&5uD^pPBdA6Bh7K)~;tIfIpiK})i!>!N5y*_Z`jm9H)KL^y-Y6)JLolguJVJ^v+A ztnAg(6ZJKSNy{dat`(YPK<5eg`CISe90{LG-$}<)*Y9BenLd#pu!D@FY2iOD09tK4 zS%CM@(Mh3Dz|+$YTeqJk(3c(n&K4mFgJzU>URo{OntI`_JFJd{g*>bjk-3a*BkoPtc_2A|bUDg~f9b z9+d-I`{(;qEbwfS*Cvjy^#EYkVMZ?%A<00o=v4o8*jzu4Z^W+zAwb5knSW zW?(w`SrCw*ujtYj*9h?4Z=L~zl>qaR=e_jZ)}DjVl~jprP@STOG9d*S1(m36T8c%> zc4O7rW0=$Ws#t!bR6gY~1o&g!#)D)9eFXkNtxMqf$Q@kj0>hpNsJEMf-C>TPlOS>t`XI!1qwR9|(5vdHed!Lfdha9Y$%i6aurbqN9sIA4bROBcgxE z!WPR7S8A!}K9T^Q0{W~*al^*V=Y;kL0_Su7o~5#OEo>*bA1#X-3Y7{Nlh@-TIKvUrFM8HFfIAXkVxe_7a8MHc6Lcq(Z6<)EE5}_QG zrcO@}`3LvmB?8vJat18^K{;?WFvK$Q1Fr_#A=Shf)uzV3rV`g^BqW$xN1NuAx12Ak zorRo=TI@e{0VgTkNuUQFxdJSnK8s8~moyrIwDdf5ywol760THf-SRJ#vM;f)Rryg8 z=T1eOzm;uFgr#kaf)xAcTENRY@{)&l>Kt=Qg$ECw7(DIfl_vTC5_mqARlNjz6G!MK z8w&zfdzwQ#ZYVT+8crk@Fuhi5v5BJ@}zRui6rQ}kW7c02@W$^1>J}o*!-ku2{ z#<0fA96N(-(O_eO(y7LOs+nY@dE5(#XcxJ<>OfJ|qJPGc7E2qNarpe@e((%f0?tPc zgLy=dCOwNZAB%>@H3a;i0ADxbWif53WA*X4sZ@?Vk3U)(`yM+IUbSKHlGIUup9_{0 z6C**ujzAj}kYmi5X!w_+$zxZ$%4Ad<-T$+e8BMh?4b7t3;;1gG^>5nr8psneP&Km! zM=8mXw9UukSKjLXypN^?*Z-=N42tDRWbWI<0xhpIu&{IEx$fz!i+>*2#WQJct>JXLzSEfWi0gp+INed1Ow+I*DI_TT1LD3+`#jL z$)Pke(;OLC`%D5)0VZJOf-Z!NpCEdAOPr?&0=7-F!WvIARG3pklxhT?CQOpk7$f)w zYoH`RO$(QTGdKybq&s{XkW;OLUL zhF`=PAcJS%l5n4(b=F3BO|pVNk+9HlGP?XNg>3b+5VF!`3PPx~^|!TyDoH264+hSl zB|`R|JTJ^%otBHdk~S<^(JO?3a|m9te7|tY9O9S+>RAli@jew%s@VEZT|81St7XRn z;Moe802bZ_=4crRcS958OfkkX=gHXQZHf&ZQ_<=$2`Wzy(q;x47d)tWN#ha$3_iDd zIyAa`RMd6|z>;uZ;=b%Bf7FY)^LL4T0^|VyK)Y6kPII3M@qnAi!zSbuED?p$Z4!M4S3JY@P3 za0V~s-AtC9lM3DeaR`q|p#mjCbZNMCb+qsL0|YQ=c7iNi!WPyyBPpj0vs%0QwakDA ziv(UeHqG9~(?Bev$0s+BswepX0sg^x^W&3e3hyszeJIT{cqW0vQ(;9Lg{=Fnsrc*y zQLM1$4_~<24_?x`1fKs_)-)F>d6j5g{OUvC2LoQ%zPH~37A)x@f3O#gv%0_u8L_UwMvkYiyv?ljc1iCC!)Dc2e`97zx?;>+z(#5|Os9*}nS$;1Xy) zG7;S9sF~A7)n7H*mh8e}GH*%a430xxW$iivn1M<%_%mNyRkvQG#G#SJUyh0ZdnbiY zTw=rDxgpA1S*4ISSo;iq}N(DKUfk zd>N&+ShW0g;p`Y#>%u*>Go)3dx4h4g8?;OUgOoHr@SI7R)v{AW1aJS0dk!v|(Qlpe z_SYSzo!nv*BRip?P5&rTGn=Vxm5%+eYx z?R?{3;jLF}i=o7e%(w({Rn@1obLoc-!5LVOFPU&rr06)EX zi!gmn{EW6I4VFl7pzUzqV~3}Rss4$RTfF;|?s=yFryoDaiP}RM(MxP?-3roeEm#D^nxE!IkV+j-MmF2 z&*u=yQz3y;jk3Bi%@IQLN!+ZX(o3UW&r@T1HRbJDg&0vpFiUHz`DUmNlC^;1^@u1wwBs|001KV1OcSPgn!mg z3Z4Fa`TnP=0+jz?*&uvCot5>K0iY_8{KB4y@D20UvhW1}s&D`PK;2%2jsRdHsI8`a zKhSn3lqBuG`sC9n(15-2Kx3SJFDV5r+8&+0(W^kAssU0qQtpZYN9IIw#0h{S!43~5 zvnDH@Y-(B_|2H+*-0Q#8fZM%pI+_Y@88R|4**K<<_!?30aku?sa_4TrR;Xd2NdW?O z)r~;GDxv0J5l{-Ci{{1tzwznf3VX-*cZQF4jZcTRp-wQhOvHz{3CAuZ zt7$LZ(x&KN-dgV5S1S*>PpPF84%7g+*GF^R>cl z&ewN^IbX|(a#FFR!h^@PxB$+c$^3y|JjNH=Z@*B+M#Mg>31Qj&P7vZD4%@bSt5u(h zetEnX?4y!(q!sS7ntR7#b?MIEI=jQGf$kOeeEs0URK|v;_(I#zLILyIXt_UG&(|e5 zJ?|9eal|fUkE*0Kwp~$Ou@T(GK@MX{()%@T>vnZK0rT0knNvGUh>qDbjgHHZj*e|U z`p~sL+adTJ=ie%~GN0V}PIRtogZlUf9MWU&o_S@&e#`CKEv^82E1%)%GDj>=Qdi7e;NMw{PwD1`sEGsY5niu1tAu(a~36G&LHi6&g-~2 z^*?_hYCEEuF|dG-9RImfGwdu#5`Ywd3ck#`P!Nd-L`*BCpB8`MLDTXk>6YJ>lU({d z`8oyzI@RGw(!!pQIjjfS@}XnWfa`|@Fj}TUseWj0cVt5^*s6~{%xc`QZr6l{-MQpP zaDb)I?Af<(gFaQ9zkWyG)yzG1sq+Yx~!$XbLD<}Bmk0FlGBzC+3<#I`~1cwLuXkxxyeiL3+TH><&C~5wUc;Bs1e@* z^z?rcf_R3DYUkkT5RRwGp5reccG)M>?Np$zhqYln+hxFrMCUG zRVb|5?eKx=di0Co1e_u#5!1Qd*tjVC`*9X&%)O(sR!7h4i@!ALMDMwai62ZPu$mhy zd7>U&ZY!G}9gsXou;!cHRDPc;(?3K_RmyVq%AdTHV6S-=>nLIId#Vpj~uCkBz25Q+6=$QvHynr68 z{CaT134B`PM$Kpy%X}L(p6Ez##vzS;!?QI^HAHsz!cf3$tJ-pR(JaxMouwNv3GNC%{ z?OdSqc8~0yabwquD4c z=tq}B-?P-XB8CClF>zatAFYREK9j%H7q|P%>DR=pxqh@b6gBP_uPiQhO~vb`mf!GA zof8mi*>$S&?y~gh>hoVL&h(;T~#N{WSa;XygZFaSDFxc>Qk3 zDJYcWJ=>&gy1ZCJX?r*N?acrC%4?MOdXC_refmD+r_{Oky}$S>at~t=ztyk-A>BPUAmIp zUtE*(=ar5A{Y#6-n(f@XL5t6P_Qu4W=7z(^z8S{*pC}1EZr_?62>_OXi&l3p1cUXn zva~yUeKB(Tt%3AO(LCtzUiKoB9sNuq@sCBNwN4d9#Uo_?rnCfT^UboRXSOg%@t{dNYP{?pMenMX z$b;V9>7C&|zwthR%{)b(v!gX%c3}2b9L=`_VYias@$~N!<@E8{HF?^>K4I!}T+hOu z5hCpbA|w-YhZmWh1cWHJhnqzHQ9Z-ES_V&E+q8$RKnk`lhG~|#Jay2l;ge?$f46nH zc3@>N6w*XR)wV4t$~z!|E}ES$VTG*DKxfCeEOGUwV<(T140v$Lzu1w_^hLPZsu=6rZRp6Hhy$ zd};O@q8Po|{y>=Iqu=e;v(aOH#%OacUQ%g*(=PqO9+G1*XT5}m#e@)|eP9CXUOFT&xOha&9B0sHfrh@qyF~QI6ka!X_K&%aB zyic>*;UJ;RUBtxDE-aNwW_?;HkziUDytI1GT}ECuZS9*@E4-^Y^M1hI#mpt-9z+Xz zb^9abP>gd~wv28b-ynQtDPIjL#Ustfg>Ce-f;2UqbbCQ_UXfy|cP*KeHQ(=??6xBg z&kl}n%r)fiJWhaUA^q3u=wr%_4$jvbWxX2HoqYcB~*edS})ssD54XC&L|tyoPD)CoS74sRyhxn$Q0~*$qyM9we)LE7+QgJ@G%a<*Hc) z&rPyFFn9m+gZXD0r#s;pP12&~>6E}J zdBsoi<^9C}YnPLS-`yop;952_;?y6o%yNFN3rqoy#9I(YlD~H^bNac+iF^Qa-Q{`f zfLWV2%+*&B-CVjbwIE!8Z5$K$`C&0Jxew*coMBjlan$=4FBf=9^X}+AP*bDG={mIk zg(G=zXYfyX=4UHwX@=B;NV6`jFK*VY&7HA?Y@SBKPpwmPnr{$z$< z*yTFO=i5ddxZOTFvB^F8G}LjqW|r`ArJ&=wBydMFJ5JLsO!&!Xc%a{<6KO5NXF0Wi z&ri5_!{6NEt`FLpLW&-W{2AVb$V-2D7EE?{R;%|8AoW@?t)4gL_s~OPG@4vLS`GjQ0%Ba#`}QV$X5r_CJi-jH;a6(5&yK!- zT)9lv)B?*HPoDR8co=envhI165TP!12{vpd#@VnYmb{f6{& zLP4=?bfJ!0;`j%2aUj!2i`y^E;$Y6%{1wc9aoqj0@#Ar{YRr=7%HTM1@A(>{1P1`$ z+VL2)5b{H%hN#l&ed!&6EeH#r=xdim(A5+nk!-50RG!oOe?5Ed@a^tY{3l-n__@lJIkZxe%GsyZ7vj{#nx`ps3=4=aF z5dL{3GCTAr*l_-Y=B2f3hR!f61+@t6o6inXMRn&Z?0 zX^YJ*Zm2x9gZascwd-mGEHPf|i_J`}!gpJi^ zCooQ4xar7W+lh)haexP?4%_dGY1&RGziK?{arr$wP7*AW1bzc)GYHR1ENpDbMIwCy znlg>-eI55n_!&_kf0yatDjvR&|W?FU_QC*2#0lsnweY^&eo_wemF=c4E4 zWI{AA%n`m`=6vlIPt(=~KobTTn=N0gr$Ry}_PkUm)JWBcn~&L3;K_SilP()xJ+;|; z8BG;b43`W%oytqM9pTL#=<&ngULEyee4%LIyHX247&H4KwucMpcI#O1)nBSn`Y#Nz zA7ex7=@g&h&-)m$;-DbMg)fxYQb1Z{6BhflI~`oxM8r8GaRcpxT&>}-e0#%s$m{Jv z#iPz}?D{<)^9@^Yd;r(JE>?pkxOFr*nHl~>FB0)W$@sX$_=vq5A3k=75wtSW=hZ;( zFET`{@r7kK-Aq<|2S1!fLodT}$J{BBsuag2 z<%2@8{ga;iZ=MguNpvw=1~EyF|2O@2)A!Bs^-JhA8{&{M_U_I7+;ykeHL?z)CAK-KEjil`s^}&yHQDpZ+iQw~+OrioF^cDTT%sk&3o*B%4|!${~NDCt;S1 z{qAMxql7kg@S)c4uKO4RfDdu(x0ltf84MmlPn(uK+*8K{6wyXptL# zn@Htvm0oWj3OtnPqa)=2mr8jQ%H7X6JvN{o_dFu$%gNjW9hxggdmtG=r{GYZ!BeB-bE1!CbDyi?GU5fs8)_(bJwXGjh{&P19^x3jQF7S4bn1wRs=fVB3XFI}x z0{sQ5D$xLFZ@OsoJ@mPB&ED9BWDNOF8|N+5q=a3pcy;;EMaM?v9Y@Ze7{;I$@ew4Q)d z)yHJu8RSw8aYjj5=$MP**sqhz@|%gnfSt_aSAvzN!|p>GP=J9W<7$i)b@<)uJ0Fm( zj=JYHO~J!sQTRE=eu@2uo->FE9Q8;xl)LTR$aPVvMgDco)%l7DmK#ur3(bj%)&UCR z3*3d-PgV6ol8OC}`ZaXVt)r6;M3qU)QMvtyz=anKIf7V&&z`Tuup1z)hb14Hb=avYD{{jy-;q+DJz~gX7LI_jHgZh&uFSN*CNJOtEFSDE z;g5Xknuf}Thq~LY>oceZR_}~EEBpWcxN>K)=Pe}nQAc&2Q?u(C!0LF*U|m4 z=HM0GpMW>YF9DU%)751-n&t6nU@K$InR&z!xcr5>7MHvuf&^5fsU(7SBnv)Ke{rXZ zH6@GQ!=w*tAb9C~Y_%wt*sy_!-XI;5u-0>GN@_9MUg~mwr zwGvH)4k-sw`l)Z^K)NOs_Kx9d+_Q=smPm1_p_5PXutYfaZNw2w|3-i+;^{`)$&kp zRYw-JS2$xBMF;F}W%tSt`x39$@Vt2{Id_a|>RIh6a;;wHC4ZU&9&R#RQKyGGkmWy} zb-vyC64&pm)3OtA`*|7X2|M%497W*2r&Y)7U*z?E+Fypx>ZsSuVt3^~!blCmFjn$3 zg;IY)CV}aRyQ?Yr4?u^7*U_FW_rXaf&mVw$WTqJyPQ@^1Xb*56nOf_0m)(`Do4mlp z);d$`)kS~!&DnzRD|UN#rSrvXFy#vcJ<65AqR_+W4w%&TLo|-7q1yU8*Z^^!`!$g& zgcf!hgH?fZkd%^HUmo-tTOGs;CS(rG5#TlR;QBw?5~-}am%ryn+!XzDY1Ym?NP%AC zzt4;{IhOeDHI^*NZFPhrT{nX$q{gqKeik8s`G?q&)kc_~jJ}KH(!`Yvr8ai_i%vEy z2`UFpgE?;AX`PCAnINM_`MH0DH0kiHJ3Cx({AF>E3*Ki;+OKRc=rDA@r9$?Co}WKD zE;l(^t?rV^0@QpL6IO2l{(%um{)jBcK`u1gv+HSQBYt#1*zs(Shje<;@N1~S=)27lGV5&O1oBDv zK20HMno!UE$_yapA?|vDJ?EuOOyNjXl9`#(QP$PfrQL-A#@ezkeD7luza$_x`1`H_QzJV18*{k@pyc;e#bZC8wUe*y`S z2Hm6of+q6p^jCU|P4PTS)Rc9D23`g#H7!brfiR2IeUYGnG!W8NBJC(whL!u@TqCXe zbMW#SL0wW}b>vHtxx2-PaR~)EsayFszh$?qrX)0yMp2lAWwM9n!$9{ACaIayzw&t& zyY<5d3vF{D|4lV2N}T=J!i-i-4Q*lah8n5%>}h_MSFvicyKPEu`dljXp~LqII$qVI z5+fs41mBq0vY8U^zP+dX9qO2Xg!v6nsjYO_{6VMH5aZq&pSvruynn2uBb!EO;M{~_ z*i`d6Mie1bChTv5w{OO%u?-+F_fKW{^82Ih{c%^-P9UkU<^M2?iM`SS+9871PQ>B9 zf+DgO!D7UWPm{V*?3#(tqF6mN<;2@ff1&9`@EbfB3Dscr=0mvXQ2_Evz6-4Y}Gy0z;pfQ+6Xy5t_Ui`MJ2HjTWbXAeFo0wEK>29 zn(<2A4yFG@E+yv5&y;P(*K0PU`+Cjl8EPyb)9Q>fSKfE%HfkB;9)*QhSudM#nGt$A z9p(l{bo^}Z_RM-63z=ljGvhDxu0g#Sw?RSM9PyW%{$T9W86b&A>Xpy)h~ z_t4$2zb%xj!dPN-Bhq=SPadt0B5V3iqC)GfzcBIT^t)jgXJHZ64>U^bz;Y5{bE$Zw zAY=VGUokO=GK`i7b|l6wAQ~aIxc)YZ7q%@XuT^P31~-S2-q5gmAy|=MO=QAxisIox~u)w%04*-t{;o|{uKEdU4Rq-09tuHXAhJ@YK<|xR+-vHku z1yayD04YVWNpi%*|&n z2&>;J%AUWjJy?_BA@fglCw~224CF-0<&FeX(SzPbBZ-5f;F5P?BTwzW>wSIYKdgbD zGix(pmF9|EH_hM4DSD3V&au4YBS*5S#(KG2)tin!UkfkO1w-OWy5S2n5Tpo_7vLc| z)3c&Wk{8gQk%A&+B%&in^G#Jjg?5_Ro=7U9{Su`M3&_p&h3|Ld4fiG=SB@|CE`NGXV()?W0B_6omx`g3nu zBy=P!5*p;+XT%wKNBo8~SS})T#Ol3@S8A(Vt#+>@7esH?{vq|on$lNq_ZNsB{mJ_@ zAnY$q8hFTec|dBM)H}U_v%RzzdK@wINTvn&9N9d;zv- zdyQ|l^*m`?s&W>ER{EVot-Flnn6pd^(jA6*TB)S021I?P#9muwL-F)xbZ`&~CPYtE1oi&uFDong%%9Q=lB-|h{BW}v zsEZgO4q|}YWIRwRh#Z|5A_=^_Am6)IOUsCduCw4dwY4tWUO5`2BluIP>E@E#a?Jq| zG~X7i_W7s96_UI!;>2V`F!Gw zlBV4R-}PX^2uK>=wr{n`gC=w&G49nRJm{!gL6regsW?cXvhtZ?!0%m}eTERjNLEou z5F9;^w|)z1N--vNkTVvWO&~>~7R_H0ynx)xiL+G$1Yju{Qn@2&`MtQ$36WNuPF?~F z`g~>j50@Huf=s!arG)0VmxGQJ`8Z0}meA8rcMkThv;5La8+Qv`Y6%GQ|(TeY?rLo1uJFR649#c!gM~wdFK1o9V$@VoDHGIj{Fi+r+KH zA>X}=N}9${RQIz(S9Fb0=Ik5CswTN{Mv{T(J|z&6GRERk`bW%uY@ zcXbh1+t6_?$>A8_(RV#%?B+x?*$vTzAH0Z`+cTD*pigv*n+r|CxC?%GNTpS}7WQA8 z)=7dWx>W|uaMCiO%-zo?BV54Tv`GKQ7k-DCN2* zB}f}7S@h+*+qav-sN=CS8W@%??fOY9mX9^HU9!|Tp3HZhF79>}IyT^gfRVk{$ME=( zNgdwdj>-!orhC&&6wJ>HqhMot@{Oit#Thw5H`nu9=ewa|V{IXq)=t&bF@Ez<4KuqB zF~jWsw8MHQk~DCe=#}>Ibv8ft%bSJNHky}7*cBdhHPbCjsotSLf4mH{a-8=K(!8FI ztBhDk-UD{F^mAX{Q}NIuxuCY?l~2apTu9?YVuW!NTJnsx@4{kDmPwD}c@jFczoIU}hU8@!Yx$fP;0SRS$+z^RGUO zYY&QRbIgrC0E7;uEX^?6sBvvE>hi{-hcgNSIwH<_b^pQqwk;dQX|SfUI6i|r=Q$ct zFgjO{3=8SZ4F#;jZJ*xj$vXKX*vPcdzCY!zWTyVq4Dd+)aZAG%Tk+HG;MuzTt&dmp zBr2YGX}t6H;&L?@354pzt2I<#jZ(^4?n)2KJb^Ho-jGcCvV0yC(KCl7Bx7L6hU{m$NgkgYVEb>M?7x7`ANN`x=ExS4)aI>QHl9lxLY z#gQfrFVb=J0{|l>Ds`Gc>XMAps+J(u+?<>!ad}HU^HlEFDmF^Y3r9>~HyRq=r{3>= zmA71cR~_9|HeR&3b2wZ3mvBu|%~J5fqziA|AH$t(gVb{)p0DJWW6WJpy3*;MKm%w{ zlT@t6Li(rv3IF~Kx-iO^B$x%B>{W5{Y_Trj#mxA@=E=rXQFhh4Sp~YZ@;&$p^c{Ua z3T5YG?doi-$Zx0DQKoWV?2dL;+oM9QxxmtO385uiNeu+A7x8I4kR+W(?)Z3Vv{&gH zB0Lr9&62z2&H>s0U(iG?<&;#=-d?l$>FA&C`f&ytGPnFde;N+oS|H-+X4KES{zRFokitTmB2kL$OlzhbwB8=r16LQ;nDX-lORz*6zI^H&^^rY6 z3+o8GhyQD(3`NTUkrC2k-{YGaMBtk5{qU~QpJJ0|SNLDM%ZgMHjYYQfF3jCRT$l>q zjfZ76$A4tt$q`h7Lb$z??{ZY!RpA4FS*}P4yH>2DT(JAvgJ;r4AzcT>0sPNYJ6h=v zfW&FY!6;`~byxy*BM`U6lv(7lsX8??;F2kg8vU9doQ5oe*i9_UBxk>-U5A}=o-o}v zWmf}ppiNI6)2q|=ci!UFG&G5JYspdTef$lPJvzS7UR^qcJ`0W=-+b7acQ-iBC({7o zzttgV(3YFY7~b8W_IDBUwle<87r>N=aX<>{}6-oQcq?K&%ChghD-YxgwP9+#`*QGKk+Cl@nz=@)@96sIfv1{ci< zp<%Xypr*US(TsBY*EA%^bJiM=A3Z;0zLN5csFSn=gE)Bm^#D(*Jhm9TuL05p($V7fl^o>o zpJ+VR;u`zV0Bn@ItynXsPA0=Xy<8KWwk?nLF`{B+ed5%uh}28w{_m<)jr1w>yQ0rDV>d7-GAXJ+bg`u@5zqzcw3 z<11ed+ikWbO4(?JSIV3)y$=LVqwOwi$F=%rO92*H{ok7%yidb&JQrH1%Qic|W%F{t zFss@WH%g)7{d!AsaW6K}{_3rvVGUGHbH8LG=IBqKr2i75ogsNj7n2ui8a@lvV!g=U zQpFeHG@+RG8A7Y-LW3WjVNyWuNa=7%LLHid=pQrBx@mKgj~=Ke8B^AO zzK~fUlfK7yFyqJ0j5bC6M0<>O)`y9WSx8dWAv4T!PH1izujlH9wn z0K1Z7r0VD)1-rF1o&F7T6B02%7)y4*j(!4t?J2snnfQ~jk4e%{!5@G2tlAP7l8>?& zJPx%@9;!G$8BauN&6xAjd;s)9JuW?YKG_=X$=*B7O9hgk&o`AJI&QZAY}^A!4kiHd zo7WrCtIA*o+qz$AiI3w~XZ4O(HLy$2IX!IE8??6SY;98lU_E2a%X1`88{^p>a?*X) zl6_I03K+>jVXC7$!7rngbkRW16ya zs(LOa?5UG{Z}(jtanIP-Lnk9DI);dVFW*L!>9MN+J2hCK-11dK6c|HbD~|FIqkF1` zw#`heRk6C|$~|?>lM_lUk&pS1#St~|K{v=FExVAZhV1Y%Z4(VFTj z9ss26A-`^z0|9^conc0BZxAWQW7{#}p3f+k#PvuL*S1dMpNO9+ZL66x)r0BhwGD${ z>>oI-)ydLGBDV14#5H8IVWr6|fd>`DR!5Cb$0KOgc_O&V#e{(f73*XZOJ8#8@DyYQ zpktDX8b+Z?Tdqg=plAwZD~Ta#{>PcRQ-d3DE~E2l2$*KG= zK3Pc5YUujC2;6b8B10&HkMfLYKvz)9JKM5{73Z6 zDSTR*MO@nSmf#|eCGhybSL7EgcGOOR8aM;V+*UN$|G}U|9{YW^wruD|K>AFx-3Ll< z(=yN7Lr3Su$gqWTRI#`Bk-$ht-m1et==;GdYn|i?dVXKk z%ywM_69{`Q<_W7A%mI&viU3NYW=CayjZ8yGuM)*!t`0-UlWQ5PZD!dAixC`h1TTZ;^an(-V zv&;|;o^lMMjZxXPhvZUUD6-EnKqOrE;kxK@5Nv(0fhR2t2jZP*wdY?_5{69v7i^i=eakfog~lR`3cxhXq&A&7hIKE}wq=HAbM^*djX(9g zvt_1+T521Hvbx(;@U+u5Q=88hED`rApX8y*(Kwlc+UCfA4xxo;P5kTLVV|OkC$ZQn z{i^i;9;yyJ4lSQ!$h+fH7FA|)IU>{pcp&j&8T!Zp2m)J7*f65HRMx z4x2Ph;AohmIcP|`gBVN?7yrHQEr6;p@d&bMrCl@U74ieH`)rel8+3|w=YrZ{46;)T zTosbP*Aor&v?eaKoTDpRKr#uXnY+cuRGh>%2V>4=cFh`t%j4my7v=YF6H50Cwtw%( z8$#D9l^XLUvJNn(#Za?#5+711vR?3+A(c{gtnWsQ6?82D^XhEnMKa8APpCZ?l(|Q> zM`b6NK!YZ$YjOkMf2CArU+3Jh7`OZX%cImi=EQz`-r3qA_~PAv9!txECY9okH{D~x zcQYLh^wWR#bbfZ#4_yST+Zy7bA<&2eKvCp27r-)mxIZ?@ftu)ar95H_qSk-9^6%W; zfKEv>%|ey+cr6Cn{&3w*p5T(dgPt^D?6B$lS?i2x2JI>7O0q!aTX05Gj%Gp^W^2Z3 zXOEktPFxEegCv|;n}x`(aM2|D_X_TRrW^uORLFfKCf7kHraf_@6|Meze4e#6>{*3| zhbxtPvFDum122Aj?v8Dx?ePaofGqf-R_wHb!*z;_NIMU_eI~IQC;T1s+gbaI_xyhd z@1+`I-Q@m!Ix%Hjej1LJ}zn?zHazZrYcRf!WgbVdR`w{&i zOgq|+%-)l#pbdA?B_fOu$i!@GZs9%8sfF)G{6jh`l;wU9BMs0OnVIs=VFCVcfbRE! zDug{^n59j)hrYPiv%S7I?<9S;UQo_VDf3yy`A+%P`V9Q7(cZ%vpmGnwOZH{+U(|}> z@&51H9*0qm8swEQI#jMD^fMEz0rs@epMi?E=Slpg-enp3ZYkeoeeOfbIZkHuWt*Es zy3!fau_Y%dtIvaOrZOwFX85r6;N88~|5SU6jpbk6(}WQFFYynwVtRqEPKfel*38Kh z3sC!pf*FqzbiF)}3AhE_mPf%bKKLB!0beO;mo;w4W^P9@&nGLgAR*by`coU%gDJLe zLa+blXI+eL>QgDLN*JjQdV^`1P!GBwp!Z=B11IosJHy65pBpzP(VjD+&*33oWN8aS zotpb2d%nLit80k|^d11^QzlIt4W09e(@UW2V7e5xZ-fK}iEz=4f|m4F>Ngqy1a7{k z8W5E7QNC@>YCZCxyz90Y7xs>HAVW^*k-OGXcY2r!NDuW&l~i6!wG^1JtfT=f5Qide z+4lZR31Yx81bDO5puUhwumMIHJT1lqdAM86oGXNt2W8cusz$&@3{%sqD>gr$wYLT; zxHyCB1Rcr^MqX%)=!-=dMzw(bexB|LEfjSm5<*!%Fp_lO6$iptGtwY&zu#*f5O5@= zg`AANW*|g|p2K(sshdb=>nG2WEdV=X3WW*!sc3^g>7@~JHv{;F&wIWtZ^<%r^6k&; zZh)Hwi7{Y1g>07Fy;^|xP7LtmZJp-7KrW@lQ6X|<1_y-tP~32vD6G(MXqYsbVe!00 z@-W2s+C%@!$XCHHY@Wo{1vN21O(gB=HK*>~1sNtGvMwA^AgEXkAOYW$Qux^lw_3%o zPn!D#u>xYqooor0e|70VR=}fV5cI&0oGrAJh?6DZ@V60HH&?$6^|6tV!H%4N?COgCX8?~nK*wDX zygroCA}~W`%@36F_?~Ul6De@!cZiSfRfF}&pQuO$)sKW`t~R7^^93MJ=Jdl_AH&kL zzB+-{-S5Nz@NQ1<`UkzI%Y-XxQ?huMM?zGS6NN>U3` zXKn}s#*-eo9@3K0ww93*U(#zcHH+ODyK3YwTj5wJfucFY6|;vMDj|eC0Q-O(BXT5$ z49Bad#uAo!JP6eQKb-?;I^-D+%sxSQG`0zpUGWc-DYw?hYny7DVXf_3p_uQ_GMm^( zQ_H_tQn6l~zQWN@vd#w#irz^hm=UQD4T3-EqVf)Wca;s>J)r~d!vU!3pTNG ziXC(6Ks_o;czW&cjz4f-N@N}0{cuRe?Gq0=E1Vs4$Y|~ZC#Xgk1&V_X(}eShxP@RS z95Rz=!Rq_g=vC0NEj7NYir6~8-K{xVZ){^31AZX=E%d?j-95r(e~#h;-oy1A(Fby` z-`UZEIKGez&dE&$obE#c2?6(=1$w*&xJUmAwNc^9)JwNc4jX@DLf4(r#=x{bRz}27 zsgL5T-gotweU?30Pjuq9llY$pl9->*M=M7?XCEh$ zY61%Huv_v@-PeeZ3{@PhB-#tHRCHtwjafZ;G}D!y+z`=m#}Y>zB2T4HIOuX99K5ym+zmFZ&s{K+j4@Bx#0y%MZ?^ z;DCcc&4Y5E;A{czKRt-Y$W{=;+o4diM>WJm+4DS_q{K!mG zSm8Fb^6o!0Z-TAkBO=@+r#Yw9fI`9SG8}t#y`p1NxvhliPIAKP3DHH!Rm+gI?1vNA z&{>6vFfnrU+t5QCe8G$qBl=H*B)O5VG%>|y?_BeW4>t&t-&!>JG2sU3q0dElXdl5^ zl@T~ivY)3HH+cLaaP-sU6N`9%v244Jlm{0ZP~d?50rET8ZbIT4wNx1?1hr z!@ooRc60Cgw!qcBtpO3g)Y%HRORvKK1qVnakOnZG>GMcnr2N^42QkHXfwfeLvk36V4;kcyfGRS+#ndY>%-P7K%zTd<1 zX8@jywQtX?jK~c8V|n(xJm3R~HcGmHEF>s#f#V5u8jM1?xPf>~3TW3sVibrE&?Ng+ zoj;VY>5T^}F_TlhUl^w2Ymk~#GtJCMi-5tSbA4q6D-?A%$kFP628gWV10!$2`TnO7 zVmq01pRv^Zx`GyP>q{2_0Hw|gS=XbaTH8?3j%GHc*W{?%TcIYQ?Whm##o|_;yIcVK z9aQtA24GH&r3aFcv;yb65QP%}H8FYffUXF;Y@C%}@(h4!X6%hl@{z0Z zoDZMI!avQ-*PHY6^i_N(^?=<~#6-JgK2Spp0VT4jw56}ZNU=#vn z<$PsTgq0<=-a?ZMI8Zz|L&}jSV@Eoye=-t!HC#K_h%Nv=3NNgImCg>!N!whTsj+5X zSX4O1NiGlT{pOs6K^(8Yi4hKG!hp#W(uSh%FZ}f}VIron08e|X*o?6kpPBCL-9BF$ zSUHajbyHKMx(Vb3p~ZOkaYWWre(bJc;OZd+hT{|LLhk9DXTVJu@QkI94hzLXht_UxH_HjE-3z*)EfT6#5=|cNBvAGfX>gFVW&*BHJv;fqoWXOT|CKN~lB!SQT4!oVPf$a-iM8tF$0E}`zae;+5 zLlhG#&M#*B4^Le2Nf%++d_x*rB`0||!3_HozJ=>~S5HsphLL~=NaEBJG0jcr;B_;~ znajj|rTIVAocTYLZP>=|xy@j#W8ar-krYDKF$T>jM3E)SP}!+0(`L90p+yD}WA~JV z##YiOGfI|1QbO56vh+lTOqTJ^^Zp6%Z}0sFTtD2`^*PS#Jg)C~XdP;-4|<}lU}4sX za<=+0jsHirOHt58e^-blp%v!Sry{-fVd(_)<&9NTly_)mhPk&IKJqsnqT^;zbQL{k+31z{0Nn?$l#sSkvF=>H6EyLx% z00BxM30BK1vqC~xPP2C|o?0m2$8OBnawWFJA5lYFh%?l8VigzyaWaq|RJ*4>{L)X0 zsx|!rHtP}~ZvoFR-}xEj1uO4>ly2yc*h&y1v=Z@8Cn5wQtC*s&msf?8a-NvJq>llo zOSyK69^|X=x{tFIlk>C*=F_`nYhhcM0zNkzZdYTP!{eT+Of13LQIys(atlz|i}BEZ zpF1ld|Kema$)s<&Rc3RPANbl9gQ_208PSZYzn1VOT@)4%XNSNXVwg%_WbASAr!a~+ z)*9D65G^_)gw+LGe1|lfrMW$yM_y>sQGsZ-UYBwN0g&02WGUQojL>o=@oYk9pQ@0g z-A=hHYTzWFyLQ=(Us}a|pgd9@HA^_Uh}?t7;kvIJESOMv`(*?<0o`PsB732adQCYH z44GK@F+sujji&bjJ37Js8V4BPq-V<1PNWOQ4zH(M<<|lf(0%?lY}ihG)Oq1eL8IXB zCDIMc3&{gmSe;*5!T}jT8dyZH@&_X?YYvb?+#ixx=?vIx{!CYYyVl3SOZyL)m0h^r zv%C@dm-2vK-Vt!~5BGXpS{LQbhXOCF@fB;hy&BL10A+?)v@wc@0IrCT+8_-V7n49O zUeRVD+nYMVS}OB1MZ?IzMFguBj%sw-tMPbv?sd%}_(kA+VSkJhj9R&k#X~e#2Z$f2 z3tuLgZWga~!kI1oN5Iye&~{O6)pWAB$pv*kVC9uJQx)F5a?@Vh(?{~CK)(1V2~zwQ zYlUIvoVbw;`{L$F{r8ol?%07dTq2A)DOu(Lk-3Q7_|VGpWsoXww#eBC^KafOwgm}Qy7THuUwVS=+R^?A4B_5I z!*R+2eeS^L9+PR6uCZYr68_<-!lS&7!04UmU%|PU$yaYh5K`(KEX*b(RH{3DEbT4} ztJsbMJgujA7+iC}Y5jUOMCVKdbuMkZiZfB&ss)ukX=Oyw57Ry(F+06*CT2oQyt}Tp z&<18BDeTHa_MAWS^)aq=@bx~d4ARXxU)~F7i}q`KKyNmS&k3je8=qM8{F>F3y)*=d z`K*8wt7xngX#fym%}66+L1D9!r}3(i(1D+Z$zTqAmYY`a!*RmZ0XX|j4cLG9j~J9t zlDCl>c5VFU`&1xaej*lqV4hUT=n?khvRRHmtB}Ssmdd^j(RtC83Ud@l=I3NJbH@_t zw9@SalC#P&vM(H}eI3ECs<2WBEw^Td7SIGo_K9_90&!R0KltmerY{EMT|Vg3U_wPO zxBj(^U@sB1kloOfIiy@^IhS_>m}=!wZ2R6S+kF5mizWDXlsrK@!8W0ql82r)MLHIf zgX0t-Mhl!k-Lvu>umb@47YuL#mJblMjDA6k2jNjY?c&Tt-jxQV{dj0Fmp#C@KOrC2 zL;#;>{~0uJJe&%Z(t1*XMg$tMGfmxvpH&(_V^u{qI@USH zfFOh<1l##8Z5DpPdrUbA@SjMP>k}H0UV~&KZ1&|!#xu28lWt?`9a8mu<6CoUq#wRX z)};$k=AtWI|8_}ZmcX~pTSm_xujy!LX{ATNx1>QSwmNr-&Kj}; z&+nVLOY&ZzDnbR8KleAzB`trmve)XK-1$a0_D03?IRFDh*VocAG3OMSbzS2Up&ce@$3C07Z>;x zPCV=C#984MAE4+EYzW6oWBMPn+gYDaY_4Ry`|+$edG28hen4%YrjC1tLCH%4lldo4 zaN}zJGWa>J81AK}yer}gXU{FtCwr?|*47CU$-%PxWa6IT=iAo+FGP&CoQw5~z+zqr zrU>|ow*54D-_j{?Dks=qtzIfld&FtjI1PwMNK}+zy2l+pO=;cCTHv;6Qe#@t1Mgo8 zp8-d5vs#ile~QjVCx#-nm7z}Fe;zp;YSe-aAGHQXgMWRzVtl^zNj$$;6`U)+>zggC zKh+0Sa9barn!~ujhqD%>l#=Aj31{gZxx)t|_yW9v&8Hyc-|s8Car^_muDhtIrJD6d zhjrm%*6=uN$lGP|Ox~Nbu>JHlEj7(We1q)4(Y%$YM~i5! zm94xDamoxTEoyVCmqb;*pUz0ILi@+DBAr1@LMKs{cU!8p8ZJ=1NOu6)VV>jcs%(9~ z8E^3FIscrVy6lvN7Xl+L;h4iaLptV4Bb$bkEtL$t;Zo+mH`#^I@h+G1N&5k)n5$FV zf4|T0+03L>RoJIEH%-|*s7E7CDLiWMxQW@;#p4TPWQ~AZ-q5~<4PwFuRqK|(7MR` zPTMwS3dA=9vIQ1)Aa}QLJZt&Fm~p5DURJoiM=qEEVsJ-fDS*4S-AqJJYsf>@@pnhQdGXWm4yl%gnvT!EuVfa6ZlzTrAZSg z{hP`1%nVS2bUnu9`@joA&_(*V2F1g0T0;)lw%#vQ2@&{_Tmc;VnHjy2+h?qfr99_B zi+862)0>>lur^Z;otc+0%Fozf$~eU)=zNG{I5FYrv=*{hi4VmEeX<^z!oQk{Ss+Mds4Ugab{b{Q=DvX(HHxt^V(ns>xiDf^(Kj>cN&zx?NW zpgNl&5$r4bT;b!vl7m5gzLI(v@VBa!oV{a%cF=EXhHJCh+kzyYGP82~ncm&jyq{EP z!ly|^b%X1V^i+{ckc3u|IF4Z>2ci6m92ZkhHW`@IB#1mo-p{FTDf?7alK+Rp|6!pV#wZO6CMXQC}U;%2ik`a&Z z6rds=rV6{2J-Ff6-}W=?VtelJ5w9H9y*hFH=cG9B7}7w3f)t2n_a?6CD3PkAwl7N) zVcweiiN$I1J_gg5k<48{Qd=<9W)zD$>y zU0uATUS_6avdKpk*Iw$uR`c4@oUY}#llS%3SNs>{5q+t%#Nf0>mt!VSowER0?UM59PDhVCjec?l* zi|ZQoaINF4lt;QvHa`Xh|NL(#VjdpA!~SFH42QhPr_4;*<-`P}A~*iVBVfJCA12Gs zbVa|Q%7{)9*T+wHWDJ(3`U|s&A2OESfT3#dy`qa-T*SMc55}TxqhgGmc(Sz8up!5k#3-wg~>3x7Scf)qEExD}jRy%XX|dK_$M z_Ao|JX85?Ij$Avg#w^ZTGS*h1z~JIueBzZ8lJTt?;8yPykMvPNX&n4Q&-C{|PNPBx zI4bSidZJk>@OR_)z~9s19od@4I#!qJWNL*#FcI|KfC3qc$lJ$>Q(|03^GLfn zd(_ihkfG4TgFi*KzT=f#z@pv$^C7wJ4xs87dDkfUplGRbln_%&pfi$GEJFMktOeB} zEQuLucZZTsb>nxMt`Du(IbbjQQ`suQwAx*#fQ+%|+UVKcBk0z}8C?4d#|y`)Ydkqa z6__w${$I1?w3}@_t9I`v_TKt6-imvC`dL&3F4M2#_%2NCxHtIvoMUyER?%&@a8&AQ_QN zP+I(*f<5 zkI^VRcAfM3#N@oki5NFV#h?T$)qO+G)5l$(5aMvLpE5`-diCwhmXxH^LQalF6Ryrr z#$mvJ;%WHsxyHxY%ZIy({=>>v%1cAfc4MB~9`jdmLr?RVN&IdQ(&sc+5qs}NHw-cg zYYJc{c9Xh$9W!cqJdyR%1Y<|D<-zWorpM;giq!RFjK9>)sX_V}MSLtdmn<3l#b0dM zKq@_^+XHh#vT_UcfzKg8Ui@R0>OqQNb41t1wA_m2WfQfOH#H_lI$qzvSP0s&mqU=q zCpHx)Hp<hv5l zywrQnG;ME}#hzk%tbZ*YXWr zO^So*^4y2=k<+^PD7A2ev;ZDKqUa8YlV`5|7l|l>WRe%S?+l7A-Z75cVXBR!p*SAi zQ+Je2TIg-`kdBs%*N4tjN)6p9)VmSbrjhl)Hmq}O|BW*_@r(!B#&bHOepz{MudQx( z**|J1?HOkD{K?HUlJCzPlZU6AhUp?sraA(a5niDG8DuOssH)v~UsbKOw{s0quS!1G zqL%1*qMvp<>vNBggLI5W0Uj$yx}}k`m3qH30Vm#HXuH%&(&+gnY8&3g`4PVTgY{3- l|GOB+|9kXgeX_>NE^K-35S{O5?jpeb9PFL#XjlUIe*ldXyD|U( literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_open.png b/code/studio/src/plugins/core/icons/ic_nel_open.png new file mode 100644 index 0000000000000000000000000000000000000000..c4992affd19cf3a55bb8ec2f3121e5befa69a55c GIT binary patch literal 4310 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 rVX-&N2bPDNB8 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 UsoZjLV*mgE07*qoM6N<$g2^9G?f?J) literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_save.png b/code/studio/src/plugins/core/icons/ic_nel_save.png new file mode 100644 index 0000000000000000000000000000000000000000..5aeb3bbe94a27c3528cecf0f2e849fb82a85b4b3 GIT binary patch literal 43738 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 %I{nv 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 literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_save_as.png b/code/studio/src/plugins/core/icons/ic_nel_save_as.png new file mode 100644 index 0000000000000000000000000000000000000000..6cb71a33436e58801b73476821800b1b95a1018e GIT binary patch literal 52871 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 mw#_~9)Gt2qq5{#N!2bXMO`x+Fh$+(m0000 +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ICONTEXT_H +#define ICONTEXT_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QWidget; +class QUndoStack; +QT_END_NAMESPACE + +namespace Core +{ +/** +@interface IContext +@brief The IContext is an interface for providing tab pages in main window. +@details You need to subclass this interface and put an instance of your subclass + into the plugin manager object pool. +*/ +class CORE_EXPORT IContext: public QObject +{ + Q_OBJECT +public: + IContext(QObject *parent = 0): QObject(parent) {} + virtual ~IContext() {} + + /// id() is a unique identifier for referencing this page + virtual QString id() const = 0; + + /// trName() is the (translated) name for display. + virtual QString trName() const = 0; + + /// icon() is the icon for display + virtual QIcon icon() const = 0; + + /// The widget will be destroyed by the widget hierarchy when the main window closes + virtual QWidget *widget() = 0; + + virtual QUndoStack *undoStack() = 0; + + virtual void open() = 0; + + virtual void save(){} + + virtual void saveAs(){} + + virtual void newDocument(){} + + virtual void close(){} +}; + +} // namespace Core + +#endif // ICONTEXT_H diff --git a/code/studio/src/plugins/core/icore.h b/code/studio/src/plugins/core/icore.h new file mode 100644 index 000000000..4f1ee474f --- /dev/null +++ b/code/studio/src/plugins/core/icore.h @@ -0,0 +1,70 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ICORE_H +#define ICORE_H + +#include "core_global.h" + +#include + +QT_BEGIN_NAMESPACE +class QMainWindow; +class QSettings; +QT_END_NAMESPACE + +namespace ExtensionSystem +{ +class IPluginManager; +} + +namespace Core +{ +class MenuManager; +class ContextManager; + +class CORE_EXPORT ICore : public QObject +{ + Q_OBJECT + +public: + ICore() {} + virtual ~ICore() {} + + static ICore *instance(); + + virtual bool showOptionsDialog(const QString &group = QString(), + const QString &page = QString(), + QWidget *parent = 0) = 0; + + virtual MenuManager *menuManager() const = 0; + virtual ContextManager *contextManager() const = 0; + + virtual QSettings *settings() const = 0; + virtual QMainWindow *mainWindow() const = 0; + + virtual ExtensionSystem::IPluginManager *pluginManager() const = 0; + +Q_SIGNALS: + void changeSettings(); + void closeMainWindow(); +}; + +} // namespace Core + +#endif // ICORE_H diff --git a/code/studio/src/plugins/core/icore_listener.h b/code/studio/src/plugins/core/icore_listener.h new file mode 100644 index 000000000..c27e40242 --- /dev/null +++ b/code/studio/src/plugins/core/icore_listener.h @@ -0,0 +1,63 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ICORE_LISTENER_H +#define ICORE_LISTENER_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include + +QT_BEGIN_NAMESPACE +class QWidget; +QT_END_NAMESPACE + +namespace Core +{ +/** +@interface ICoreListener +@brief The ICoreListener is an interface for providing a hook for plugins to veto on close event emitted from +the core plugin. +@details You implement this interface if you want to prevent the closing of the whole application. +If the application window requests a close, then first ICoreListener::closeMainWindow() is called +(in arbitrary order) on all registered objects implementing this interface. +If one if these calls returns false, the process is aborted and the event is ignored. If all calls return +true, the corresponding signal is emitted and the event is accepted/performed. + +You need to add your implementing object to the plugin managers objects: +PluginManager->addObject(yourImplementingObject); +Don't forget to remove the object again at deconstruction (e.g. in the destructor of +your plugin) +*/ +class CORE_EXPORT ICoreListener: public QObject +{ + Q_OBJECT +public: + ICoreListener(QObject *parent = 0): QObject(parent) {} + virtual ~ICoreListener() {} + + /// Return false from the implemented method if you want to prevent the event. + virtual bool closeMainWindow() const = 0; +}; + +} // namespace Core + + +#endif // ICORE_LISTENER_H diff --git a/code/studio/src/plugins/core/images/nel.png b/code/studio/src/plugins/core/images/nel.png new file mode 100644 index 0000000000000000000000000000000000000000..d2139bb2557984f999a563059ea00f7e76436293 GIT binary patch literal 15587 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 literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/images/preferences.png b/code/studio/src/plugins/core/images/preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..729bc039355928ae3b0c39969f6dbfea6154a125 GIT binary patch literal 10286 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 +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef IOPTIONS_PAGE_H +#define IOPTIONS_PAGE_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include + +QT_BEGIN_NAMESPACE +class QWidget; +class QIcon; +QT_END_NAMESPACE + +namespace Core +{ +/** +@interface IOptionsPage +@brief The IOptionsPage is an interface for providing options pages. +@details You need to subclass this interface and put an instance of your subclass + into the plugin manager object pool. +*/ +class CORE_EXPORT IOptionsPage: public QObject +{ + Q_OBJECT +public: + IOptionsPage(QObject *parent = 0): QObject(parent) {} + virtual ~IOptionsPage() {} + + /// id() is a unique identifier for referencing this page + virtual QString id() const = 0; + + /// trName() is the (translated) name for display. + virtual QString trName() const = 0; + + /// category() is the unique id for the category that the page should be displayed in + virtual QString category() const = 0; + + /// trCategory() is the translated category + virtual QString trCategory() const = 0; + + virtual QIcon categoryIcon() const = 0; + + /// createPage() is called to retrieve the widget to show in the preferences dialog + /// The widget will be destroyed by the widget hierarchy when the dialog closes + virtual QWidget *createPage(QWidget *parent) = 0; + + /// apply() is called to store the settings. It should detect if any changes have been made and store those. + virtual void apply() = 0; + + /// finish() is called directly before the preferences dialog closes + virtual void finish() = 0; +}; + +} // namespace Core + +#endif // IOPTIONS_PAGE_H diff --git a/code/studio/src/plugins/core/main_window.cpp b/code/studio/src/plugins/core/main_window.cpp new file mode 100644 index 000000000..a90e67bc0 --- /dev/null +++ b/code/studio/src/plugins/core/main_window.cpp @@ -0,0 +1,492 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "main_window.h" +#include "icontext.h" +#include "icore_listener.h" +#include "menu_manager.h" +#include "context_manager.h" +#include "core.h" +#include "core_constants.h" +#include "settings_dialog.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace Core +{ + +MainWindow::MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) + : QMainWindow(parent), + m_pluginManager(0), + m_menuManager(0), + m_contextManager(0), + m_coreImpl(0), + m_lastDir("."), + m_undoGroup(0), + m_settings(0) +{ + QCoreApplication::setApplicationName(QLatin1String("ObjectViewerQt")); + QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::OVQT_VERSION_LONG)); + QCoreApplication::setOrganizationName(QLatin1String("RyzomCore")); + + setObjectName(Constants::MAIN_WINDOW); + setWindowIcon(QIcon(Constants::ICON_PILL)); + setWindowTitle(tr("Object Viewer Qt")); + + m_pluginManager = pluginManager; + m_settings = m_pluginManager->settings(); + m_coreImpl = new CoreImpl(this); + +#ifdef Q_WS_MAC + m_menuBar = new QMenuBar(0); +#else + m_menuBar = new QMenuBar(this); + setMenuBar(m_menuBar); +#endif + + m_menuManager = new MenuManager(m_menuBar, this); + + m_tabWidget = new QTabWidget(this); + m_tabWidget->setTabPosition(QTabWidget::South); + m_tabWidget->setMovable(false); + m_tabWidget->setDocumentMode(true); + setCentralWidget(m_tabWidget); + + m_contextManager = new ContextManager(this, m_tabWidget); + + setDockNestingEnabled(true); + m_originalPalette = QApplication::palette(); + m_undoGroup = new QUndoGroup(this); + + createDialogs(); + createActions(); + createMenus(); + createStatusBar(); + resize(1024, 768); +} + +MainWindow::~MainWindow() +{ + m_pluginManager->removeObject(m_coreImpl); + m_pluginManager->removeObject(m_menuManager); + + delete m_coreImpl; + m_coreImpl = 0; +} + +bool MainWindow::initialize(QString *errorString) +{ + Q_UNUSED(errorString); + m_pluginManager->addObject(m_coreImpl); + m_pluginManager->addObject(m_menuManager); + return true; +} + +void MainWindow::extensionsInitialized() +{ + readSettings(); + connect(m_contextManager, SIGNAL(currentContextChanged(Core::IContext *)), + this, SLOT(updateContext(Core::IContext *))); + if (m_contextManager->currentContext() != NULL) + updateContext(m_contextManager->currentContext()); + show(); +} + +MenuManager *MainWindow::menuManager() const +{ + return m_menuManager; +} + +ContextManager *MainWindow::contextManager() const +{ + return m_contextManager; +} + +QSettings *MainWindow::settings() const +{ + return m_settings; +} + +QUndoGroup *MainWindow::undoGroup() const +{ + return m_undoGroup; +} + +ExtensionSystem::IPluginManager *MainWindow::pluginManager() const +{ + return m_pluginManager; +} + +void MainWindow::addContextObject(IContext *context) +{ + QUndoStack *stack = context->undoStack(); + if (stack) + m_undoGroup->addStack(stack); +} + +void MainWindow::removeContextObject(IContext *context) +{ + QUndoStack *stack = context->undoStack(); + if (stack) + m_undoGroup->removeStack(stack); +} + +void MainWindow::open() +{ + m_contextManager->currentContext()->open(); +} + +void MainWindow::newFile() +{ + m_contextManager->currentContext()->newDocument(); +} + +void MainWindow::save() +{ + m_contextManager->currentContext()->save(); +} + +void MainWindow::saveAs() +{ + m_contextManager->currentContext()->saveAs(); +} + +void MainWindow::saveAll() +{ +} + +void MainWindow::closeDocument() +{ + m_contextManager->currentContext()->close(); +} + + +void MainWindow::cut() +{ +} + +void MainWindow::copy() +{ +} + +void MainWindow::paste() +{ +} + +void MainWindow::del() +{ +} + +void MainWindow::find() +{ +} + +void MainWindow::gotoPos() +{ +} + +void MainWindow::setFullScreen(bool enabled) +{ + if (bool(windowState() & Qt::WindowFullScreen) == enabled) + return; + if (enabled) + setWindowState(windowState() | Qt::WindowFullScreen); + else + setWindowState(windowState() & ~Qt::WindowFullScreen); +} + +bool MainWindow::showOptionsDialog(const QString &group, + const QString &page, + QWidget *parent) +{ + if (!parent) + parent = this; + SettingsDialog settingsDialog(m_pluginManager, group, page, parent); + settingsDialog.show(); + bool ok = settingsDialog.execDialog(); + if (ok) + Q_EMIT m_coreImpl->changeSettings(); + return ok; +} + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Object Viewer Qt"), + tr("

Object Viewer Qt

" + "

Ryzom Core team

Compiled on %1 %2").arg(__DATE__).arg(__TIME__)); +} + +void MainWindow::updateContext(Core::IContext *context) +{ + m_undoGroup->setActiveStack(context->undoStack()); +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + QList listeners = m_pluginManager->getObjects(); + Q_FOREACH(ICoreListener *listener, listeners) + { + if (!listener->closeMainWindow()) + { + event->ignore(); + return; + } + } + Q_EMIT m_coreImpl->closeMainWindow(); + + writeSettings(); + event->accept(); +} + +void MainWindow::createActions() +{ + m_newAction = new QAction(tr("&New"), this); + m_newAction->setIcon(QIcon(Constants::ICON_NEW)); + m_newAction->setShortcut(QKeySequence::New); + menuManager()->registerAction(m_newAction, Constants::NEW); + connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile())); + m_newAction->setEnabled(false); + + m_openAction = new QAction(tr("&Open..."), this); + m_openAction->setIcon(QIcon(Constants::ICON_OPEN)); + m_openAction->setShortcut(QKeySequence::Open); + m_openAction->setStatusTip(tr("Open an existing file")); + menuManager()->registerAction(m_openAction, Constants::OPEN); + connect(m_openAction, SIGNAL(triggered()), this, SLOT(open())); + + m_saveAction = new QAction(tr("&Save"), this); + m_saveAction->setIcon(QIcon(Constants::ICON_SAVE)); + m_saveAction->setShortcut(QKeySequence::Save); + menuManager()->registerAction(m_saveAction, Constants::SAVE); + connect(m_saveAction, SIGNAL(triggered()), this, SLOT(save())); + m_saveAction->setEnabled(false); + + m_saveAsAction = new QAction(tr("Save &As..."), this); + m_saveAsAction->setIcon(QIcon(Constants::ICON_SAVE_AS)); + m_saveAsAction->setShortcut(QKeySequence::SaveAs); + menuManager()->registerAction(m_saveAsAction, Constants::SAVE_AS); + connect(m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); + m_saveAsAction->setEnabled(false); + + m_saveAllAction = new QAction(tr("&Save A&ll"), this); + m_saveAllAction->setShortcut(QKeySequence::SelectAll); + menuManager()->registerAction(m_saveAllAction, Constants::SAVE_ALL); + connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll())); + m_saveAllAction->setEnabled(false); + + m_closeAction = new QAction(tr("Close"), this); + m_closeAction->setShortcut(QKeySequence::Close); + menuManager()->registerAction(m_closeAction, Constants::CLOSE); + connect(m_closeAction, SIGNAL(triggered()), this, SLOT(closeDocument())); + m_closeAction->setEnabled(false); + + m_exitAction = new QAction(tr("E&xit"), this); + m_exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + m_exitAction->setStatusTip(tr("Exit the application")); + menuManager()->registerAction(m_exitAction, Constants::EXIT); + connect(m_exitAction, SIGNAL(triggered()), this, SLOT(close())); + + m_cutAction = new QAction(tr("Cu&t"), this); + m_cutAction->setShortcut(QKeySequence::Cut); + menuManager()->registerAction(m_cutAction, Constants::CUT); + connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cut())); + m_cutAction->setEnabled(false); + + m_copyAction = new QAction(tr("&Copy"), this); + m_copyAction->setShortcut(QKeySequence::Copy); + menuManager()->registerAction(m_copyAction, Constants::COPY); + connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copy())); + m_copyAction->setEnabled(false); + + m_pasteAction = new QAction(tr("&Paste"), this); + m_pasteAction->setShortcut(QKeySequence::Paste); + menuManager()->registerAction(m_pasteAction, Constants::PASTE); + connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); + m_pasteAction->setEnabled(false); + + m_delAction = new QAction(tr("&Delete"), this); + m_delAction->setShortcut(QKeySequence::Delete); + menuManager()->registerAction(m_delAction, Constants::DEL); + connect(m_delAction, SIGNAL(triggered()), this, SLOT(del())); + m_delAction->setEnabled(false); + + m_selectAllAction = new QAction(tr("Select &All"), this); + m_selectAllAction->setShortcut(QKeySequence::SelectAll); + menuManager()->registerAction(m_selectAllAction, Constants::SELECT_ALL); + connect(m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll())); + m_selectAllAction->setEnabled(false); + + m_findAction = new QAction(tr("&Find"), this); + m_findAction->setShortcut(QKeySequence::Find); + menuManager()->registerAction(m_findAction, Constants::FIND); + connect(m_findAction, SIGNAL(triggered()), this, SLOT(find())); + m_findAction->setEnabled(false); + + m_gotoAction = new QAction(tr("&Go To.."), this); + m_gotoAction->setShortcut(QKeySequence(tr("Ctrl+G"))); + menuManager()->registerAction(m_gotoAction, Constants::GOTO_POS); + connect(m_gotoAction, SIGNAL(triggered()), this, SLOT(gotoPos())); + m_gotoAction->setEnabled(false); + + m_fullscreenAction = new QAction(tr("Fullscreen"), this); + m_fullscreenAction->setCheckable(true); + m_fullscreenAction->setShortcut(QKeySequence(tr("Ctrl+Shift+F11"))); + menuManager()->registerAction(m_fullscreenAction, Constants::TOGGLE_FULLSCREEN); + connect(m_fullscreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool))); + + m_settingsAction = new QAction(tr("&Settings"), this); + m_settingsAction->setIcon(QIcon(":/images/preferences.png")); + m_settingsAction->setShortcut(QKeySequence::Preferences); + m_settingsAction->setStatusTip(tr("Open the settings dialog")); + menuManager()->registerAction(m_settingsAction, Constants::SETTINGS); + connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog())); + + m_aboutAction = new QAction(tr("&About"), this); + m_aboutAction->setStatusTip(tr("Show the application's About box")); + menuManager()->registerAction(m_aboutAction, Constants::ABOUT); + connect(m_aboutAction, SIGNAL(triggered()), this, SLOT(about())); + + m_aboutQtAction = new QAction(tr("About &Qt"), this); + m_aboutQtAction->setStatusTip(tr("Show the Qt library's About box")); + menuManager()->registerAction(m_aboutQtAction, Constants::ABOUT_QT); + connect(m_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + + m_pluginViewAction = new QAction(tr("About &Plugins"), this); + m_pluginViewAction->setStatusTip(tr("Show the plugin view dialog")); + menuManager()->registerAction(m_pluginViewAction, Constants::ABOUT_PLUGINS); + connect(m_pluginViewAction, SIGNAL(triggered()), m_pluginView, SLOT(show())); + +#ifdef Q_WS_MAC + m_exitAction->setMenuRole(QAction::QuitRole); + m_settingsAction->setMenuRole(QAction::PreferencesRole); + m_aboutAction->setMenuRole(QAction::AboutRole); + m_aboutQtAction->setMenuRole(QAction::AboutQtRole); + m_pluginViewAction->setMenuRole(QAction::ApplicationSpecificRole); +#endif +} + +void MainWindow::createMenus() +{ + m_fileMenu = m_menuBar->addMenu(tr("&File")); + menuManager()->registerMenu(m_fileMenu, Constants::M_FILE); + m_fileMenu->addAction(m_newAction); + m_fileMenu->addAction(m_openAction); + m_fileMenu->addSeparator(); + m_fileMenu->addAction(m_saveAction); + m_fileMenu->addAction(m_saveAsAction); + m_fileMenu->addAction(m_saveAllAction); + m_fileMenu->addAction(m_closeAction); + m_fileMenu->addSeparator(); + + m_recentFilesMenu = m_fileMenu->addMenu(tr("Recent &Files")); + m_recentFilesMenu->setEnabled(false); + menuManager()->registerMenu(m_recentFilesMenu, Constants::M_FILE_RECENTFILES); + + m_fileMenu->addSeparator(); + m_fileMenu->addAction(m_exitAction); + + m_editMenu = m_menuBar->addMenu(tr("&Edit")); + QAction *undoAction = m_undoGroup->createUndoAction(this); + menuManager()->registerAction(undoAction, Constants::UNDO); + undoAction->setIcon(QIcon(Constants::ICON_UNDO)); + undoAction->setShortcut(QKeySequence::Undo); + QAction *redoAction = m_undoGroup->createRedoAction(this); + menuManager()->registerAction(redoAction, Constants::REDO); + redoAction->setIcon(QIcon(Constants::ICON_REDO)); + redoAction->setShortcut(QKeySequence::Redo); + m_editMenu->addAction(undoAction); + m_editMenu->addAction(redoAction); + + m_editMenu->addSeparator(); + m_editMenu->addAction(m_cutAction); + m_editMenu->addAction(m_copyAction); + m_editMenu->addAction(m_pasteAction); + m_editMenu->addAction(m_delAction); + m_editMenu->addSeparator(); + m_editMenu->addAction(m_selectAllAction); + m_editMenu->addSeparator(); + m_editMenu->addAction(m_findAction); + m_editMenu->addAction(m_gotoAction); + menuManager()->registerMenu(m_editMenu, Constants::M_EDIT); + + m_viewMenu = m_menuBar->addMenu(tr("&View")); + m_viewMenu->addAction(m_fullscreenAction); + m_viewMenu->addAction(m_dockWidget->toggleViewAction()); + menuManager()->registerMenu(m_viewMenu, Constants::M_VIEW); + + m_toolsMenu = m_menuBar->addMenu(tr("&Tools")); + menuManager()->registerMenu(m_toolsMenu, Constants::M_TOOLS); + + m_sheetMenu = m_toolsMenu->addMenu(tr("&Sheet")); + menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); + +// m_toolsMenu->addSeparator(); + + m_toolsMenu->addAction(m_settingsAction); + + m_menuBar->addSeparator(); + + m_helpMenu = m_menuBar->addMenu(tr("&Help")); + menuManager()->registerMenu(m_helpMenu, Constants::M_HELP); + m_helpMenu->addAction(m_aboutAction); + m_helpMenu->addAction(m_aboutQtAction); + m_helpMenu->addAction(m_pluginViewAction); +} + +void MainWindow::createStatusBar() +{ + statusBar()->showMessage(tr("StatusReady")); +} + +void MainWindow::createDialogs() +{ + m_pluginView = new PluginView(m_pluginManager, this); + + // Create undo/redo command list + m_dockWidget = new QDockWidget("Command List", this); + m_dockWidget->setObjectName(QString::fromUtf8("UndoRedoCommandDockWidget")); + QUndoView *undoView = new QUndoView(m_undoGroup, m_dockWidget); + m_dockWidget->setWidget(undoView); + addDockWidget(Qt::RightDockWidgetArea, m_dockWidget); +} + +void MainWindow::readSettings() +{ + m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + restoreState(m_settings->value(Constants::MAIN_WINDOW_STATE).toByteArray()); + restoreGeometry(m_settings->value(Constants::MAIN_WINDOW_GEOMETRY).toByteArray()); + m_settings->endGroup(); +} + +void MainWindow::writeSettings() +{ + m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + m_settings->setValue(Constants::MAIN_WINDOW_STATE, saveState()); + m_settings->setValue(Constants::MAIN_WINDOW_GEOMETRY, saveGeometry()); + m_settings->endGroup(); +} + +} /* namespace Core */ + +/* end of file */ diff --git a/code/studio/src/plugins/core/main_window.h b/code/studio/src/plugins/core/main_window.h new file mode 100644 index 000000000..d258a5eba --- /dev/null +++ b/code/studio/src/plugins/core/main_window.h @@ -0,0 +1,147 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef MAIN_WINDOW_H +#define MAIN_WINDOW_H + +// Project includes +#include "../../extension_system/iplugin_manager.h" +#include "plugin_view_dialog.h" + +// STL includes + +// Qt includes +#include +#include +#include + +namespace Core +{ +class CSettingsDialog; +class CorePlugin; +class IContext; +class MenuManager; +class ContextManager; +class CoreImpl; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); + ~MainWindow(); + + bool initialize(QString *errorString); + void extensionsInitialized(); + + MenuManager *menuManager() const; + ContextManager *contextManager() const; + QSettings *settings() const; + QUndoGroup *undoGroup() const; + + ExtensionSystem::IPluginManager *pluginManager() const; + + void addContextObject(IContext *context); + void removeContextObject(IContext *context); + +public Q_SLOTS: + bool showOptionsDialog(const QString &group = QString(), + const QString &page = QString(), + QWidget *parent = 0); + void updateContext(Core::IContext *context); + +private Q_SLOTS: + void open(); + void newFile(); + void save(); + void saveAs(); + void saveAll(); + void closeDocument(); + void cut(); + void copy(); + void paste(); + void del(); + void find(); + void gotoPos(); + void setFullScreen(bool enabled); + void about(); + +protected: + virtual void closeEvent(QCloseEvent *event); + +private: + void createActions(); + void createMenus(); + void createStatusBar(); + void createDialogs(); + + void readSettings(); + void writeSettings(); + + ExtensionSystem::IPluginManager *m_pluginManager; + PluginView *m_pluginView; + MenuManager *m_menuManager; + ContextManager *m_contextManager; + CoreImpl *m_coreImpl; + + QPalette m_originalPalette; + QString m_lastDir; + + QDockWidget *m_dockWidget; + QUndoGroup *m_undoGroup; + QSettings *m_settings; + + QTimer *m_mainTimer; + QTimer *m_statusBarTimer; + + QTabWidget *m_tabWidget; + + QMenu *m_fileMenu; + QMenu *m_recentFilesMenu; + QMenu *m_editMenu; + QMenu *m_viewMenu; + QMenu *m_toolsMenu; + QMenu *m_helpMenu; + QMenuBar *m_menuBar; + QMenu *m_sheetMenu; + + QAction *m_newAction; + QAction *m_openAction; + QAction *m_saveAction; + QAction *m_saveAsAction; + QAction *m_saveAllAction; + QAction *m_closeAction; + QAction *m_exitAction; + QAction *m_cutAction; + QAction *m_copyAction; + QAction *m_pasteAction; + QAction *m_delAction; + QAction *m_selectAllAction; + QAction *m_findAction; + QAction *m_gotoAction; + QAction *m_fullscreenAction; + QAction *m_settingsAction; + QAction *m_pluginViewAction; + QAction *m_aboutAction; + QAction *m_aboutQtAction; + +};/* class MainWindow */ + +} /* namespace Core */ + +#endif // MAIN_WINDOW_H diff --git a/code/studio/src/plugins/core/menu_manager.cpp b/code/studio/src/plugins/core/menu_manager.cpp new file mode 100644 index 000000000..3e6272f0a --- /dev/null +++ b/code/studio/src/plugins/core/menu_manager.cpp @@ -0,0 +1,96 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "menu_manager.h" + +// NeL includes +#include + +namespace Core +{ +struct MenuManagerPrivate +{ + MenuManagerPrivate(): m_menuBar(0) {} + QMenuBar *m_menuBar; + typedef QHash IdMenuMap; + IdMenuMap m_menuMap; + typedef QHash IdActionMap; + IdActionMap m_actionMap; +}; + +MenuManager::MenuManager(QMenuBar *menuBar, QObject *parent) + : QObject(parent), + d(new MenuManagerPrivate()) +{ + d->m_menuBar = menuBar; +} + +MenuManager::~MenuManager() +{ + d->m_menuMap.clear(); + delete d; +} + +void MenuManager::registerMenu(QMenu *menu, const QString &id) +{ + menu->setObjectName(id); + d->m_menuMap.insert(id, menu); +} + +void MenuManager::registerAction(QAction *action, const QString &id) +{ + action->setObjectName(id); + d->m_actionMap.insert(id, action); +} + +QMenu *MenuManager::menu(const QString &id) const +{ + QMenu *result = 0; + if (!d->m_menuMap.contains(id)) + nlwarning("QMenu %s not found", id.toUtf8().constData()); + else + result = d->m_menuMap.value(id); + return result; +} + +QAction *MenuManager::action(const QString &id) const +{ + QAction *result = 0; + if (!d->m_actionMap.contains(id)) + nlwarning("QAction %s not found", id.toUtf8().constData()); + else + result = d->m_actionMap.value(id); + return result; +} + +void MenuManager::unregisterMenu(const QString &id) +{ + d->m_menuMap.remove(id); +} + +void MenuManager::unregisterAction(const QString &id) +{ + d->m_actionMap.remove(id); +} + +QMenuBar *MenuManager::menuBar() const +{ + return d->m_menuBar; +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/menu_manager.h b/code/studio/src/plugins/core/menu_manager.h new file mode 100644 index 000000000..fd6af8f3a --- /dev/null +++ b/code/studio/src/plugins/core/menu_manager.h @@ -0,0 +1,67 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef MENU_MANAGER_H +#define MENU_MANAGER_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +namespace Core +{ +struct MenuManagerPrivate; + +/* +@interface MenuManager +@brief The MenuManager provide the interface for registration of menus and menu item. +@details The MenuManager provides centralized access to menus and menu items. +All menus and menu items should be registered in the MenuManager. +*/ +class CORE_EXPORT MenuManager: public QObject +{ + Q_OBJECT + +public: + MenuManager(QMenuBar *menuBar, QObject *parent = 0); + virtual ~MenuManager(); + + void registerMenu(QMenu *menu, const QString &id); + void registerAction(QAction *action, const QString &id); + + QMenu *menu(const QString &id) const; + QAction *action(const QString &id) const; + + void unregisterMenu(const QString &id); + void unregisterAction(const QString &id); + + QMenuBar *menuBar() const; +private: + + MenuManagerPrivate *d; +}; + +} // namespace Core + +#endif // MENU_MANAGER_H diff --git a/code/studio/src/plugins/core/ovqt_plugin_core.xml b/code/studio/src/plugins/core/ovqt_plugin_core.xml new file mode 100644 index 000000000..2f5d6e9a8 --- /dev/null +++ b/code/studio/src/plugins/core/ovqt_plugin_core.xml @@ -0,0 +1,7 @@ + + ovqt_plugin_core + Core + 0.8 + Ryzom Core + Core plugin. + \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp new file mode 100644 index 000000000..175902d39 --- /dev/null +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -0,0 +1,108 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "plugin_view_dialog.h" +#include "core_constants.h" + +#include "nel/misc/debug.h" + +// Qt includes +#include +#include +#include +#include + +// Project includes +#include "../../extension_system/iplugin_spec.h" +#include "../../extension_system/iplugin_manager.h" + +namespace Core +{ + +PluginView::PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) + : QDialog(parent), + m_checkStateColumn(0) +{ + m_ui.setupUi(this); + m_pluginManager = pluginManager; + + connect(m_pluginManager, SIGNAL(pluginsChanged()), this, SLOT(updateList())); + connect(this, SIGNAL(accepted()), this, SLOT(updateSettings())); + + // WhiteList is list of plugins which can not disable. + m_whiteList << Constants::OVQT_CORE_PLUGIN; + updateList(); +} + +PluginView::~PluginView() +{ +} + +void PluginView::updateList() +{ + static QIcon okIcon = QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton); + static QIcon errorIcon = QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton); + static QIcon notLoadedIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton); + + m_specToItem.clear(); + + QList items; + Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) + { + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() + << spec->name() + << QString("%1").arg(spec->version()) + << spec->vendor() + << QDir::toNativeSeparators(spec->filePath())); + + bool ok = !spec->hasError(); + QIcon icon = ok ? okIcon : errorIcon; + if (ok && (spec->state() != ExtensionSystem::State::Running)) + icon = notLoadedIcon; + + item->setIcon(m_checkStateColumn, icon); + + if (!m_whiteList.contains(spec->name())) + item->setCheckState(m_checkStateColumn, spec->isEnabled() ? Qt::Checked : Qt::Unchecked); + + items.append(item); + m_specToItem.insert(spec, item); + } + + m_ui.pluginTreeWidget->clear(); + if (!items.isEmpty()) + m_ui.pluginTreeWidget->addTopLevelItems(items); + + m_ui.pluginTreeWidget->resizeColumnToContents(m_checkStateColumn); +} + +void PluginView::updateSettings() +{ + Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) + { + if (m_specToItem.contains(spec) && (!m_whiteList.contains(spec->name()))) + { + QTreeWidgetItem *item = m_specToItem.value(spec); + if (item->checkState(m_checkStateColumn) == Qt::Checked) + spec->setEnabled(true); + else + spec->setEnabled(false); + } + } +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.h b/code/studio/src/plugins/core/plugin_view_dialog.h new file mode 100644 index 000000000..aae16749d --- /dev/null +++ b/code/studio/src/plugins/core/plugin_view_dialog.h @@ -0,0 +1,58 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PLUGIN_VIEW_H +#define PLUGIN_VIEW_H + +#include "ui_plugin_view_dialog.h" + +#include +#include + +namespace ExtensionSystem +{ +class IPluginManager; +class IPluginSpec; +} + +namespace Core +{ + +class PluginView: public QDialog +{ + Q_OBJECT + +public: + PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); + ~PluginView(); + +private Q_SLOTS: + void updateList(); + void updateSettings(); + +private: + + const int m_checkStateColumn; + QMap m_specToItem; + QStringList m_whiteList; + ExtensionSystem::IPluginManager *m_pluginManager; + Ui::PluginView m_ui; +}; /* class PluginView */ + +} /* namespace Core */ + +#endif // PLUGIN_VIEW_H diff --git a/code/studio/src/plugins/core/plugin_view_dialog.ui b/code/studio/src/plugins/core/plugin_view_dialog.ui new file mode 100644 index 000000000..9d7d395be --- /dev/null +++ b/code/studio/src/plugins/core/plugin_view_dialog.ui @@ -0,0 +1,135 @@ + + + PluginView + + + + 0 + 0 + 756 + 296 + + + + About plugins + + + true + + + + + + true + + + 0 + + + false + + + true + + + false + + + true + + + + Name + + + + + Version + + + + + Vendor + + + + + Location + + + + + + + + false + + + Details + + + + + + + false + + + Error details + + + + + + + Qt::Horizontal + + + + 427 + 20 + + + + + + + + Close + + + + + + + false + + + All objects list + + + + + + + + + + + closePushButton + clicked() + PluginView + accept() + + + 620 + 232 + + + 507 + 226 + + + + + diff --git a/code/studio/src/plugins/core/qtwin.cpp b/code/studio/src/plugins/core/qtwin.cpp new file mode 100644 index 000000000..115203ded --- /dev/null +++ b/code/studio/src/plugins/core/qtwin.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#include "qtwin.h" +#include +#include +#include +#include +#include + +#ifdef Q_WS_WIN + +#include + +// Blur behind data structures +#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified +#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified +#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified +#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message + +typedef struct _DWM_BLURBEHIND +{ + DWORD dwFlags; + BOOL fEnable; + HRGN hRgnBlur; + BOOL fTransitionOnMaximized; +} DWM_BLURBEHIND, *PDWM_BLURBEHIND; + +typedef struct _MARGINS +{ + int cxLeftWidth; + int cxRightWidth; + int cyTopHeight; + int cyBottomHeight; +} MARGINS, *PMARGINS; + +typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL *pfEnabled); +typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset); +typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind); +typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); + +static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; +static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; +static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; +static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; + + +/* + * Internal helper class that notifies windows if the + * DWM compositing state changes and updates the widget + * flags correspondingly. + */ +class WindowNotifier : public QWidget +{ +public: + WindowNotifier() + { + winId(); + } + void addWidget(QWidget *widget) + { + widgets.append(widget); + } + void removeWidget(QWidget *widget) + { + widgets.removeAll(widget); + } + bool winEvent(MSG *message, long *result); + +private: + QWidgetList widgets; +}; + +static bool resolveLibs() +{ + if (!pDwmIsCompositionEnabled) + { + QLibrary dwmLib(QString::fromAscii("dwmapi")); + pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); + pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); + pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); + pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); + } + return pDwmIsCompositionEnabled != 0; +} + +#endif + +/*! + * Chekcs and returns true if Windows DWM composition + * is currently enabled on the system. + * + * To get live notification on the availability of + * this feature, you will currently have to + * reimplement winEvent() on your widget and listen + * for the WM_DWMCOMPOSITIONCHANGED event to occur. + * + */ +bool QtWin::isCompositionEnabled() +{ +#ifdef Q_WS_WIN + if (resolveLibs()) + { + HRESULT hr = S_OK; + BOOL isEnabled = false; + hr = pDwmIsCompositionEnabled(&isEnabled); + if (SUCCEEDED(hr)) + return isEnabled; + } +#endif + return false; +} + +/*! + * Enables Blur behind on a Widget. + * + * \a enable tells if the blur should be enabled or not + */ +bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable) +{ + Q_ASSERT(widget); + bool result = false; +#ifdef Q_WS_WIN + if (resolveLibs()) + { + DWM_BLURBEHIND bb = {0}; + HRESULT hr = S_OK; + bb.fEnable = enable; + bb.dwFlags = DWM_BB_ENABLE; + bb.hRgnBlur = NULL; + widget->setAttribute(Qt::WA_TranslucentBackground, enable); + widget->setAttribute(Qt::WA_NoSystemBackground, enable); + hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); + if (SUCCEEDED(hr)) + { + result = true; + windowNotifier()->addWidget(widget); + } + } +#endif + return result; +} + +/*! + * ExtendFrameIntoClientArea. + * + * This controls the rendering of the frame inside the window. + * Note that passing margins of -1 (the default value) will completely + * remove the frame from the window. + * + * \note you should not call enableBlurBehindWindow before calling + * this functions + * + * \a enable tells if the blur should be enabled or not + */ +bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) +{ + + Q_ASSERT(widget); + Q_UNUSED(left); + Q_UNUSED(top); + Q_UNUSED(right); + Q_UNUSED(bottom); + + bool result = false; +#ifdef Q_WS_WIN + if (resolveLibs()) + { + QLibrary dwmLib(QString::fromAscii("dwmapi")); + HRESULT hr = S_OK; + MARGINS m = {left, top, right, bottom}; + hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); + if (SUCCEEDED(hr)) + { + result = true; + windowNotifier()->addWidget(widget); + } + widget->setAttribute(Qt::WA_TranslucentBackground, result); + } +#endif + return result; +} + +/*! + * Returns the current colorizationColor for the window. + * + * \a enable tells if the blur should be enabled or not + */ +QColor QtWin::colorizatinColor() +{ + QColor resultColor = QApplication::palette().window().color(); + +#ifdef Q_WS_WIN + if (resolveLibs()) + { + DWORD color = 0; + BOOL opaque = FALSE; + QLibrary dwmLib(QString::fromAscii("dwmapi")); + HRESULT hr = S_OK; + hr = pDwmGetColorizationColor(&color, &opaque); + if (SUCCEEDED(hr)) + resultColor = QColor(color); + } +#endif + return resultColor; +} + +#ifdef Q_WS_WIN +WindowNotifier *QtWin::windowNotifier() +{ + static WindowNotifier *windowNotifierInstance = 0; + if (!windowNotifierInstance) + windowNotifierInstance = new WindowNotifier; + return windowNotifierInstance; +} + + +/* Notify all enabled windows that the DWM state changed */ +bool WindowNotifier::winEvent(MSG *message, long *result) +{ + if (message && message->message == WM_DWMCOMPOSITIONCHANGED) + { + bool compositionEnabled = QtWin::isCompositionEnabled(); + Q_FOREACH(QWidget * widget, widgets) + { + if (widget) + { + widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); + } + widget->update(); + } + } + return QWidget::winEvent(message, result); +} +#endif diff --git a/code/studio/src/plugins/core/qtwin.h b/code/studio/src/plugins/core/qtwin.h new file mode 100644 index 000000000..5692a34fb --- /dev/null +++ b/code/studio/src/plugins/core/qtwin.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#ifndef QTWIN_H +#define QTWIN_H + +#include +#include +/** + * This is a helper class for using the Desktop Window Manager + * functionality on Windows 7 and Windows Vista. On other platforms + * these functions will simply not do anything. + */ + +class WindowNotifier; + +class QtWin +{ +public: + static bool enableBlurBehindWindow(QWidget *widget, bool enable = true); + static bool extendFrameIntoClientArea(QWidget *widget, + int left = -1, int top = -1, + int right = -1, int bottom = -1); + static bool isCompositionEnabled(); + static QColor colorizatinColor(); + +private: + static WindowNotifier *windowNotifier(); +}; + +#endif // QTWIN_H diff --git a/code/studio/src/plugins/core/search_paths_settings_page.cpp b/code/studio/src/plugins/core/search_paths_settings_page.cpp new file mode 100644 index 000000000..e76d6c796 --- /dev/null +++ b/code/studio/src/plugins/core/search_paths_settings_page.cpp @@ -0,0 +1,219 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "search_paths_settings_page.h" +#include "core_constants.h" +#include "icore.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace Core +{ + +QString lastDir = "."; + +SearchPathsSettingsPage::SearchPathsSettingsPage(bool recurse, QObject *parent) + : IOptionsPage(parent), + m_recurse(recurse), + m_page(0) +{ +} + +SearchPathsSettingsPage::~SearchPathsSettingsPage() +{ +} + +QString SearchPathsSettingsPage::id() const +{ + if (m_recurse) + return QLatin1String("search_recurse_paths"); + else + return QLatin1String("search_paths"); +} + +QString SearchPathsSettingsPage::trName() const +{ + if (m_recurse) + return tr("Search Recurse Paths"); + else + return tr("Search Paths"); +} + +QString SearchPathsSettingsPage::category() const +{ + return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); +} + +QString SearchPathsSettingsPage::trCategory() const +{ + return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); +} + +QIcon SearchPathsSettingsPage::categoryIcon() const +{ + return QIcon(); +} + +QWidget *SearchPathsSettingsPage::createPage(QWidget *parent) +{ + m_page = new QWidget(parent); + m_ui.setupUi(m_page); + + readSettings(); + checkEnabledButton(); + connect(m_ui.addToolButton, SIGNAL(clicked()), this, SLOT(addPath())); + connect(m_ui.removeToolButton, SIGNAL(clicked()), this, SLOT(delPath())); + connect(m_ui.upToolButton, SIGNAL(clicked()), this, SLOT(upPath())); + connect(m_ui.downToolButton, SIGNAL(clicked()), this, SLOT(downPath())); + connect(m_ui.resetToolButton, SIGNAL(clicked()), m_ui.pathsListWidget, SLOT(clear())); + return m_page; +} + +void SearchPathsSettingsPage::apply() +{ + writeSettings(); + applySearchPaths(); +} + +void SearchPathsSettingsPage::finish() +{ + delete m_page; + m_page = 0; +} + +void SearchPathsSettingsPage::applySearchPaths() +{ + QStringList paths, remapExt; + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + if (m_recurse) + paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); + else + paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); + + remapExt = settings->value(Core::Constants::REMAP_EXTENSIONS).toStringList(); + settings->endGroup(); + + for (int i = 1; i < remapExt.size(); i += 2) + NLMISC::CPath::remapExtension(remapExt.at(i - 1).toUtf8().constData(), remapExt.at(i).toUtf8().constData(), true); + + Q_FOREACH(QString path, paths) + { + NLMISC::CPath::addSearchPath(path.toUtf8().constData(), m_recurse, false); + } +} + +void SearchPathsSettingsPage::addPath() +{ + QString newPath = QFileDialog::getExistingDirectory(m_page, "", lastDir); + if (!newPath.isEmpty()) + { + QListWidgetItem *newItem = new QListWidgetItem; + newItem->setText(newPath); + newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + m_ui.pathsListWidget->addItem(newItem); + lastDir = newPath; + } + + checkEnabledButton(); +} + +void SearchPathsSettingsPage::delPath() +{ + QListWidgetItem *removeItem = m_ui.pathsListWidget->takeItem(m_ui.pathsListWidget->currentRow()); + if (!removeItem) + delete removeItem; + + checkEnabledButton(); +} + +void SearchPathsSettingsPage::upPath() +{ + int currentRow = m_ui.pathsListWidget->currentRow(); + if (!(currentRow == 0)) + { + QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); + m_ui.pathsListWidget->insertItem(--currentRow, item); + m_ui.pathsListWidget->setCurrentRow(currentRow); + } +} + +void SearchPathsSettingsPage::downPath() +{ + int currentRow = m_ui.pathsListWidget->currentRow(); + if (!(currentRow == m_ui.pathsListWidget->count()-1)) + { + QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); + m_ui.pathsListWidget->insertItem(++currentRow, item); + m_ui.pathsListWidget->setCurrentRow(currentRow); + } +} + +void SearchPathsSettingsPage::readSettings() +{ + QStringList paths; + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + if (m_recurse) + paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); + else + paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); + settings->endGroup(); + Q_FOREACH(QString path, paths) + { + QListWidgetItem *newItem = new QListWidgetItem; + newItem->setText(path); + newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + m_ui.pathsListWidget->addItem(newItem); + } +} + +void SearchPathsSettingsPage::writeSettings() +{ + QStringList paths; + for (int i = 0; i < m_ui.pathsListWidget->count(); ++i) + paths << m_ui.pathsListWidget->item(i)->text(); + + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + if (m_recurse) + settings->setValue(Core::Constants::RECURSIVE_SEARCH_PATHS, paths); + else + settings->setValue(Core::Constants::SEARCH_PATHS, paths); + settings->endGroup(); + settings->sync(); +} + +void SearchPathsSettingsPage::checkEnabledButton() +{ + bool bEnabled = true; + if (m_ui.pathsListWidget->count() == 0) + bEnabled = false; + + m_ui.removeToolButton->setEnabled(bEnabled); + m_ui.upToolButton->setEnabled(bEnabled); + m_ui.downToolButton->setEnabled(bEnabled); +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/search_paths_settings_page.h b/code/studio/src/plugins/core/search_paths_settings_page.h new file mode 100644 index 000000000..c45b29571 --- /dev/null +++ b/code/studio/src/plugins/core/search_paths_settings_page.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef SEARCH_PATHS_SETTINGS_PAGE_H +#define SEARCH_PATHS_SETTINGS_PAGE_H + +#include + +#include "ioptions_page.h" + +#include "ui_search_paths_settings_page.h" + +class QWidget; + +namespace Core +{ +/** +@class SearchPathsSettingsPage +*/ +class SearchPathsSettingsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + explicit SearchPathsSettingsPage(bool recurse, QObject *parent = 0); + ~SearchPathsSettingsPage(); + + QString id() const; + QString trName() const; + QString category() const; + QString trCategory() const; + QIcon categoryIcon() const; + QWidget *createPage(QWidget *parent); + + void apply(); + void finish(); + + // Set of the search paths(not recursive) and the remap extensions (loading from settings file) + void applySearchPaths(); + +private Q_SLOTS: + void addPath(); + void delPath(); + void upPath(); + void downPath(); + +private: + void readSettings(); + void writeSettings(); + void checkEnabledButton(); + + bool m_recurse; + QWidget *m_page; + Ui::SearchPathsSettingsPage m_ui; +}; + +} // namespace Core + +#endif // SEARCH_PATHS_SETTINGS_H diff --git a/code/studio/src/plugins/core/search_paths_settings_page.ui b/code/studio/src/plugins/core/search_paths_settings_page.ui new file mode 100644 index 000000000..cf47314b8 --- /dev/null +++ b/code/studio/src/plugins/core/search_paths_settings_page.ui @@ -0,0 +1,198 @@ + + + SearchPathsSettingsPage + + + + 0 + 0 + 431 + 285 + + + + Form + + + + 6 + + + 3 + + + + + Search paths + + + + + + + Qt::Horizontal + + + + 228 + 20 + + + + + + + + 3 + + + + + + 0 + 0 + + + + Add + + + + + + + :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png + + + + 20 + 20 + + + + true + + + + + + + + 0 + 0 + + + + Delete + + + + + + + :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png + + + + 20 + 20 + + + + true + + + + + + + + 0 + 0 + + + + Up + + + + + + + :/core/icons/ic_nel_up_item.png:/core/icons/ic_nel_up_item.png + + + + 20 + 20 + + + + true + + + + + + + + 0 + 0 + + + + Down + + + + + + + :/core/icons/ic_nel_down_item.png:/core/icons/ic_nel_down_item.png + + + + 20 + 20 + + + + true + + + + + + + Reset + + + + + + + :/core/icons/ic_nel_reset_all.png:/core/icons/ic_nel_reset_all.png + + + + 20 + 20 + + + + true + + + + + + + + + + + + + + + diff --git a/code/studio/src/plugins/core/settings_dialog.cpp b/code/studio/src/plugins/core/settings_dialog.cpp new file mode 100644 index 000000000..4b7bbac3a --- /dev/null +++ b/code/studio/src/plugins/core/settings_dialog.cpp @@ -0,0 +1,182 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "settings_dialog.h" +#include "ioptions_page.h" + +// Qt includes +#include +#include + +struct PageData +{ + int index; + QString category; + QString id; +}; + +Q_DECLARE_METATYPE(PageData); + +namespace Core +{ +SettingsDialog::SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, + const QString &categoryId, + const QString &pageId, + QWidget *parent) + : QDialog(parent), + m_applied(false) +{ + m_ui.setupUi(this); + + m_plugMan = pluginManager; + + QString initialCategory = categoryId; + QString initialPage = pageId; + + m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + + connect(m_ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); + + m_ui.splitter->setCollapsible(1, false); + m_ui.pageTree->header()->setVisible(false); + + connect(m_ui.pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(pageSelected())); + + QMap categories; + + QList pages = m_plugMan->getObjects(); + + int index = 0; + Q_FOREACH(IOptionsPage *page, pages) + { + PageData pageData; + pageData.index = index; + pageData.category = page->category(); + pageData.id = page->id(); + + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, page->trName()); + item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + + QStringList categoriesId = page->category().split(QLatin1Char('|')); + QStringList trCategories = page->trCategory().split(QLatin1Char('|')); + QString currentCategory = categoriesId.at(0); + + QTreeWidgetItem *treeitem; + if (!categories.contains(currentCategory)) + { + treeitem = new QTreeWidgetItem(m_ui.pageTree); + treeitem->setText(0, trCategories.at(0)); + treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + categories.insert(currentCategory, treeitem); + } + + int catCount = 1; + while (catCount < categoriesId.count()) + { + if (!categories.contains(currentCategory + QLatin1Char('|') + categoriesId.at(catCount))) + { + treeitem = new QTreeWidgetItem(categories.value(currentCategory)); + currentCategory += QLatin1Char('|') + categoriesId.at(catCount); + treeitem->setText(0, trCategories.at(catCount)); + treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + categories.insert(currentCategory, treeitem); + } + else + { + currentCategory += QLatin1Char('|') + categoriesId.at(catCount); + } + ++catCount; + } + + categories.value(currentCategory)->addChild(item); + + m_pages.append(page); + m_ui.stackedPages->addWidget(page->createPage(m_ui.stackedPages)); + + if (page->id() == initialPage && currentCategory == initialCategory) + { + m_ui.stackedPages->setCurrentIndex(m_ui.stackedPages->count()); + m_ui.pageTree->setCurrentItem(item); + } + + index++; + } + + QList sizes; + sizes << 150 << 300; + m_ui.splitter->setSizes(sizes); + + m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.pageTree), 0); + m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.layoutWidget), 1); +} + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::pageSelected() +{ + QTreeWidgetItem *item = m_ui.pageTree->currentItem(); + PageData data = item->data(0, Qt::UserRole).value(); + int index = data.index; + m_currentCategory = data.category; + m_currentPage = data.id; + m_ui.stackedPages->setCurrentIndex(index); +} + +void SettingsDialog::accept() +{ + m_applied = true; + Q_FOREACH(IOptionsPage *page, m_pages) + { + page->apply(); + page->finish(); + } + done(QDialog::Accepted); +} + +void SettingsDialog::reject() +{ + Q_FOREACH(IOptionsPage *page, m_pages) + page->finish(); + done(QDialog::Rejected); +} + +void SettingsDialog::apply() +{ + Q_FOREACH(IOptionsPage *page, m_pages) + page->apply(); + m_applied = true; +} + +bool SettingsDialog::execDialog() +{ + m_applied = false; + exec(); + return m_applied; +} + +void SettingsDialog::done(int val) +{ + QDialog::done(val); +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/settings_dialog.h b/code/studio/src/plugins/core/settings_dialog.h new file mode 100644 index 000000000..9e1c86444 --- /dev/null +++ b/code/studio/src/plugins/core/settings_dialog.h @@ -0,0 +1,75 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SETTINGS_DIALOG_H +#define SETTINGS_DIALOG_H + +#include "ui_settings_dialog.h" + +// Qt includes +#include + +// Project includes +#include "../../extension_system/iplugin_manager.h" + +namespace Core +{ +class IOptionsPage; + +/** +@class CSettingsDialog +@brief Settings dialog +*/ +class SettingsDialog: public QDialog +{ + Q_OBJECT + +public: + SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, + const QString &initialCategory = QString(), + const QString &initialPage = QString(), + QWidget *parent = 0); + + ~SettingsDialog(); + + /// Run the dialog and return true if 'Ok' was choosen or 'Apply' was invoked at least once + bool execDialog(); + +public Q_SLOTS: + void done(int); + +private Q_SLOTS: + void pageSelected(); + void accept(); + void reject(); + void apply(); + +private: + QList m_pages; + bool m_applied; + QString m_currentCategory; + QString m_currentPage; + + ExtensionSystem::IPluginManager *m_plugMan; + + Ui::SettingsDialog m_ui; +}; /* class CSettingsDialog */ + +} /* namespace Core */ + +#endif // SETTINGS_DIALOG_H diff --git a/code/studio/src/plugins/core/settings_dialog.ui b/code/studio/src/plugins/core/settings_dialog.ui new file mode 100644 index 000000000..8e9780c9a --- /dev/null +++ b/code/studio/src/plugins/core/settings_dialog.ui @@ -0,0 +1,126 @@ + + + SettingsDialog + + + + 0 + 0 + 697 + 476 + + + + Settings + + + + :/core/images/preferences.png:/core/images/preferences.png + + + + 6 + + + 9 + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + 1 + + + + 0 + + + + + + + 6 + + + 0 + + + + + + 350 + 250 + + + + + + + + Qt::Horizontal + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + SettingsDialog + accept() + + + 297 + 361 + + + 297 + 193 + + + + + buttonBox + rejected() + SettingsDialog + reject() + + + 297 + 361 + + + 297 + 193 + + + + + From e6569049e9ac2eaab30ad546aadfa0a94972e093 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 7 May 2014 00:53:07 +0200 Subject: [PATCH 022/282] Same as before... --HG-- branch : gsoc2014-dfighter --- .hgignore | 1 - code/studio/src/plugins/core/core.cpp | 77 +++++++++++++++++++++++++++ code/studio/src/plugins/core/core.h | 54 +++++++++++++++++++ code/studio/src/plugins/core/core.qrc | 21 ++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/core/core.cpp create mode 100644 code/studio/src/plugins/core/core.h create mode 100644 code/studio/src/plugins/core/core.qrc diff --git a/.hgignore b/.hgignore index 5587652fd..6b7285bac 100644 --- a/.hgignore +++ b/.hgignore @@ -43,7 +43,6 @@ default_c *.so *.so.* *_debug -core.* *.pc *.gch diff --git a/code/studio/src/plugins/core/core.cpp b/code/studio/src/plugins/core/core.cpp new file mode 100644 index 000000000..b21d934c8 --- /dev/null +++ b/code/studio/src/plugins/core/core.cpp @@ -0,0 +1,77 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "core.h" +#include "context_manager.h" +#include "main_window.h" +#include "../../extension_system/iplugin_manager.h" + +static Core::CoreImpl *m_coreInstance = 0; + +namespace Core +{ + +ICore *ICore::instance() +{ + return m_coreInstance; +} + +CoreImpl::CoreImpl(MainWindow *mainWindow) +{ + m_mainWindow = mainWindow; + m_coreInstance = this; +} + +CoreImpl::~CoreImpl() +{ + m_coreInstance = 0; +} + +bool CoreImpl::showOptionsDialog(const QString &group, + const QString &page, + QWidget *parent) +{ + return m_mainWindow->showOptionsDialog(group, page, parent); +} + +MenuManager *CoreImpl::menuManager() const +{ + return m_mainWindow->menuManager(); +} + +ContextManager *CoreImpl::contextManager() const +{ + return m_mainWindow->contextManager(); +} + +QSettings *CoreImpl::settings() const +{ + return m_mainWindow->settings(); +} + +QMainWindow *CoreImpl::mainWindow() const +{ + return m_mainWindow; +} + +ExtensionSystem::IPluginManager *CoreImpl::pluginManager() const +{ + return m_mainWindow->pluginManager(); +} + +} // namespace Core diff --git a/code/studio/src/plugins/core/core.h b/code/studio/src/plugins/core/core.h new file mode 100644 index 000000000..f34dd6ae6 --- /dev/null +++ b/code/studio/src/plugins/core/core.h @@ -0,0 +1,54 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_H +#define CORE_H + +#include "icore.h" + +namespace Core +{ +class MainWindow; + +class CoreImpl : public ICore +{ + Q_OBJECT + +public: + explicit CoreImpl(MainWindow *mainWindow); + virtual ~CoreImpl(); + + virtual bool showOptionsDialog(const QString &group = QString(), + const QString &page = QString(), + QWidget *parent = 0); + + virtual MenuManager *menuManager() const; + virtual ContextManager *contextManager() const; + + virtual QSettings *settings() const; + virtual QMainWindow *mainWindow() const; + + virtual ExtensionSystem::IPluginManager *pluginManager() const; +private: + MainWindow *m_mainWindow; + friend class MainWindow; +}; + +} // namespace Core + +#endif // CORE_H diff --git a/code/studio/src/plugins/core/core.qrc b/code/studio/src/plugins/core/core.qrc new file mode 100644 index 000000000..68b6ad141 --- /dev/null +++ b/code/studio/src/plugins/core/core.qrc @@ -0,0 +1,21 @@ + + + icons/ic_nel_add_item.png + icons/ic_nel_redo.png + icons/ic_nel_undo.png + icons/ic_nel_crash.png + icons/ic_nel_delete_item.png + icons/ic_nel_down_item.png + icons/ic_nel_generic_settings.png + icons/ic_nel_open.png + icons/ic_nel_new.png + icons/ic_nel_save.png + icons/ic_nel_save_as.png + icons/ic_nel_path_settings.png + icons/ic_nel_pill.png + icons/ic_nel_reset_all.png + icons/ic_nel_up_item.png + images/nel.png + images/preferences.png + + From 3440c7081b697bf4d89134012f8f8939878f8b42 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 18 May 2014 21:47:31 +0200 Subject: [PATCH 024/282] Renamed ovqt and ovqt plugin binaries. --HG-- branch : gsoc2014-dfighter --- code/studio/CMakeLists.txt | 6 +-- code/studio/src/CMakeLists.txt | 38 +++++++++---------- .../src/plugins/bnp_manager/CMakeLists.txt | 12 +++--- .../bnp_manager/ovqt_plugin_bnp_manager.xml | 2 +- code/studio/src/plugins/core/CMakeLists.txt | 18 ++++----- .../src/plugins/core/ovqt_plugin_core.xml | 2 +- .../src/plugins/disp_sheet_id/CMakeLists.txt | 20 +++++----- .../ovqt_plugin_disp_sheet_id.xml | 2 +- .../studio/src/plugins/example/CMakeLists.txt | 18 ++++----- .../plugins/example/ovqt_plugin_example.xml | 2 +- .../src/plugins/georges_editor/CMakeLists.txt | 20 +++++----- .../ovqt_plugin_georges_editor.xml | 2 +- .../src/plugins/gui_editor/CMakeLists.txt | 20 +++++----- .../gui_editor/ovqt_plugin_gui_editor.xml | 2 +- .../plugins/landscape_editor/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_landscape_editor.xml | 2 +- code/studio/src/plugins/log/CMakeLists.txt | 18 ++++----- .../src/plugins/log/ovqt_plugin_log.xml | 2 +- .../plugins/mission_compiler/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_mission_compiler.xml | 2 +- .../src/plugins/object_viewer/CMakeLists.txt | 22 +++++------ .../ovqt_plugin_object_viewer.xml | 2 +- .../plugins/ovqt_sheet_builder/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_sheet_builder.xml | 2 +- .../src/plugins/tile_editor/CMakeLists.txt | 14 +++---- .../tile_editor/ovqt_plugin_tile_editor.xml | 2 +- .../translation_manager/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_translation_manager.xml | 2 +- .../src/plugins/world_editor/CMakeLists.txt | 22 +++++------ .../world_editor/ovqt_plugin_world_editor.xml | 2 +- .../src/plugins/zone_painter/CMakeLists.txt | 18 ++++----- .../zone_painter/ovqt_plugin_zone_painter.xml | 2 +- 32 files changed, 174 insertions(+), 174 deletions(-) diff --git a/code/studio/CMakeLists.txt b/code/studio/CMakeLists.txt index ff1128b9f..b301430cf 100644 --- a/code/studio/CMakeLists.txt +++ b/code/studio/CMakeLists.txt @@ -16,9 +16,9 @@ ELSEIF(APPLE) SET(OVQT_PLUGIN_DIR "plugins") SET(OVQT_DATA_DIR ".") ELSE(WIN32) - SET(OVQT_PLUGIN_SPECS_DIR ${NL_SHARE_PREFIX}/object_viewer_qt/plugins) - SET(OVQT_PLUGIN_DIR ${NL_LIB_PREFIX}/object_viewer_qt) - SET(OVQT_DATA_DIR ${NL_SHARE_PREFIX}/object_viewer_qt/data) + SET(OVQT_PLUGIN_SPECS_DIR ${NL_SHARE_PREFIX}/studio/plugins) + SET(OVQT_PLUGIN_DIR ${NL_LIB_PREFIX}/studio) + SET(OVQT_DATA_DIR ${NL_SHARE_PREFIX}/studio/data) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ovqt_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/ovqt_config.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index d77b0e6a1..cc0c5d452 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -5,16 +5,16 @@ INCLUDE( ${QT_USE_FILE} ) CONFIGURE_FILE(translations/translations.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc COPYONLY) -FILE(GLOB OBJECT_VIEWER_SRC extension_system/*.h +FILE(GLOB STUDIO_SRC extension_system/*.h extension_system/*.cpp *.h *.cpp) -SET(OBJECT_VIEWER_HDR extension_system/iplugin_manager.h +SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h) -SET(OBJECT_VIEWER_RCS object_viewer_qt.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) +SET(STUDIO_RCS object_viewer_qt.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) -SET(OBJECT_VIEWER_TS translations/object_viewer_qt_en.ts +SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_fr.ts translations/object_viewer_qt_de.ts translations/object_viewer_qt_ru.ts) @@ -23,31 +23,31 @@ SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) IF(WIN32) - SET(OBJECT_VIEWER_RC object_viewer_qt.rc) + SET(STUDIO object_viewer_qt.rc) ENDIF(WIN32) -QT4_ADD_TRANSLATION(OBJECT_VIEWER_QM ${OBJECT_VIEWER_TS}) -QT4_ADD_RESOURCES( OBJECT_VIEWER_RC_SRCS ${OBJECT_VIEWER_RCS}) -QT4_WRAP_CPP( OBJECT_VIEWER_MOC_SRCS ${OBJECT_VIEWER_HDR} ) +QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) +QT4_ADD_RESOURCES( STUDIO_RC_SRCS ${STUDIO_RCS}) +QT4_WRAP_CPP( STUDIO_MOC_SRCS ${STUDIO_HDR} ) -SOURCE_GROUP(QtResources FILES ${OBJECT_VIEWER_RCS}) -SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OBJECT_VIEWER_MOC_SRCS} ${OBJECT_VIEWER_RC_SRCS}) +SOURCE_GROUP(QtResources FILES ${STUDIO_RCS}) +SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${STUDIO_MOC_SRCS} ${STUDIO_RC_SRCS}) -ADD_EXECUTABLE(object_viewer_qt WIN32 MACOSX_BUNDLE - ${OBJECT_VIEWER_SRC} - ${OBJECT_VIEWER_MOC_SRCS} - ${OBJECT_VIEWER_RC_SRCS} - ${OBJECT_VIEWER_RC}) +ADD_EXECUTABLE(studio WIN32 MACOSX_BUNDLE + ${STUDIO_SRC} + ${STUDIO_MOC_SRCS} + ${STUDIO_RC_SRCS} + ${STUDIO_RC}) -TARGET_LINK_LIBRARIES(object_viewer_qt +TARGET_LINK_LIBRARIES(studio nelmisc ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY}) ADD_DEFINITIONS(-DQT_NO_KEYWORDS ${LIBXML2_DEFINITIONS} ${QT_DEFINITIONS}) -NL_DEFAULT_PROPS(object_viewer_qt "NeL, Tools, 3D: Object Viewer Qt") -NL_ADD_RUNTIME_FLAGS(object_viewer_qt) +NL_DEFAULT_PROPS(studio "Tools: Studio") +NL_ADD_RUNTIME_FLAGS(studio) ADD_SUBDIRECTORY(plugins) -INSTALL(TARGETS object_viewer_qt RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT runtime BUNDLE DESTINATION /Applications) +INSTALL(TARGETS studio RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT runtime BUNDLE DESTINATION /Applications) diff --git a/code/studio/src/plugins/bnp_manager/CMakeLists.txt b/code/studio/src/plugins/bnp_manager/CMakeLists.txt index 2991da073..be56bc704 100644 --- a/code/studio/src/plugins/bnp_manager/CMakeLists.txt +++ b/code/studio/src/plugins/bnp_manager/CMakeLists.txt @@ -34,16 +34,16 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_BNP_MANAGER_MOC_SRC}) SOURCE_GROUP("BNP Manager Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_bnp_manager MODULE ${SRC} ${OVQT_PLUG_BNP_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_BNP_MANAGER_RC_SRCS} ${OVQT_PLUG_BNP_MANAGER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_bnp_manager MODULE ${SRC} ${OVQT_PLUG_BNP_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_BNP_MANAGER_RC_SRCS} ${OVQT_PLUG_BNP_MANAGER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_bnp_manager ovqt_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_bnp_manager studio_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_bnp_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: BNP Manager") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_bnp_manager) -NL_ADD_LIB_SUFFIX(ovqt_plugin_bnp_manager) +NL_DEFAULT_PROPS(studio_plugin_bnp_manager "Tools: Studio Plugin: BNP Manager") +NL_ADD_RUNTIME_FLAGS(studio_plugin_bnp_manager) +NL_ADD_LIB_SUFFIX(studio_plugin_bnp_manager) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS ovqt_plugin_bnp_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) +INSTALL(TARGETS studio_plugin_bnp_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_bnp_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml b/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml index a368a123c..591611504 100644 --- a/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml +++ b/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml @@ -1,5 +1,5 @@ - ovqt_plugin_bnp_manager + studio_plugin_bnp_manager BNPManager 0.1 Krolock diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index 5a20ba46c..add4665bc 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -45,27 +45,27 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) SOURCE_GROUP("Core Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) +ADD_LIBRARY(studio_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_core nelmisc ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) -NL_ADD_LIB_SUFFIX(ovqt_plugin_core) +NL_DEFAULT_PROPS(studio_plugin_core "Tools: Studio Plugin: Core") +NL_ADD_RUNTIME_FLAGS(studio_plugin_core) +NL_ADD_LIB_SUFFIX(studio_plugin_core) ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/core/ovqt_plugin_core.xml b/code/studio/src/plugins/core/ovqt_plugin_core.xml index 2f5d6e9a8..335ed8845 100644 --- a/code/studio/src/plugins/core/ovqt_plugin_core.xml +++ b/code/studio/src/plugins/core/ovqt_plugin_core.xml @@ -1,5 +1,5 @@ - ovqt_plugin_core + studio_plugin_core Core 0.8 Ryzom Core diff --git a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt index 7e5c0e409..65f880f07 100644 --- a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt +++ b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt @@ -26,32 +26,32 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_DISP_SHEET_ID_PLUGIN_MOC_SRC}) SOURCE_GROUP("Display sheet id Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_disp_sheet_id MODULE ${SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_UI_HDRS}) +ADD_LIBRARY(studio_plugin_disp_sheet_id MODULE ${SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_disp_sheet_id ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_disp_sheet_id studio_plugin_core nelmisc ${QT_LIBRARIES}) IF(WITH_STLPORT) - TARGET_LINK_LIBRARIES(ovqt_plugin_disp_sheet_id ${CMAKE_THREAD_LIBS_INIT}) + TARGET_LINK_LIBRARIES(studio_plugin_disp_sheet_id ${CMAKE_THREAD_LIBS_INIT}) ENDIF(WITH_STLPORT) -NL_DEFAULT_PROPS(ovqt_plugin_disp_sheet_id "NeL, Tools, 3D: Object Viewer Qt Plugin: Display sheet id") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_disp_sheet_id) -NL_ADD_LIB_SUFFIX(ovqt_plugin_disp_sheet_id) +NL_DEFAULT_PROPS(studio_plugin_disp_sheet_id "Tools: Studio Plugin: Display sheet id") +NL_ADD_RUNTIME_FLAGS(studio_plugin_disp_sheet_id) +NL_ADD_LIB_SUFFIX(studio_plugin_disp_sheet_id) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml b/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml index 173ce4479..4ac055b1a 100644 --- a/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml +++ b/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml @@ -1,5 +1,5 @@ - ovqt_plugin_disp_sheet_id + studio_plugin_disp_sheet_id DisplaySheetId 1.0 pemeon diff --git a/code/studio/src/plugins/example/CMakeLists.txt b/code/studio/src/plugins/example/CMakeLists.txt index 27e8698df..9eda8916e 100644 --- a/code/studio/src/plugins/example/CMakeLists.txt +++ b/code/studio/src/plugins/example/CMakeLists.txt @@ -28,27 +28,27 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_EXAMPLE_MOC_SRC}) SOURCE_GROUP("Example Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_example MODULE ${SRC} ${OVQT_PLUG_EXAMPLE_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_EXAMPLE_UI_HDRS}) +ADD_LIBRARY(studio_plugin_example MODULE ${SRC} ${OVQT_PLUG_EXAMPLE_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_EXAMPLE_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_example ovqt_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_example studio_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_example "NeL, Tools, 3D: Object Viewer Qt Plugin: Example") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_example) -NL_ADD_LIB_SUFFIX(ovqt_plugin_example) +NL_DEFAULT_PROPS(studio_plugin_example "Tools: Studio Plugin: Example") +NL_ADD_RUNTIME_FLAGS(studio_plugin_example) +NL_ADD_LIB_SUFFIX(studio_plugin_example) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/example/ovqt_plugin_example.xml b/code/studio/src/plugins/example/ovqt_plugin_example.xml index ae6664d52..434e37907 100644 --- a/code/studio/src/plugins/example/ovqt_plugin_example.xml +++ b/code/studio/src/plugins/example/ovqt_plugin_example.xml @@ -1,5 +1,5 @@ - ovqt_plugin_example + studio_plugin_example ExamplePlugin 0.2 dnk-88 diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index af33f5311..044d1ed39 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -36,32 +36,32 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC}) SOURCE_GROUP("Georges Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_georges_editor MODULE ${SRC} ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_GEORGES_EDITOR_UI_HDRS} ${OVQT_PLUGIN_GEORGES_EDITOR_RC_SRCS}) +ADD_LIBRARY(studio_plugin_georges_editor MODULE ${SRC} ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_GEORGES_EDITOR_UI_HDRS} ${OVQT_PLUGIN_GEORGES_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_georges_editor ovqt_plugin_core nelmisc nelgeorges qt_property_browser ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_georges_editor studio_plugin_core nelmisc nelgeorges qt_property_browser ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_georges_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Georges Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_georges_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_georges_editor) +NL_DEFAULT_PROPS(studio_plugin_georges_editor "Tools: Studio Plugin: Georges Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_georges_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_georges_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WITH_PCH) - ADD_NATIVE_PRECOMPILED_HEADER(ovqt_plugin_georges_editor ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) + ADD_NATIVE_PRECOMPILED_HEADER(studio_plugin_georges_editor ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) ENDIF(WITH_PCH) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml b/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml index a1972dded..700373bf3 100644 --- a/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml +++ b/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_georges_editor + studio_plugin_georges_editor GeorgesEditor 0.4 aquiles diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index fd1283db8..909d2e993 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -61,7 +61,7 @@ SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_GUI_EDITOR_MOC_SRC} OVQT_P SOURCE_GROUP("GUI Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_gui_editor MODULE ${SRC} +ADD_LIBRARY(studio_plugin_gui_editor MODULE ${SRC} ${OVQT_PLUGIN_GUI_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_GUI_EDITOR_UI_HDRS} @@ -69,8 +69,8 @@ ADD_LIBRARY(ovqt_plugin_gui_editor MODULE ${SRC} ) TARGET_LINK_LIBRARIES( - ovqt_plugin_gui_editor - ovqt_plugin_core + studio_plugin_gui_editor + studio_plugin_core nelmisc nel3d nelgui @@ -80,23 +80,23 @@ TARGET_LINK_LIBRARIES( qt_property_browser ) -NL_DEFAULT_PROPS(ovqt_plugin_gui_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: GUI Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_gui_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_gui_editor) +NL_DEFAULT_PROPS(studio_plugin_gui_editor "Tools: Studio Plugin: GUI Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_gui_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_gui_editor) ADD_DEFINITIONS(-DGUI_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml b/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml index 3703509bb..9ba1452e9 100644 --- a/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml +++ b/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_gui_editor + studio_plugin_gui_editor GUI Editor 0.0.1 Ryzom Core diff --git a/code/studio/src/plugins/landscape_editor/CMakeLists.txt b/code/studio/src/plugins/landscape_editor/CMakeLists.txt index 129f672c5..9fc9e2a5a 100644 --- a/code/studio/src/plugins/landscape_editor/CMakeLists.txt +++ b/code/studio/src/plugins/landscape_editor/CMakeLists.txt @@ -41,17 +41,17 @@ SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} SOURCE_GROUP("Landscape Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_landscape_editor SHARED ${SRC} +ADD_LIBRARY(studio_plugin_landscape_editor SHARED ${SRC} ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS} ${OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_landscape_editor ovqt_plugin_core nelmisc nel3d nelgeorges nelligo ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_landscape_editor studio_plugin_core nelmisc nel3d nelgeorges nelligo ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_landscape_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Landscape Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_landscape_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_landscape_editor) +NL_DEFAULT_PROPS(studio_plugin_landscape_editor "Tools: Studio Plugin: Landscape Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_landscape_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_landscape_editor) ADD_DEFINITIONS(-DLANDSCAPE_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) @@ -59,15 +59,15 @@ ADD_DEFINITIONS(-DLANDSCAPE_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -D IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml index a0d32a22a..53dac537b 100644 --- a/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml +++ b/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_landscape_editor + studio_plugin_landscape_editor LandscapeEditor 0.8 GSoC2011_dnk-88 diff --git a/code/studio/src/plugins/log/CMakeLists.txt b/code/studio/src/plugins/log/CMakeLists.txt index 4cee3da24..4ff8b1888 100644 --- a/code/studio/src/plugins/log/CMakeLists.txt +++ b/code/studio/src/plugins/log/CMakeLists.txt @@ -26,28 +26,28 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_LOG_MOC_SRC}) SOURCE_GROUP("Log Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_log MODULE ${SRC} ${OVQT_PLUG_LOG_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_LOG_UI_HDRS}) +ADD_LIBRARY(studio_plugin_log MODULE ${SRC} ${OVQT_PLUG_LOG_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_LOG_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_log ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_log studio_plugin_core nelmisc ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_log "NeL, Tools, 3D: Object Viewer Qt Plugin: Log") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_log) -NL_ADD_LIB_SUFFIX(ovqt_plugin_log) +NL_DEFAULT_PROPS(studio_plugin_log "Tools: Studio Plugin: Log") +NL_ADD_RUNTIME_FLAGS(studio_plugin_log) +NL_ADD_LIB_SUFFIX(studio_plugin_log) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/log/ovqt_plugin_log.xml b/code/studio/src/plugins/log/ovqt_plugin_log.xml index 90b1b1e27..48d97bd87 100644 --- a/code/studio/src/plugins/log/ovqt_plugin_log.xml +++ b/code/studio/src/plugins/log/ovqt_plugin_log.xml @@ -1,5 +1,5 @@ - ovqt_plugin_log + studio_plugin_log LogPlugin 1.1 aquiles diff --git a/code/studio/src/plugins/mission_compiler/CMakeLists.txt b/code/studio/src/plugins/mission_compiler/CMakeLists.txt index 1dcbebfa8..d2c1a4180 100644 --- a/code/studio/src/plugins/mission_compiler/CMakeLists.txt +++ b/code/studio/src/plugins/mission_compiler/CMakeLists.txt @@ -36,13 +36,13 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ryzom/tools/leveldesign/mission_compiler # Game Share Library INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common/src) -ADD_LIBRARY(ovqt_plugin_mission_compiler MODULE ${SRC} ${OVQT_PLUG_MISSION_COMPILER_MOC_SRC} ${OVQT_PLUG_MISSION_COMPILER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_MISSION_COMPILER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_mission_compiler MODULE ${SRC} ${OVQT_PLUG_MISSION_COMPILER_MOC_SRC} ${OVQT_PLUG_MISSION_COMPILER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_MISSION_COMPILER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_mission_compiler ovqt_plugin_core nelmisc nelligo ryzom_mission_compiler_lib ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_mission_compiler studio_plugin_core nelmisc nelligo ryzom_mission_compiler_lib ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_mission_compiler "NeL, Tools, 3D: Object Viewer Qt Plugin: Mission Compiler") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_mission_compiler) -NL_ADD_LIB_SUFFIX(ovqt_plugin_mission_compiler) +NL_DEFAULT_PROPS(studio_plugin_mission_compiler "Tools: Studio Plugin: Mission Compiler") +NL_ADD_RUNTIME_FLAGS(studio_plugin_mission_compiler) +NL_ADD_LIB_SUFFIX(studio_plugin_mission_compiler) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) @@ -50,15 +50,15 @@ ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS} IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml b/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml index 072707e07..85bdca66f 100644 --- a/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml +++ b/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml @@ -1,5 +1,5 @@ - ovqt_plugin_mission_compiler + studio_plugin_mission_compiler MissionCompiler 0.1 Ryzom Core diff --git a/code/studio/src/plugins/object_viewer/CMakeLists.txt b/code/studio/src/plugins/object_viewer/CMakeLists.txt index b550e8ea0..79e535420 100644 --- a/code/studio/src/plugins/object_viewer/CMakeLists.txt +++ b/code/studio/src/plugins/object_viewer/CMakeLists.txt @@ -165,7 +165,7 @@ SOURCE_GROUP("ovqt Plugin PS Src" FILES ${OVQT_PS_SRC}) SOURCE_GROUP("ovqt Plugin Vegetable Src" FILES ${OVQT_VEGETABLE_SRC}) SOURCE_GROUP("ovqt Plugin Widgets Src" FILES ${OVQT_WIDGETS_SRC}) -ADD_LIBRARY(ovqt_plugin_object_viewer MODULE ${SRC} +ADD_LIBRARY(studio_plugin_object_viewer MODULE ${SRC} ${OVQT_SCENE_SRC} ${OVQT_PS_SRC} ${OVQT_VEGETABLE_SRC} @@ -175,8 +175,8 @@ ADD_LIBRARY(ovqt_plugin_object_viewer MODULE ${SRC} ${OBJECT_VIEWER_PLUGIN_UI_HDRS} ${OBJECT_VIEWER_PLUGIN_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_object_viewer - ovqt_plugin_core +TARGET_LINK_LIBRARIES(studio_plugin_object_viewer + studio_plugin_core nelmisc nel3d nelsound @@ -185,30 +185,30 @@ TARGET_LINK_LIBRARIES(ovqt_plugin_object_viewer ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_object_viewer "NeL, Tools, 3D: Object Viewer Qt Plugin: Object Viewer") +NL_DEFAULT_PROPS(studio_plugin_object_viewer "Tools: Studio Plugin: Object Viewer") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_object_viewer) -NL_ADD_LIB_SUFFIX(ovqt_plugin_object_viewer) +NL_ADD_RUNTIME_FLAGS(studio_plugin_object_viewer) +NL_ADD_LIB_SUFFIX(studio_plugin_object_viewer) ADD_DEFINITIONS(-DQT_NO_KEYWORDS ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WITH_PCH) - ADD_NATIVE_PRECOMPILED_HEADER(ovqt_plugin_object_viewer ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) + ADD_NATIVE_PRECOMPILED_HEADER(studio_plugin_object_viewer ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) ENDIF(WITH_PCH) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml b/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml index 6033c3985..c5ae8c081 100644 --- a/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml +++ b/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml @@ -1,5 +1,5 @@ - ovqt_plugin_object_viewer + studio_plugin_object_viewer ObjectViewer 0.8 Ryzom Core diff --git a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt index 34f237757..90764e7dd 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt +++ b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt @@ -19,28 +19,28 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC}) SOURCE_GROUP("Sheet builder Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_sheet_builder MODULE ${SRC} ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC} ${OVQT_EXT_SYS_SRC}) +ADD_LIBRARY(studio_plugin_sheet_builder MODULE ${SRC} ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC} ${OVQT_EXT_SYS_SRC}) -TARGET_LINK_LIBRARIES(ovqt_plugin_sheet_builder ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_sheet_builder studio_plugin_core nelmisc ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_sheet_builder "NeL, Tools, 3D: Object Viewer Qt Plugin: Sheet builder") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_sheet_builder) -NL_ADD_LIB_SUFFIX(ovqt_plugin_sheet_builder) +NL_DEFAULT_PROPS(studio_plugin_sheet_builder "Tools: Studio Plugin: Sheet builder") +NL_ADD_RUNTIME_FLAGS(studio_plugin_sheet_builder) +NL_ADD_LIB_SUFFIX(studio_plugin_sheet_builder) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml index 01dbefa8a..4f1f3210d 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml @@ -1,5 +1,5 @@ - ovqt_plugin_sheet_builder + studio_plugin_sheet_builder SheetBuilder 1.0 kharvd diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index f3458c909..889e40ffa 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -30,18 +30,18 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_P SOURCE_GROUP("Tile Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) +ADD_LIBRARY(studio_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_tile_editor studio_plugin_core nelmisc ${QT_LIBRARIES}) IF(WITH_STLPORT) - TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) + TARGET_LINK_LIBRARIES(studio_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) ENDIF(WITH_STLPORT) -NL_DEFAULT_PROPS(ovqt_plugin_tile_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Tile Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_tile_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_tile_editor) +NL_DEFAULT_PROPS(studio_plugin_tile_editor "Tools: Studio Plugin: Tile Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_tile_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS ovqt_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file +INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml index 0e21a2eb9..d69201f9b 100644 --- a/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml +++ b/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_tile_editor + studio_plugin_tile_editor TileEditor 1.0 Ryzom Core diff --git a/code/studio/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt index 1d96ebc77..64d081484 100644 --- a/code/studio/src/plugins/translation_manager/CMakeLists.txt +++ b/code/studio/src/plugins/translation_manager/CMakeLists.txt @@ -38,27 +38,27 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC}) SOURCE_GROUP("Translation Manager Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_translation_manager MODULE ${SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_translation_manager MODULE ${SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_translation_manager ovqt_plugin_core nelmisc nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) +TARGET_LINK_LIBRARIES(studio_plugin_translation_manager studio_plugin_core nelmisc nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) -NL_DEFAULT_PROPS(ovqt_plugin_translation_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: Translation Manager") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_translation_manager) -NL_ADD_LIB_SUFFIX(ovqt_plugin_translation_manager) +NL_DEFAULT_PROPS(studio_plugin_translation_manager "Tools: Studio Plugin: Translation Manager") +NL_ADD_RUNTIME_FLAGS(studio_plugin_translation_manager) +NL_ADD_LIB_SUFFIX(studio_plugin_translation_manager) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml b/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml index c5574777a..261fbe65a 100644 --- a/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml +++ b/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml @@ -1,5 +1,5 @@ - ovqt_plugin_translation_manager + studio_plugin_translation_manager TranslationManager 0.8 Ryzom Core diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index 150cc4c4f..5f2d421f0 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -43,15 +43,15 @@ SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} OVQT SOURCE_GROUP("World Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_world_editor MODULE ${SRC} +ADD_LIBRARY(studio_plugin_world_editor MODULE ${SRC} ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS} ${OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES( ovqt_plugin_world_editor - ovqt_plugin_core - ovqt_plugin_landscape_editor +TARGET_LINK_LIBRARIES( studio_plugin_world_editor + studio_plugin_core + studio_plugin_landscape_editor nelmisc nel3d qt_property_browser @@ -59,23 +59,23 @@ TARGET_LINK_LIBRARIES( ovqt_plugin_world_editor ${QT_QTOPENGL_LIBRARY} ) -NL_DEFAULT_PROPS(ovqt_plugin_world_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: World Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_world_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_world_editor) +NL_DEFAULT_PROPS(studio_plugin_world_editor "Tools: Studio Plugin: World Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_world_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_world_editor) ADD_DEFINITIONS(-DWORLD_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml index 13a157a7e..1b15af6a0 100644 --- a/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml +++ b/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_world_editor + studio_plugin_world_editor WorldEditor 0.6 GSoC2011_dnk-88 diff --git a/code/studio/src/plugins/zone_painter/CMakeLists.txt b/code/studio/src/plugins/zone_painter/CMakeLists.txt index 729658ab4..70c72f94c 100644 --- a/code/studio/src/plugins/zone_painter/CMakeLists.txt +++ b/code/studio/src/plugins/zone_painter/CMakeLists.txt @@ -32,28 +32,28 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_ZONE_PAINTER_MOC_SRC} ${OVQT_PL SOURCE_GROUP("Zone Painter Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_zone_painter MODULE ${SRC} ${OVQT_PLUG_ZONE_PAINTER_MOC_SRC} ${OVQT_PLUG_ZONE_PAINTER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_ZONE_PAINTER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_zone_painter MODULE ${SRC} ${OVQT_PLUG_ZONE_PAINTER_MOC_SRC} ${OVQT_PLUG_ZONE_PAINTER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_ZONE_PAINTER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_zone_painter ovqt_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_zone_painter studio_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_zone_painter "NeL, Tools, 3D: Object Viewer Qt Plugin: Zone Painter") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_zone_painter) -NL_ADD_LIB_SUFFIX(ovqt_plugin_zone_painter) +NL_DEFAULT_PROPS(studio_plugin_zone_painter "Tools: Studio Plugin: Zone Painter") +NL_ADD_RUNTIME_FLAGS(studio_plugin_zone_painter) +NL_ADD_LIB_SUFFIX(studio_plugin_zone_painter) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml b/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml index 9a07a6be6..eb796aa42 100644 --- a/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml +++ b/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml @@ -1,5 +1,5 @@ - ovqt_plugin_zone_painter + studio_plugin_zone_painter ZonePainter 0.0 Ryzom Core From 0974142bccea49cd1de9863c4c328e102f3d568c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 19 May 2014 01:45:19 +0200 Subject: [PATCH 025/282] Renamed the plugin XML files. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/bnp_manager/CMakeLists.txt | 2 +- ...qt_plugin_bnp_manager.xml => studio_plugin_bnp_manager.xml} | 0 code/studio/src/plugins/core/CMakeLists.txt | 2 +- .../core/{ovqt_plugin_core.xml => studio_plugin_core.xml} | 0 code/studio/src/plugins/disp_sheet_id/CMakeLists.txt | 2 +- ...lugin_disp_sheet_id.xml => studio_plugin_disp_sheet_id.xml} | 0 code/studio/src/plugins/example/CMakeLists.txt | 2 +- .../{ovqt_plugin_example.xml => studio_plugin_example.xml} | 0 code/studio/src/plugins/georges_editor/CMakeLists.txt | 2 +- ...gin_georges_editor.xml => studio_plugin_georges_editor.xml} | 0 code/studio/src/plugins/gui_editor/CMakeLists.txt | 2 +- ...ovqt_plugin_gui_editor.xml => studio_plugin_gui_editor.xml} | 0 code/studio/src/plugins/landscape_editor/CMakeLists.txt | 2 +- ...landscape_editor.xml => studio_plugin_landscape_editor.xml} | 0 code/studio/src/plugins/log/CMakeLists.txt | 2 +- .../plugins/log/{ovqt_plugin_log.xml => studio_plugin_log.xml} | 0 code/studio/src/plugins/mission_compiler/CMakeLists.txt | 2 +- ...mission_compiler.xml => studio_plugin_mission_compiler.xml} | 0 code/studio/src/plugins/object_viewer/CMakeLists.txt | 2 +- ...lugin_object_viewer.xml => studio_plugin_object_viewer.xml} | 0 code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt | 2 +- ...lugin_sheet_builder.xml => studio_plugin_sheet_builder.xml} | 0 code/studio/src/plugins/tile_editor/CMakeLists.txt | 3 ++- ...qt_plugin_tile_editor.xml => studio_plugin_tile_editor.xml} | 0 code/studio/src/plugins/translation_manager/CMakeLists.txt | 2 +- ...ation_manager.xml => studio_plugin_translation_manager.xml} | 0 code/studio/src/plugins/world_editor/CMakeLists.txt | 2 +- ..._plugin_world_editor.xml => studio_plugin_world_editor.xml} | 0 code/studio/src/plugins/zone_painter/CMakeLists.txt | 2 +- ..._plugin_zone_painter.xml => studio_plugin_zone_painter.xml} | 0 30 files changed, 16 insertions(+), 15 deletions(-) rename code/studio/src/plugins/bnp_manager/{ovqt_plugin_bnp_manager.xml => studio_plugin_bnp_manager.xml} (100%) rename code/studio/src/plugins/core/{ovqt_plugin_core.xml => studio_plugin_core.xml} (100%) rename code/studio/src/plugins/disp_sheet_id/{ovqt_plugin_disp_sheet_id.xml => studio_plugin_disp_sheet_id.xml} (100%) rename code/studio/src/plugins/example/{ovqt_plugin_example.xml => studio_plugin_example.xml} (100%) rename code/studio/src/plugins/georges_editor/{ovqt_plugin_georges_editor.xml => studio_plugin_georges_editor.xml} (100%) rename code/studio/src/plugins/gui_editor/{ovqt_plugin_gui_editor.xml => studio_plugin_gui_editor.xml} (100%) rename code/studio/src/plugins/landscape_editor/{ovqt_plugin_landscape_editor.xml => studio_plugin_landscape_editor.xml} (100%) rename code/studio/src/plugins/log/{ovqt_plugin_log.xml => studio_plugin_log.xml} (100%) rename code/studio/src/plugins/mission_compiler/{ovqt_plugin_mission_compiler.xml => studio_plugin_mission_compiler.xml} (100%) rename code/studio/src/plugins/object_viewer/{ovqt_plugin_object_viewer.xml => studio_plugin_object_viewer.xml} (100%) rename code/studio/src/plugins/ovqt_sheet_builder/{ovqt_plugin_sheet_builder.xml => studio_plugin_sheet_builder.xml} (100%) rename code/studio/src/plugins/tile_editor/{ovqt_plugin_tile_editor.xml => studio_plugin_tile_editor.xml} (100%) rename code/studio/src/plugins/translation_manager/{ovqt_plugin_translation_manager.xml => studio_plugin_translation_manager.xml} (100%) rename code/studio/src/plugins/world_editor/{ovqt_plugin_world_editor.xml => studio_plugin_world_editor.xml} (100%) rename code/studio/src/plugins/zone_painter/{ovqt_plugin_zone_painter.xml => studio_plugin_zone_painter.xml} (100%) diff --git a/code/studio/src/plugins/bnp_manager/CMakeLists.txt b/code/studio/src/plugins/bnp_manager/CMakeLists.txt index be56bc704..406a927b8 100644 --- a/code/studio/src/plugins/bnp_manager/CMakeLists.txt +++ b/code/studio/src/plugins/bnp_manager/CMakeLists.txt @@ -45,5 +45,5 @@ NL_ADD_LIB_SUFFIX(studio_plugin_bnp_manager) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) INSTALL(TARGETS studio_plugin_bnp_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_bnp_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_bnp_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml b/code/studio/src/plugins/bnp_manager/studio_plugin_bnp_manager.xml similarity index 100% rename from code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml rename to code/studio/src/plugins/bnp_manager/studio_plugin_bnp_manager.xml diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index add4665bc..964f95b11 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -69,5 +69,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/core/ovqt_plugin_core.xml b/code/studio/src/plugins/core/studio_plugin_core.xml similarity index 100% rename from code/studio/src/plugins/core/ovqt_plugin_core.xml rename to code/studio/src/plugins/core/studio_plugin_core.xml diff --git a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt index 65f880f07..bce24b667 100644 --- a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt +++ b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt @@ -55,5 +55,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_disp_sheet_id.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_disp_sheet_id.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml b/code/studio/src/plugins/disp_sheet_id/studio_plugin_disp_sheet_id.xml similarity index 100% rename from code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml rename to code/studio/src/plugins/disp_sheet_id/studio_plugin_disp_sheet_id.xml diff --git a/code/studio/src/plugins/example/CMakeLists.txt b/code/studio/src/plugins/example/CMakeLists.txt index 9eda8916e..fd4008fc4 100644 --- a/code/studio/src/plugins/example/CMakeLists.txt +++ b/code/studio/src/plugins/example/CMakeLists.txt @@ -52,5 +52,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_example.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_example.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/example/ovqt_plugin_example.xml b/code/studio/src/plugins/example/studio_plugin_example.xml similarity index 100% rename from code/studio/src/plugins/example/ovqt_plugin_example.xml rename to code/studio/src/plugins/example/studio_plugin_example.xml diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index 044d1ed39..bab12b7e1 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -65,5 +65,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_georges_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_georges_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml b/code/studio/src/plugins/georges_editor/studio_plugin_georges_editor.xml similarity index 100% rename from code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml rename to code/studio/src/plugins/georges_editor/studio_plugin_georges_editor.xml diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 909d2e993..ff248a261 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -100,4 +100,4 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_gui_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_gui_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml b/code/studio/src/plugins/gui_editor/studio_plugin_gui_editor.xml similarity index 100% rename from code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml rename to code/studio/src/plugins/gui_editor/studio_plugin_gui_editor.xml diff --git a/code/studio/src/plugins/landscape_editor/CMakeLists.txt b/code/studio/src/plugins/landscape_editor/CMakeLists.txt index 9fc9e2a5a..448d86a48 100644 --- a/code/studio/src/plugins/landscape_editor/CMakeLists.txt +++ b/code/studio/src/plugins/landscape_editor/CMakeLists.txt @@ -71,4 +71,4 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_landscape_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_landscape_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/studio/src/plugins/landscape_editor/studio_plugin_landscape_editor.xml similarity index 100% rename from code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml rename to code/studio/src/plugins/landscape_editor/studio_plugin_landscape_editor.xml diff --git a/code/studio/src/plugins/log/CMakeLists.txt b/code/studio/src/plugins/log/CMakeLists.txt index 4ff8b1888..7a27f370a 100644 --- a/code/studio/src/plugins/log/CMakeLists.txt +++ b/code/studio/src/plugins/log/CMakeLists.txt @@ -51,5 +51,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_log.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_log.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/log/ovqt_plugin_log.xml b/code/studio/src/plugins/log/studio_plugin_log.xml similarity index 100% rename from code/studio/src/plugins/log/ovqt_plugin_log.xml rename to code/studio/src/plugins/log/studio_plugin_log.xml diff --git a/code/studio/src/plugins/mission_compiler/CMakeLists.txt b/code/studio/src/plugins/mission_compiler/CMakeLists.txt index d2c1a4180..cbf35b9c7 100644 --- a/code/studio/src/plugins/mission_compiler/CMakeLists.txt +++ b/code/studio/src/plugins/mission_compiler/CMakeLists.txt @@ -62,5 +62,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_mission_compiler.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_mission_compiler.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml b/code/studio/src/plugins/mission_compiler/studio_plugin_mission_compiler.xml similarity index 100% rename from code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml rename to code/studio/src/plugins/mission_compiler/studio_plugin_mission_compiler.xml diff --git a/code/studio/src/plugins/object_viewer/CMakeLists.txt b/code/studio/src/plugins/object_viewer/CMakeLists.txt index 79e535420..3a4ce9c65 100644 --- a/code/studio/src/plugins/object_viewer/CMakeLists.txt +++ b/code/studio/src/plugins/object_viewer/CMakeLists.txt @@ -212,5 +212,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_object_viewer.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_object_viewer.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml b/code/studio/src/plugins/object_viewer/studio_plugin_object_viewer.xml similarity index 100% rename from code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml rename to code/studio/src/plugins/object_viewer/studio_plugin_object_viewer.xml diff --git a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt index 90764e7dd..a543421c5 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt +++ b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt @@ -44,5 +44,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_sheet_builder.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_sheet_builder.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml b/code/studio/src/plugins/ovqt_sheet_builder/studio_plugin_sheet_builder.xml similarity index 100% rename from code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml rename to code/studio/src/plugins/ovqt_sheet_builder/studio_plugin_sheet_builder.xml diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index 889e40ffa..d546beba1 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -44,4 +44,5 @@ NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file +INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_tile_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml similarity index 100% rename from code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml rename to code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml diff --git a/code/studio/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt index 64d081484..6f0f7a1c2 100644 --- a/code/studio/src/plugins/translation_manager/CMakeLists.txt +++ b/code/studio/src/plugins/translation_manager/CMakeLists.txt @@ -62,5 +62,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_translation_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_translation_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml b/code/studio/src/plugins/translation_manager/studio_plugin_translation_manager.xml similarity index 100% rename from code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml rename to code/studio/src/plugins/translation_manager/studio_plugin_translation_manager.xml diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index 5f2d421f0..7b76ed810 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -79,5 +79,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_world_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_world_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/studio/src/plugins/world_editor/studio_plugin_world_editor.xml similarity index 100% rename from code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml rename to code/studio/src/plugins/world_editor/studio_plugin_world_editor.xml diff --git a/code/studio/src/plugins/zone_painter/CMakeLists.txt b/code/studio/src/plugins/zone_painter/CMakeLists.txt index 70c72f94c..94f5e85f7 100644 --- a/code/studio/src/plugins/zone_painter/CMakeLists.txt +++ b/code/studio/src/plugins/zone_painter/CMakeLists.txt @@ -57,5 +57,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_zone_painter.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_zone_painter.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml b/code/studio/src/plugins/zone_painter/studio_plugin_zone_painter.xml similarity index 100% rename from code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml rename to code/studio/src/plugins/zone_painter/studio_plugin_zone_painter.xml From eeb4e48d38514578b57b0845e99b3da39e519977 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 19 May 2014 02:08:03 +0200 Subject: [PATCH 026/282] Renames. --HG-- branch : gsoc2014-dfighter --- code/studio/CMakeLists.txt | 2 +- code/studio/ovqt_config.h.cmake | 4 ++-- code/studio/src/main.cpp | 6 +++--- code/studio/src/plugins/core/main_window.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/code/studio/CMakeLists.txt b/code/studio/CMakeLists.txt index b301430cf..bf9ee062c 100644 --- a/code/studio/CMakeLists.txt +++ b/code/studio/CMakeLists.txt @@ -27,7 +27,7 @@ ELSE(WIN32) ENDIF(WIN32) IF(UNIX AND WITH_STATIC) - MESSAGE(FATAL_ERROR "OVQT does not work with static NeL builds on Unix atm.") + MESSAGE(FATAL_ERROR "Studio does not work with static NeL builds on Unix atm.") ENDIF() ADD_SUBDIRECTORY(src) diff --git a/code/studio/ovqt_config.h.cmake b/code/studio/ovqt_config.h.cmake index 5b3a49654..9d4907473 100644 --- a/code/studio/ovqt_config.h.cmake +++ b/code/studio/ovqt_config.h.cmake @@ -1,7 +1,7 @@ #ifndef OVQT_CONFIG_H #define OVQT_CONFIG_H -#define DATA_DIR "${NL_SHARE_ABSOLUTE_PREFIX}/object_viewer_qt" -#define PLUGINS_DIR "${NL_LIB_ABSOLUTE_PREFIX}/object_viewer_qt" +#define DATA_DIR "${NL_SHARE_ABSOLUTE_PREFIX}/studio" +#define PLUGINS_DIR "${NL_LIB_ABSOLUTE_PREFIX}/studio" #endif diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index d0407ccfd..e94bac9d6 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -164,7 +164,7 @@ int main(int argc, char **argv) pluginManager.setSettings(settings); QStringList pluginPaths; #if defined(NL_OS_MAC) - pluginPaths << settings->value("PluginPath", qApp->applicationDirPath() + QString("/../PlugIns/ovqt")).toString(); + pluginPaths << settings->value("PluginPath", qApp->applicationDirPath() + QString("/../PlugIns/studio")).toString(); #else pluginPaths << settings->value("PluginPath", QString("%1/plugins").arg(DATA_DIR)).toString(); #endif @@ -180,7 +180,7 @@ int main(int argc, char **argv) { QDir absolutePluginPaths(pluginPaths.join(QLatin1String(","))); QString absolutePaths = absolutePluginPaths.absolutePath(); - const QString reason = QCoreApplication::translate("Application", "Could not find ovqt_plugin_core in %1").arg(absolutePaths); + const QString reason = QCoreApplication::translate("Application", "Could not find studio_plugin_core in %1").arg(absolutePaths); displayError(msgCoreLoadFailure(reason)); QString newPath = QFileDialog::getExistingDirectory(0, QCoreApplication::translate("Application", "Change the plugins path"), QDir::homePath()); @@ -205,7 +205,7 @@ int main(int argc, char **argv) errors.append(spec->fileName() + " : " + spec->errorString()); if (!errors.isEmpty()) - QMessageBox::warning(0, QCoreApplication::translate("Application", "Object Viewer Qt - Plugin loader messages"), + QMessageBox::warning(0, QCoreApplication::translate("Application", "Studio - Plugin loader messages"), errors.join(QString::fromLatin1("\n\n"))); int result = app.exec(); diff --git a/code/studio/src/plugins/core/main_window.cpp b/code/studio/src/plugins/core/main_window.cpp index a90e67bc0..fcde24fbf 100644 --- a/code/studio/src/plugins/core/main_window.cpp +++ b/code/studio/src/plugins/core/main_window.cpp @@ -46,13 +46,13 @@ MainWindow::MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget * m_undoGroup(0), m_settings(0) { - QCoreApplication::setApplicationName(QLatin1String("ObjectViewerQt")); + QCoreApplication::setApplicationName(QLatin1String("Studio")); QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::OVQT_VERSION_LONG)); QCoreApplication::setOrganizationName(QLatin1String("RyzomCore")); setObjectName(Constants::MAIN_WINDOW); setWindowIcon(QIcon(Constants::ICON_PILL)); - setWindowTitle(tr("Object Viewer Qt")); + setWindowTitle(tr("Ryzom Core Studio")); m_pluginManager = pluginManager; m_settings = m_pluginManager->settings(); @@ -232,8 +232,8 @@ bool MainWindow::showOptionsDialog(const QString &group, void MainWindow::about() { - QMessageBox::about(this, tr("About Object Viewer Qt"), - tr("

Object Viewer Qt

" + QMessageBox::about(this, tr("About Ryzom Core Studio"), + tr("

Ryzom Core Studio

" "

Ryzom Core team

Compiled on %1 %2").arg(__DATE__).arg(__TIME__)); } From ef7a39641fcde8fce34420097d4ce9a36935ac35 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 22 May 2014 15:06:40 +0200 Subject: [PATCH 027/282] Rename. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 4 ++-- code/studio/src/{object_viewer_qt.qrc => studio.qrc} | 0 code/studio/src/{object_viewer_qt.rc => studio.rc} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename code/studio/src/{object_viewer_qt.qrc => studio.qrc} (100%) rename code/studio/src/{object_viewer_qt.rc => studio.rc} (100%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index cc0c5d452..2954909fb 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -12,7 +12,7 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h) -SET(STUDIO_RCS object_viewer_qt.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) +SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_fr.ts @@ -23,7 +23,7 @@ SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) IF(WIN32) - SET(STUDIO object_viewer_qt.rc) + SET(STUDIO studio.rc) ENDIF(WIN32) QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) diff --git a/code/studio/src/object_viewer_qt.qrc b/code/studio/src/studio.qrc similarity index 100% rename from code/studio/src/object_viewer_qt.qrc rename to code/studio/src/studio.qrc diff --git a/code/studio/src/object_viewer_qt.rc b/code/studio/src/studio.rc similarity index 100% rename from code/studio/src/object_viewer_qt.rc rename to code/studio/src/studio.rc From 79348c8e93a0bb8be4d1565a40907f02f52930ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 22 May 2014 15:56:38 +0200 Subject: [PATCH 028/282] More renames. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 2 +- .../images/{nel_ide_load.png => studio_splash.png} | Bin code/studio/src/{ic_nel_pill.ico => studio.ico} | Bin code/studio/src/studio.qrc | 2 +- code/studio/src/studio.rc | 6 +++--- 5 files changed, 5 insertions(+), 5 deletions(-) rename code/studio/src/images/{nel_ide_load.png => studio_splash.png} (100%) rename code/studio/src/{ic_nel_pill.ico => studio.ico} (100%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 2954909fb..4ccc932c5 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -23,7 +23,7 @@ SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) IF(WIN32) - SET(STUDIO studio.rc) + SET(STUDIO_RC studio.rc) ENDIF(WIN32) QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) diff --git a/code/studio/src/images/nel_ide_load.png b/code/studio/src/images/studio_splash.png similarity index 100% rename from code/studio/src/images/nel_ide_load.png rename to code/studio/src/images/studio_splash.png diff --git a/code/studio/src/ic_nel_pill.ico b/code/studio/src/studio.ico similarity index 100% rename from code/studio/src/ic_nel_pill.ico rename to code/studio/src/studio.ico diff --git a/code/studio/src/studio.qrc b/code/studio/src/studio.qrc index 13d47d75b..17306e2cc 100644 --- a/code/studio/src/studio.qrc +++ b/code/studio/src/studio.qrc @@ -1,5 +1,5 @@ - images/nel_ide_load.png + images/studio_splash.png diff --git a/code/studio/src/studio.rc b/code/studio/src/studio.rc index a0f0e7099..05ade2766 100644 --- a/code/studio/src/studio.rc +++ b/code/studio/src/studio.rc @@ -28,12 +28,12 @@ BEGIN VALUE "CompanyName", "Ryzom Core\0" VALUE "FileDescription", "\0" VALUE "FileVersion", "1, 0, 0, 1\0" - VALUE "InternalName", "Object_Viewer_Qt\0" + VALUE "InternalName", "Ryzom Core Studio\0" VALUE "LegalCopyright", "Copyright (C) 2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "\0" VALUE "PrivateBuild", "\0" - VALUE "ProductName", "Object Viewer Qt\0" + VALUE "ProductName", "Ryzom Core Studio\0" VALUE "ProductVersion", "1, 0, 0, 1\0" VALUE "SpecialBuild", "\0" END @@ -51,4 +51,4 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDR_MAINFRAME ICON DISCARDABLE "ic_nel_pill.ico" +IDR_MAINFRAME ICON DISCARDABLE "studio.ico" From 4adbb6dbd9211ce4e8082b94ca196312acfd22f9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 23 May 2014 02:26:31 +0200 Subject: [PATCH 029/282] Moved plugin menu items to their own sub-menu into the menubar. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/core/main_window.cpp | 6 +-- .../plugins/gui_editor/gui_editor_window.cpp | 6 +-- .../src/plugins/object_viewer/main_window.cpp | 47 +++++++++---------- .../translation_manager_main_window.cpp | 7 ++- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/code/studio/src/plugins/core/main_window.cpp b/code/studio/src/plugins/core/main_window.cpp index fcde24fbf..4ccd32564 100644 --- a/code/studio/src/plugins/core/main_window.cpp +++ b/code/studio/src/plugins/core/main_window.cpp @@ -438,9 +438,6 @@ void MainWindow::createMenus() m_toolsMenu = m_menuBar->addMenu(tr("&Tools")); menuManager()->registerMenu(m_toolsMenu, Constants::M_TOOLS); - m_sheetMenu = m_toolsMenu->addMenu(tr("&Sheet")); - menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); - // m_toolsMenu->addSeparator(); m_toolsMenu->addAction(m_settingsAction); @@ -452,6 +449,9 @@ void MainWindow::createMenus() m_helpMenu->addAction(m_aboutAction); m_helpMenu->addAction(m_aboutQtAction); m_helpMenu->addAction(m_pluginViewAction); + + m_sheetMenu = m_menuBar->addMenu(tr("&Sheet")); + menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); } void MainWindow::createStatusBar() diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 341338d8d..24ecc5cfc 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -360,11 +360,9 @@ namespace GUIEditor connect( delAction, SIGNAL( triggered( bool ) ), messageProcessor, SLOT( onDelete() ) ); } - QMenu *menu = mm->menu( Core::Constants::M_TOOLS ); - if( menu != NULL ) + QMenu *m = mm->menuBar()->addMenu( "GUI Editor" ); + if( m != NULL ) { - QMenu *m = menu->addMenu( "GUI Editor" ); - QAction *a = new QAction( "Widget Properties", this ); connect( a, SIGNAL( triggered( bool ) ), widgetProps, SLOT( show() ) ); m->addAction( a ); diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index bccf7a6b1..91f832ac0 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -270,55 +270,51 @@ void CMainWindow::createMenus() menuManager->registerAction(_reloadTexturesAction, "ObjectViewer.View.ReloadTextures"); menuManager->registerAction(_saveScreenshotAction, "ObjectViewer.View.SaveScreenshot"); - // add actions in view menu - QMenu *viewMenu = menuManager->menu(Core::Constants::M_VIEW); - viewMenu->addAction(_setBackColorAction); - viewMenu->addAction(_SetupFog->toggleViewAction()); - viewMenu->addAction(_resetSceneAction); - viewMenu->addAction(_reloadTexturesAction); - viewMenu->addAction(_saveScreenshotAction); - - // add actions in tools menu - QMenu *toolsMenu = menuManager->menu(Core::Constants::M_TOOLS); - QAction *settingsAction = menuManager->action(Core::Constants::SETTINGS); - QMenu *ovMenu = new QMenu("Object Viewer", this); + QMenu *ovMenu = menuManager->menuBar()->addMenu( "Object Viewer" ); menuManager->registerMenu(ovMenu, "ObjectViewerQt.ObjectViewer"); - toolsMenu->insertMenu(settingsAction, ovMenu); - ovMenu->insertAction(settingsAction ,_AnimationDialog->toggleViewAction()); + ovMenu->addAction(_setBackColorAction); + ovMenu->addAction(_SetupFog->toggleViewAction()); + ovMenu->addAction(_resetSceneAction); + ovMenu->addAction(_reloadTexturesAction); + ovMenu->addAction(_saveScreenshotAction); + + ovMenu->addSeparator(); + + ovMenu->addAction(_AnimationDialog->toggleViewAction() ); _AnimationDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_ANIM)); - ovMenu->insertAction(settingsAction ,_AnimationSetDialog->toggleViewAction()); + ovMenu->addAction(_AnimationSetDialog->toggleViewAction()); _AnimationSetDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_ANIMSET)); - ovMenu->insertAction(settingsAction ,_SlotManagerDialog->toggleViewAction()); + ovMenu->addAction(_SlotManagerDialog->toggleViewAction()); _SlotManagerDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_MIXER)); - ovMenu->insertAction(settingsAction ,_ParticleControlDialog->toggleViewAction()); + ovMenu->addAction(_ParticleControlDialog->toggleViewAction()); _ParticleControlDialog->toggleViewAction()->setIcon(QIcon(":/images/pqrticles.png")); - ovMenu->insertAction(settingsAction ,_DayNightDialog->toggleViewAction()); + ovMenu->addAction(_DayNightDialog->toggleViewAction()); _DayNightDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_DAYNIGHT)); - ovMenu->insertAction(settingsAction ,_WaterPoolDialog->toggleViewAction()); + ovMenu->addAction(_WaterPoolDialog->toggleViewAction()); _WaterPoolDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_WATER)); _WaterPoolDialog->toggleViewAction()->setEnabled(false); - ovMenu->insertAction(settingsAction ,_VegetableDialog->toggleViewAction()); + ovMenu->addAction(_VegetableDialog->toggleViewAction()); _VegetableDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_VEGET)); - ovMenu->insertAction(settingsAction ,_GlobalWindDialog->toggleViewAction()); + ovMenu->addAction(_GlobalWindDialog->toggleViewAction()); _GlobalWindDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_WIND)); - ovMenu->insertAction(settingsAction ,_SkeletonScaleDialog->toggleViewAction()); + ovMenu->addAction(_SkeletonScaleDialog->toggleViewAction()); _SkeletonScaleDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_SKELSCALE)); - ovMenu->insertAction(settingsAction ,_TuneTimerDialog->toggleViewAction()); + ovMenu->addAction(_TuneTimerDialog->toggleViewAction()); _TuneTimerDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_FRAMEDELAY)); - ovMenu->insertAction(settingsAction ,_SunColorDialog->toggleViewAction()); + ovMenu->addAction(_SunColorDialog->toggleViewAction()); - ovMenu->insertAction(settingsAction ,_TuneMRMDialog->toggleViewAction()); + ovMenu->addAction(_TuneMRMDialog->toggleViewAction()); _TuneMRMDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_MRM_MESH)); connect(_ParticleControlDialog->toggleViewAction(), SIGNAL(triggered(bool)), @@ -327,7 +323,6 @@ void CMainWindow::createMenus() connect(_ParticleControlDialog->toggleViewAction(), SIGNAL(triggered(bool)), _ParticleWorkspaceDialog->_PropertyDialog, SLOT(setVisible(bool))); - toolsMenu->insertSeparator(settingsAction); } void CMainWindow::createToolBars() diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 9fcb9626a..d80ffe3f5 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -129,7 +129,12 @@ void CMainWindow::createToolbar() // Windows menu Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - windowMenu = menuManager->menuBar()->addMenu("Window"); + QMenu *m = menuManager->menuBar()->addMenu( "Translation Manager" ); + if( m != NULL ) + { + windowMenu = m->addMenu("Window"); + } + updateWindowsList(); connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); From 23c0a8bc24486b99488eefe0c96a89269ff9180a Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Sun, 25 May 2014 15:03:20 +0530 Subject: [PATCH 030/282] CRUD layer for AMS --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/dblayer.php | 112 +++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php index 58ea7b80e..b095b4dc7 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php @@ -81,5 +81,113 @@ class DBLayer{ $this->PDO->commit(); return $lastId; } - -} \ No newline at end of file + /** + * + * Select function using prepared statement + * @param string $tb_name Table Name to Select + * @param array $data Associative array + * @param string $where where to select + * @return array Array containing fetched data + */ + public function select($query, $data) + { + try{ + $sth = $this->PDO->prepare($query); + $this->PDO->beginTransaction(); + $sth->execute(array($data)); + $this->PDO->commit(); + }catch(Exception $e) + { + $this->PDO->rollBack(); + throw new Exception("error selection"); + return false; + } + return $sth; + } + + /** + * + * Update function with prepared statement + * @param string $tb_name name of the table + * @param array $data associative array with values + * @param string $where where part + * @throws Exception error in updating + */ + public function update($tb_name, $data, $where) + { + $field_option_values=null; + foreach ($data as $key => $value) + { + $field_option_values.=",$key".'=:'.$value; + } + $field_option_values = ltrim($field_option_values,','); + try { + $sth = $this->PDO->prepare("UPDATE $tb_name SET $field_option_values WHERE $where "); + + foreach ($data as $key => $value) + { + $sth->bindValue(":$key", $value); + } + $this->PDO->beginTransaction(); + $sth->execute(); + $this->PDO->commit(); + }catch (Exception $e) + { + $this->PDO->rollBack(); + throw new Exception('error in updating'); + } + } + /** + * + * insert function using prepared statements + * @param string $tb_name Name of the table to insert in + * @param array $data Associative array of data to insert + */ + + public function insert($tb_name, $data) + { + $field_values =':'. implode(',:', array_keys($data)); + $field_options = implode(',', array_keys($data)); + try{ + $sth = $this->PDO->prepare("INSERT INTO $tb_name ($field_options) VALUE ($field_values)"); + foreach ($data as $key => $value ) + { + + $sth->bindValue(":$key", $value); + } + $this->PDO->beginTransaction(); + //execution + $sth->execute(); + $this->PDO->commit(); + + }catch (Exception $e) + { + //for rolling back the changes during transaction + $this->PDO->rollBack(); + throw new Exception("error in inseting"); + } + } + + /** + * + * Delete database entery using prepared statement + * @param string $tb_name + * @param string $where + * @throws error in deleting + */ + public function delete($tb_name, $where) + { + try { + $sth = $this->prepare("DELETE FROM $tb_name WHERE $where"); + $this->PDO->beginTransaction(); + $sth->execute(); + $this->PDO->commit(); + } + catch (Exception $e) + { + $this->rollBack(); + throw new Exception("error in deleting"); + } + + } +} From 1306853697e32638ee27f458e3f0e97c1de4f3a4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 25 May 2014 22:45:34 +0200 Subject: [PATCH 031/282] More renames. --HG-- branch : gsoc2014-dfighter --- code/studio/src/extension_system/plugin_manager.cpp | 2 +- code/studio/src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 9b9da508b..a976583fb 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -183,7 +183,7 @@ void PluginManager::readPluginPaths() while (!searchPaths.isEmpty()) { const QDir dir(searchPaths.takeFirst()); - const QFileInfoList files = dir.entryInfoList(QStringList() << QString("ovqt_plugin_*.%1").arg(m_extension), QDir::Files); + const QFileInfoList files = dir.entryInfoList(QStringList() << QString("studio_plugin_*.%1").arg(m_extension), QDir::Files); Q_FOREACH (const QFileInfo &file, files) pluginsList << file.absoluteFilePath(); const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot); diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index e94bac9d6..d4b3f8d75 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -139,7 +139,7 @@ int main(int argc, char **argv) QApplication app(argc, argv); #endif // NL_OS_WINDOWS QSplashScreen *splash = new QSplashScreen(); - splash->setPixmap(QPixmap(":/images/nel_ide_load.png")); + splash->setPixmap(QPixmap(":/images/studio_splash.png")); splash->show(); QSettings::setDefaultFormat(QSettings::IniFormat); From 883c0d4462ec5c5ec83974cbafb6ced5f8774b22 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 26 May 2014 21:04:05 +0200 Subject: [PATCH 032/282] Settings dialog on first startup. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 11 +- code/studio/src/main.cpp | 16 +- code/studio/src/settings_dialog.cpp | 236 +++++++++++++++++++++++++ code/studio/src/settings_dialog.h | 62 +++++++ code/studio/src/settings_dialog.ui | 255 ++++++++++++++++++++++++++++ 5 files changed, 576 insertions(+), 4 deletions(-) create mode 100644 code/studio/src/settings_dialog.cpp create mode 100644 code/studio/src/settings_dialog.h create mode 100644 code/studio/src/settings_dialog.ui diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 4ccc932c5..e41bd4778 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -10,7 +10,8 @@ FILE(GLOB STUDIO_SRC extension_system/*.h *.h *.cpp) SET(STUDIO_HDR extension_system/iplugin_manager.h - extension_system/plugin_manager.h) + extension_system/plugin_manager.h + settings_dialog.h ) SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) @@ -18,6 +19,8 @@ SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_fr.ts translations/object_viewer_qt_de.ts translations/object_viewer_qt_ru.ts) + +SET(STUDIO_PLUGIN_UIS settings_dialog.ui ) SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) @@ -29,15 +32,17 @@ ENDIF(WIN32) QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) QT4_ADD_RESOURCES( STUDIO_RC_SRCS ${STUDIO_RCS}) QT4_WRAP_CPP( STUDIO_MOC_SRCS ${STUDIO_HDR} ) +QT4_WRAP_UI( STUDIO_PLUGIN_UI_HDRS ${STUDIO_PLUGIN_UIS}) -SOURCE_GROUP(QtResources FILES ${STUDIO_RCS}) +SOURCE_GROUP(QtResources FILES ${STUDIO_RCS} ${STUDIO_PLUGIN_UIS} ) SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${STUDIO_MOC_SRCS} ${STUDIO_RC_SRCS}) ADD_EXECUTABLE(studio WIN32 MACOSX_BUNDLE ${STUDIO_SRC} ${STUDIO_MOC_SRCS} ${STUDIO_RC_SRCS} - ${STUDIO_RC}) + ${STUDIO_RC} + ${STUDIO_PLUGIN_UIS} ) TARGET_LINK_LIBRARIES(studio nelmisc diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index d4b3f8d75..1f316f677 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -41,11 +41,13 @@ #include #include +#include "settings_dialog.h" + #ifdef HAVE_OVQT_CONFIG_H #include "ovqt_config.h" #endif -static const char *appNameC = "ObjectViewerQt"; +static const char *appNameC = "RyzomCoreStudio"; // nel_qt log file name #define NLQT_LOG_FILE "nel_qt.log" @@ -138,6 +140,7 @@ int main(int argc, char **argv) #else // NL_OS_WINDOWS QApplication app(argc, argv); #endif // NL_OS_WINDOWS + QSplashScreen *splash = new QSplashScreen(); splash->setPixmap(QPixmap(":/images/studio_splash.png")); splash->show(); @@ -146,6 +149,17 @@ int main(int argc, char **argv) QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, QLatin1String("RyzomCore"), QLatin1String(appNameC)); + bool firstRun = settings->value( "FirstRun", true ).toBool(); + if( firstRun ) + { + settings->setValue( "FirstRun", false ); + + SettingsDialog sd; + sd.setSettings( settings ); + sd.load(); + sd.exec(); + } + QTranslator translator; QTranslator qtTranslator; QString locale = settings->value("Language", QLocale::system().name()).toString(); diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp new file mode 100644 index 000000000..30eb39f0f --- /dev/null +++ b/code/studio/src/settings_dialog.cpp @@ -0,0 +1,236 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "settings_dialog.h" +#include +#include +#include + +int findListItem( QListWidget *l, const QString &s ) +{ + for( int i = 0; i < l->count(); i++ ) + { + QListWidgetItem *item = l->item( i ); + if( item->text() == s ) + return i; + } + + return -1; +} + +SettingsDialog::SettingsDialog( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); + settings = NULL; +} + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::load() +{ + pluginsLE->setText( settings->value( "PluginPath" ).toString() ); + + settings->beginGroup( "DataPath" ); + + sheetsLE->setText( settings->value( "LevelDesignPath" ).toString() ); + assetsLE->setText( settings->value( "AssetsPath" ).toString() ); + primitivesLE->setText( settings->value( "PrimitivesPath" ).toString() ); + ligoLE->setText( settings->value( "LigoConfigFile" ).toString() ); + + QStringList l = settings->value( "SearchPaths" ).toStringList(); + { + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + QString p = itr.next(); + if( findListItem( searchLW, p ) == -1 ) + searchLW->addItem( p ); + } + } + + l.clear(); + + l = settings->value( "RecursiveSearchPathes" ).toStringList(); + { + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + QString p = itr.next(); + if( findListItem( recursiveLW, p ) == -1 ) + recursiveLW->addItem( p ); + } + } + + settings->endGroup(); +} + +void SettingsDialog::saveSearchPaths() +{ + QStringList l; + for( int i = 0; i < searchLW->count(); i++ ) + { + l.push_back( searchLW->item( i )->text() ); + } + + settings->setValue( "SearchPaths", l ); +} + +void SettingsDialog::saveRecursivePaths() +{ + QStringList l; + for( int i = 0; i < recursiveLW->count(); i++ ) + { + l.push_back( recursiveLW->item( i )->text() ); + } + + settings->setValue( "RecursiveSearchPathes", l ); +} + +void SettingsDialog::save() +{ + settings->setValue( "PluginPath", pluginsLE->text() ); + + settings->beginGroup( "DataPath" ); + + settings->setValue( "LevelDesignPath", sheetsLE->text() ); + settings->setValue( "AssetsPath", assetsLE->text() ); + settings->setValue( "PrimitivesPath", primitivesLE->text() ); + settings->setValue( "LigoConfigFile", ligoLE->text() ); + + saveSearchPaths(); + saveRecursivePaths(); + + settings->endGroup(); + + settings->sync(); +} + +void SettingsDialog::accept() +{ + save(); + QDialog::accept(); +} + +void SettingsDialog::reject() +{ + QDialog::reject(); +} + +void SettingsDialog::onOKClicked() +{ + accept(); +} + +void SettingsDialog::onCancelClicked() +{ + reject(); +} + +void SettingsDialog::onPluginBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Plugins directory" ), "" ); + pluginsLE->setText( p ); +} + +void SettingsDialog::onSheetsBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Sheets directory" ), "" ); + sheetsLE->setText( p ); +} + +void SettingsDialog::onAssetsBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Assets directory" ), "" ); + assetsLE->setText( p ); +} + +void SettingsDialog::onPrimitivesBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Primitives directory" ), "" ); + primitivesLE->setText( p ); +} + +void SettingsDialog::onLigoBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "LIGO directory" ), "" ); + ligoLE->setText( p ); +} + +void SettingsDialog::onPathAddClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Search path" ), "" ); + if( p.isEmpty() ) + return; + + if( findListItem( searchLW, p ) != -1 ) + return; + + searchLW->addItem( p ); +} + +void SettingsDialog::onPathRemoveClicked() +{ + QListWidgetItem *i = searchLW->currentItem(); + if( i == NULL ) + return; + + delete i; +} + +void SettingsDialog::onRecursiveAddClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Recursive search path" ), "" ); + if( p.isEmpty() ) + return; + + if( findListItem( recursiveLW, p ) != -1 ) + return; + + recursiveLW->addItem( p ); +} + +void SettingsDialog::onRecursiveRemoveClicked() +{ + QListWidgetItem *i = recursiveLW->currentItem(); + if( i == NULL ) + return; + + delete i; +} + + +void SettingsDialog::setupConnections() +{ + connect( bb, SIGNAL( accepted() ), this, SLOT( onOKClicked() ) ); + connect( bb, SIGNAL( rejected() ), this, SLOT( onCancelClicked() ) ); + + connect( pluginsB, SIGNAL( clicked( bool ) ), this, SLOT( onPluginBClicked() ) ); + connect( sheetsB, SIGNAL( clicked( bool ) ), this, SLOT( onSheetsBClicked() ) ); + connect( assetsB, SIGNAL( clicked( bool ) ), this, SLOT( onAssetsBClicked() ) ); + connect( primitivesB, SIGNAL( clicked( bool ) ), this, SLOT( onPrimitivesBClicked() ) ); + connect( ligoB, SIGNAL( clicked( bool ) ), this, SLOT( onLigoBClicked() ) ); + + connect( pathAddB, SIGNAL( clicked( bool ) ), this, SLOT( onPathAddClicked() ) ); + connect( pathRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onPathRemoveClicked() ) ); + connect( recAddB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveAddClicked() ) ); + connect( recRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveRemoveClicked() ) ); +} + diff --git a/code/studio/src/settings_dialog.h b/code/studio/src/settings_dialog.h new file mode 100644 index 000000000..11a3434f1 --- /dev/null +++ b/code/studio/src/settings_dialog.h @@ -0,0 +1,62 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SETTINGS_DIALOG_H +#define SETTINGS_DIALOG_H + +#include "ui_settings_dialog.h" + +class QSettings; + +class SettingsDialog : public QDialog, public Ui::SettingsDialog +{ + Q_OBJECT +public: + SettingsDialog( QDialog *parent = NULL ); + ~SettingsDialog(); + + void setSettings( QSettings *s ){ settings = s; } + + void load(); + +public Q_SLOTS: + void accept(); + void reject(); + + void onOKClicked(); + void onCancelClicked(); + + void onPluginBClicked(); + void onSheetsBClicked(); + void onAssetsBClicked(); + void onPrimitivesBClicked(); + void onLigoBClicked(); + + void onPathAddClicked(); + void onPathRemoveClicked(); + void onRecursiveAddClicked(); + void onRecursiveRemoveClicked(); + +private: + void setupConnections(); + void save(); + void saveSearchPaths(); + void saveRecursivePaths(); + + QSettings *settings; +}; + +#endif diff --git a/code/studio/src/settings_dialog.ui b/code/studio/src/settings_dialog.ui new file mode 100644 index 000000000..2fb6151d3 --- /dev/null +++ b/code/studio/src/settings_dialog.ui @@ -0,0 +1,255 @@ + + + SettingsDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 451 + 539 + + + + Ryzom Core Studio settings + + + + + + Paths + + + + + + Plugins + + + + + + + + + + ... + + + + + + + Sheets + + + + + + + + + + ... + + + + + + + Assets database + + + + + + + + + + ... + + + + + + + Primitives + + + + + + + + + + ... + + + + + + + LIGO config file + + + + + + + + + + ... + + + + + + + + + + Search paths + + + + + + + + + + 0 + 0 + + + + Add + + + Qt::ToolButtonTextOnly + + + + + + + + 0 + 0 + + + + Remove + + + Qt::ToolButtonTextOnly + + + + + + + Qt::Vertical + + + + 20 + 75 + + + + + + + + + + + Recursive search paths + + + + + + + + + + 0 + 0 + + + + Add + + + Qt::ToolButtonTextOnly + + + + + + + + 0 + 0 + + + + Remove + + + Qt::ToolButtonTextOnly + + + + + + + Qt::Vertical + + + + 20 + 76 + + + + + + + + + + + Qt::Horizontal + + + + 120 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + From 1d23a092c13e1886a57619e7a57de21e69a782b9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 26 May 2014 21:07:39 +0200 Subject: [PATCH 033/282] rename. --HG-- branch : gsoc2014-dfighter --- code/studio/src/settings_dialog.cpp | 2 +- code/studio/src/settings_dialog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp index 30eb39f0f..6824b0f56 100644 --- a/code/studio/src/settings_dialog.cpp +++ b/code/studio/src/settings_dialog.cpp @@ -1,4 +1,4 @@ -// Object Viewer Qt - MMORPG Framework +// Ryzom Core - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify diff --git a/code/studio/src/settings_dialog.h b/code/studio/src/settings_dialog.h index 11a3434f1..c6e7cc93a 100644 --- a/code/studio/src/settings_dialog.h +++ b/code/studio/src/settings_dialog.h @@ -1,4 +1,4 @@ -// Object Viewer Qt - MMORPG Framework +// Ryzom Core - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify From a92f32c1c434ee17e2516f5b156eafee840c6c0b Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Tue, 27 May 2014 14:19:37 +0530 Subject: [PATCH 034/282] few more changes to the CRUD layer in ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/dblayer.php | 69 +++++++++++++++---- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php index b095b4dc7..b82e7ea8f 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php @@ -67,34 +67,74 @@ class DBLayer{ return $statement; } - /** + /** * execute a query (an insertion query) that has parameters and return the id of it's insertion * @param $query the mysql query * @param $params the parameters that are being used by the query * @return returns the id of the last inserted element. */ - public function executeReturnId($query,$params){ - $statement = $this->PDO->prepare($query); - $this->PDO->beginTransaction(); - $statement->execute($params); - $lastId =$this->PDO->lastInsertId(); - $this->PDO->commit(); - return $lastId; + public function executeReturnId($tb_name,$data){ + $field_values =':'. implode(',:', array_keys($data)); + $field_options = implode(',', array_keys($data)); + try{ + $sth = $this->PDO->prepare("INSERT INTO $tb_name ($field_options) VALUE ($field_values)"); + foreach ($data as $key => $value ) + { + $sth->bindValue(":$key", $value); + } + $this->PDO->beginTransaction(); + //execution + $sth->execute(); + $lastId =$this->PDO->lastInsertId(); + $this->PDO->commit(); + }catch (Exception $e) + { + //for rolling back the changes during transaction + $this->PDO->rollBack(); + throw new Exception("error in inseting"); + } + return $lastId; } - /** + + + /** * * Select function using prepared statement * @param string $tb_name Table Name to Select * @param array $data Associative array * @param string $where where to select - * @return array Array containing fetched data + * @return statement object */ - public function select($query, $data) - { + public function selectWithParameter($param, $tb_name, $data, $where) + { + try{ + $sth = $this->PDO->prepare("SELECT $param FROM $tb_name WHERE $where"); + $this->PDO->beginTransaction(); + $sth->execute($data); + $this->PDO->commit(); + }catch(Exception $e) + { + $this->PDO->rollBack(); + throw new Exception("error selection"); + return false; + } + return $sth; + } + + /** + * + * Select function using prepared statement + * @param string $tb_name Table Name to Select + * @param array $data Associative array + * @param string $where where to select + * @return statement object + */ + public function select($tb_name, $data ,$where) + { try{ - $sth = $this->PDO->prepare($query); + $sth = $this->PDO->prepare("SELECT * FROM $tb_name WHERE $where"); $this->PDO->beginTransaction(); - $sth->execute(array($data)); + $sth->execute($data); $this->PDO->commit(); }catch(Exception $e) { @@ -152,7 +192,6 @@ class DBLayer{ $sth = $this->PDO->prepare("INSERT INTO $tb_name ($field_options) VALUE ($field_values)"); foreach ($data as $key => $value ) { - $sth->bindValue(":$key", $value); } $this->PDO->beginTransaction(); From 8a28b3583a6d49d19b95a11c70b28a5cc47f6152 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Wed, 28 May 2014 03:48:44 +0530 Subject: [PATCH 035/282] restructuring of AMS database functions to work with CRUD --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/assigned.php | 16 +++---- .../ryzom_ams/ams_lib/autoload/forwarded.php | 14 +++--- .../ryzom_ams/ams_lib/autoload/helpers.php | 2 +- .../ams_lib/autoload/in_support_group.php | 12 ++--- .../ams_lib/autoload/mail_handler.php | 9 +--- .../ryzom_ams/ams_lib/autoload/querycache.php | 8 ++-- .../ams_lib/autoload/support_group.php | 24 ++++------ .../ryzom_ams/ams_lib/autoload/sync.php | 25 ++++++----- .../ryzom_ams/ams_lib/autoload/ticket.php | 14 +++--- .../ams_lib/autoload/ticket_category.php | 15 +++---- .../ams_lib/autoload/ticket_content.php | 12 ++--- .../ams_lib/autoload/ticket_info.php | 18 ++++---- .../ryzom_ams/ams_lib/autoload/ticket_log.php | 16 +++---- .../ams_lib/autoload/ticket_reply.php | 12 ++--- .../ams_lib/autoload/ticket_user.php | 17 +++---- .../ryzom_ams/ams_lib/autoload/users.php | 36 +++++++-------- .../ryzom_ams/www/html/autoload/webusers.php | 44 +++++++++---------- .../ryzom_ams/www/html/func/add_user.php | 11 +++-- 18 files changed, 129 insertions(+), 176 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php index 8de17a9e2..d9d730c8e 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php @@ -80,9 +80,9 @@ class Assigned{ $dbl = new DBLayer("lib"); //check if ticket is already assigned - if($user_id == 0 && $dbl->execute(" SELECT * FROM `assigned` WHERE `Ticket` = :ticket_id", array('ticket_id' => $ticket_id) )->rowCount() ){ + if($user_id == 0 && $dbl->select("`assigned`", array('ticket_id' => $ticket_id), "`Ticket` = :ticket_id")->rowCount() ){ return true; - }else if( $dbl->execute(" SELECT * FROM `assigned` WHERE `Ticket` = :ticket_id and `User` = :user_id", array('ticket_id' => $ticket_id, 'user_id' => $user_id) )->rowCount()){ + }else if( $dbl->select("`assigned`", array('ticket_id' => $ticket_id, 'user_id' => $user_id), "`Ticket` = :ticket_id and `User` = :user_id")->rowCount() ){ return true; }else{ return false; @@ -115,9 +115,7 @@ class Assigned{ */ public function create() { $dbl = new DBLayer("lib"); - $query = "INSERT INTO `assigned` (`User`,`Ticket`) VALUES (:user, :ticket)"; - $values = Array('user' => $this->getUser(), 'ticket' => $this->getTicket()); - $dbl->execute($query, $values); + $dbl->insert("`assigned`", Array('User' => $this->getUser(), 'Ticket' => $this->getTicket()); } @@ -127,9 +125,7 @@ class Assigned{ */ public function delete() { $dbl = new DBLayer("lib"); - $query = "DELETE FROM `assigned` WHERE `User` = :user_id and `Ticket` = :ticket_id"; - $values = array('user_id' => $this->getUser() ,'ticket_id' => $this->getTicket()); - $dbl->execute($query, $values); + $dbl->delete("`assigned`", array('user_id' => $this->getUser() ,'ticket_id' => $this->getTicket(), "`User` = :user_id and `Ticket` = :ticket_id"); } /** @@ -139,7 +135,7 @@ class Assigned{ */ public function load($ticket_id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM `assigned` WHERE `Ticket` = :ticket_id", Array('ticket_id' => $ticket_id)); + $statement = $dbl->select("`assigned`", Array('ticket_id' => $ticket_id), "`Ticket` = :ticket_id"); $row = $statement->fetch(); $this->set($row); } @@ -181,4 +177,4 @@ class Assigned{ } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php index 54fece58c..ccba764e6 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php @@ -55,7 +55,7 @@ class Forwarded{ */ public static function isForwarded( $ticket_id) { $dbl = new DBLayer("lib"); - if( $dbl->execute(" SELECT * FROM `forwarded` WHERE `Ticket` = :ticket_id", array('ticket_id' => $ticket_id))->rowCount()){ + if( $dbl->select("`forwarded`", array('ticket_id' => $ticket_id), "`Ticket` = :ticket_id")->rowCount() ){ return true; }else{ return false; @@ -90,9 +90,7 @@ class Forwarded{ */ public function create() { $dbl = new DBLayer("lib"); - $query = "INSERT INTO `forwarded` (`Group`,`Ticket`) VALUES (:group, :ticket)"; - $values = Array('group' => $this->getGroup(), 'ticket' => $this->getTicket()); - $dbl->execute($query, $values); + $dbl->insert("`forwarded`", Array('Group' => $this->getGroup(), 'Ticket' => $this->getTicket())); } @@ -102,9 +100,7 @@ class Forwarded{ */ public function delete() { $dbl = new DBLayer("lib"); - $query = "DELETE FROM `forwarded` WHERE `Group` = :group_id and `Ticket` = :ticket_id"; - $values = array('group_id' => $this->getGroup() ,'ticket_id' => $this->getTicket()); - $dbl->execute($query, $values); + $dbl->delete("`forwarded`", array('group_id' => $this->getGroup() ,'ticket_id' => $this->getTicket(), "`Group` = :group_id and `Ticket` = :ticket_id"); } @@ -115,7 +111,7 @@ class Forwarded{ */ public function load( $ticket_id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM `forwarded` WHERE `Ticket` = :ticket_id", Array('ticket_id' => $ticket_id)); + $statement = $dbl->select("`forwarded`", Array('ticket_id' => $ticket_id), "`Ticket` = :ticket_id"); $row = $statement->fetch(); $this->set($row); } @@ -156,4 +152,4 @@ class Forwarded{ } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php index 40a96f6c1..2d26f3c21 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php @@ -206,7 +206,7 @@ class Helpers{ $dbr = new DBLayer("ring"); if (isset($_GET['UserId']) && isset($_COOKIE['ryzomId'])){ $id = $_GET['UserId']; - $statement = $dbr->execute("SELECT * FROM ring_users WHERE user_id=:id AND cookie =:cookie", array('id' => $id, 'cookie' => $_COOKIE['ryzomId'])); + $statement = $dbr->select("ring_users", array('id' => $id, 'cookie' => $_COOKIE['ryzomId']), "user_id=:id AND cookie =:cookie"); if ($statement->rowCount() ){ $entry = $statement->fetch(); //print_r($entry); diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php index bf10d3d9a..86c678cd3 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php @@ -21,7 +21,7 @@ class In_Support_Group{ public static function userExistsInSGroup( $user_id, $group_id) { $dbl = new DBLayer("lib"); //check if name is already used - if( $dbl->execute(" SELECT * FROM `in_support_group` WHERE `User` = :user_id and `Group` = :group_id ", array('user_id' => $user_id, 'group_id' => $group_id) )->rowCount() ){ + if( $dbl->select("in_support_group", array('user_id' => $user_id, 'group_id' => $group_id), "`User` = :user_id and `Group` = :group_id")->rowCount() ){ return true; }else{ return false; @@ -54,9 +54,7 @@ class In_Support_Group{ */ public function create() { $dbl = new DBLayer("lib"); - $query = "INSERT INTO `in_support_group` (`User`,`Group`) VALUES (:user, :group)"; - $values = Array('user' => $this->user, 'group' => $this->group); - $dbl->execute($query, $values); + $dbl->insert("`in_support_group`", Array('User' => $this->user, 'Group' => $this->group); } @@ -66,9 +64,7 @@ class In_Support_Group{ */ public function delete() { $dbl = new DBLayer("lib"); - $query = "DELETE FROM `in_support_group` WHERE `User` = :user_id and `Group` = :group_id"; - $values = array('user_id' => $this->getUser() ,'group_id' => $this->getGroup()); - $dbl->execute($query, $values); + $dbl->delete("`in_support_group`", array('user_id' => $this->getUser() ,'group_id' => $this->getGroup(), "`User` = :user_id and `Group` = :group_id"); } /* @@ -118,4 +114,4 @@ class In_Support_Group{ } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php index dde8d4e02..66cb0f95d 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php @@ -118,12 +118,7 @@ class Mail_Handler{ $id_user = $recipient; $recipient = NULL; } - - $query = "INSERT INTO email (Recipient,Subject,Body,Status,Attempts,Sender,UserId,MessageId,TicketId) VALUES (:recipient, :subject, :body, :status, :attempts, :sender, :id_user, :messageId, :ticketId)"; - $values = array('recipient' => $recipient, 'subject' => $subject, 'body' => $body, 'status' => 'NEW', 'attempts'=> 0, 'sender' => $from,'id_user' => $id_user, 'messageId' => 0, 'ticketId'=> $ticket_id); - $db = new DBLayer("lib"); - $db->execute($query, $values); - + $db->insert("email", array('Recipient' => $recipient, 'Subject' => $subject, 'Body' => $body, 'Status' => 'NEW', 'Attempts'=> 0, 'Sender' => $from,'UserId' => $id_user, 'MessageId' => 0, 'TicketId'=> $ticket_id)); } @@ -173,7 +168,7 @@ class Mail_Handler{ //select all new & failed emails & try to send them //$emails = db_query("select * from email where status = 'NEW' or status = 'FAILED'"); - $statement = $this->db->executeWithoutParams("select * from email where Status = 'NEW' or Status = 'FAILED'"); + $statement = $this->db->select("email",array(null), "Status = 'NEW' or Status = 'FAILED'"); $emails = $statement->fetchAll(); foreach($emails as $email) { diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php index 3da0887c9..6f0c0dca6 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php @@ -47,7 +47,7 @@ class Querycache{ */ public function load_With_SID( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ams_querycache WHERE SID=:id", array('id' => $id)); + $statement = $dbl->select("ams_querycache", array('id' => $id), "SID=:id"); $row = $statement->fetch(); $this->set($row); } @@ -58,9 +58,7 @@ class Querycache{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ams_querycache SET type= :t, query = :q, db = :d WHERE SID=:id"; - $values = Array('id' => $this->getSID(), 't' => $this->getType(), 'q' => $this->getQuery(), 'd' => $this->getDb()); - $statement = $dbl->execute($query, $values); + $dbl->update("ams_querycache", Array('type' => $this->getType(), 'query' => $this->getQuery(), 'db' => $this->getDb(), "SID=$this->getSID()" ); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -127,4 +125,4 @@ class Querycache{ $this->db= $d; } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php index c42d12efb..7b8a864d4 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php @@ -24,7 +24,7 @@ class Support_Group{ */ public static function getGroup($id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM support_group WHERE SGroupId = :id", array('id' => $id)); + $statement = $dbl->select("support_group", array('id' => $id), "SGroupId = :id"); $row = $statement->fetch(); $instanceGroup = new self(); $instanceGroup->set($row); @@ -102,10 +102,10 @@ class Support_Group{ public static function supportGroup_EntryNotExists( $name, $tag) { $dbl = new DBLayer("lib"); //check if name is already used - if( $dbl->execute("SELECT * FROM support_group WHERE Name = :name",array('name' => $name))->rowCount() ){ + if( $dbl->select("support_group", array('name' => $name), "Name = :name")->rowCount() ){ return "NAME_TAKEN"; } - else if( $dbl->execute("SELECT * FROM support_group WHERE Tag = :tag",array('tag' => $tag))->rowCount() ){ + else if( $dbl->select("support_group", array('tag' => $tag), "Tag = :tag")->rowCount() ){ return "TAG_TAKEN"; }else{ return "SUCCESS"; @@ -121,7 +121,7 @@ class Support_Group{ public static function supportGroup_Exists( $id) { $dbl = new DBLayer("lib"); //check if supportgroup id exist - if( $dbl->execute("SELECT * FROM support_group WHERE SGroupId = :id",array('id' => $id ))->rowCount() ){ + if( $dbl->select("support_group", array('id' => $id ), "SGroupId = :id")->rowCount() ){ return true; }else{ return false; @@ -305,9 +305,7 @@ class Support_Group{ */ public function create() { $dbl = new DBLayer("lib"); - $query = "INSERT INTO support_group (Name, Tag, GroupEmail, IMAP_MailServer, IMAP_Username, IMAP_Password) VALUES (:name, :tag, :groupemail, :imap_mailserver, :imap_username, :imap_password)"; - $values = Array('name' => $this->getName(), 'tag' => $this->getTag(), 'groupemail' => $this->getGroupEmail(), 'imap_mailserver' => $this->getIMAP_MailServer(), 'imap_username' => $this->getIMAP_Username(), 'imap_password' => $this->getIMAP_Password()); - $dbl->execute($query, $values); + $dbl->insert("support_group", Array('Name' => $this->getName(), 'Tag' => $this->getTag(), 'GroupEmail' => $this->getGroupEmail(), 'IMAP_MailServer' => $this->getIMAP_MailServer(), 'IMAP_Username' => $this->getIMAP_Username(), 'IMAP_Password' => $this->getIMAP_Password()); } @@ -318,7 +316,7 @@ class Support_Group{ */ public function load_With_SGroupId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM `support_group` WHERE `SGroupId` = :id", array('id' => $id)); + $statement = $dbl->select("`support_group`", array('id' => $id), "`SGroupId` = :id"); $row = $statement->fetch(); $this->set($row); } @@ -329,9 +327,7 @@ class Support_Group{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE `support_group` SET `Name` = :name, `Tag` = :tag, `GroupEmail` = :groupemail, `IMAP_MailServer` = :mailserver, `IMAP_Username` = :username, `IMAP_Password` = :password WHERE `SGroupId` = :id"; - $values = Array('id' => $this->getSGroupId(), 'name' => $this->getName(), 'tag' => $this->getTag(), 'groupemail' => $this->getGroupEmail(), 'mailserver' => $this->getIMAP_MailServer(), 'username' => $this->getIMAP_Username(), 'password' => $this->getIMAP_Password() ); - $statement = $dbl->execute($query, $values); + $dbl->update("`support_group`", Array('Name' => $this->getName(), 'Tag' => $this->getTag(), 'GroupEmail' => $this->getGroupEmail(), 'IMAP_MailServer' => $this->getIMAP_MailServer(), 'IMAP_Username' => $this->getIMAP_Username(), 'IMAP_password' => $this->getIMAP_Password(), "`SGroupId` = $this->getSGroupId()"); } @@ -341,9 +337,7 @@ class Support_Group{ */ public function delete(){ $dbl = new DBLayer("lib"); - $query = "DELETE FROM `support_group` WHERE `SGroupId` = :id"; - $values = Array('id' => $this->getSGroupId()); - $statement = $dbl->execute($query, $values); + $dbl->delete("`support_group`", Array('id' => $this->getSGroupId(), "`SGroupId` = :id"); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -453,4 +447,4 @@ class Support_Group{ public function setIMAP_Password($p){ $this->iMap_Password = $p; } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php index e9d4c8748..a79ef8b83 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php @@ -42,34 +42,37 @@ class Sync{ $decode = json_decode($record['query']); $values = array('username' => $decode[0]); //make connection with and put into shard db & delete from the lib - $sth = $db->execute("SELECT UId FROM user WHERE Login= :username;", $values); + $sth=$db->selectWithParameter("UId", "user", $values, "Login= :username" ); $result = $sth->fetchAll(); foreach ($result as $UId) { - $ins_values = array('id' => $UId['UId']); - $db->execute("INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES (:id, 'r2', 'OPEN');", $ins_values); - $db->execute("INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES (:id , 'ryzom_open', 'OPEN');", $ins_values); + $ins_values = array('UId' => $UId['UId']); + $ins_values['ClientApplication'] = "r2"; + $ins_values['AccessPrivilege'] = "OPEN"; + $db->insert("permission", $ins_values); + $ins_values['ClientApplication'] = 'ryzom_open'; + $db->insert("permission",$ins_values); } break; case 'change_pass': $decode = json_decode($record['query']); - $values = array('user' => $decode[0], 'pass' => $decode[1]); + $values = array('Password' => $decode[1]); //make connection with and put into shard db & delete from the lib - $db->execute("UPDATE user SET Password = :pass WHERE Login = :user",$values); + $db->update("user", $values, "Login = $decode[0]"); break; case 'change_mail': $decode = json_decode($record['query']); - $values = array('user' => $decode[0], 'mail' => $decode[1]); + $values = array('Email' => $decode[1]); //make connection with and put into shard db & delete from the lib - $db->execute("UPDATE user SET Email = :mail WHERE Login = :user",$values); + $db->update("user", $values, "Login = $decode[0]"); break; case 'createUser': $decode = json_decode($record['query']); - $values = array('login' => $decode[0], 'pass' => $decode[1], 'mail' => $decode[2] ); + $values = array('Login' => $decode[0], 'Password' => $decode[1], 'Email' => $decode[2] ); //make connection with and put into shard db & delete from the lib - $db->execute("INSERT INTO user (Login, Password, Email) VALUES (:login, :pass, :mail)",$values); + $db->insert("user", $values); break; } - $dbl->execute("DELETE FROM ams_querycache WHERE SID=:SID",array('SID' => $record['SID'])); + $dbl->delete("ams_querycache", array('SID' => $record['SID']), "SID=:SID"); } if ($display == true) { print('Syncing completed'); diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php index 21e2614d5..51f987e5a 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php @@ -27,7 +27,7 @@ class Ticket{ public static function ticketExists($id) { $dbl = new DBLayer("lib"); //check if ticket exists - if( $dbl->execute(" SELECT * FROM `ticket` WHERE `TId` = :ticket_id", array('ticket_id' => $id) )->rowCount() ){ + if( $dbl->select("`ticket`", array('ticket_id' => $id), "`TId` = :ticket_id")->rowCount() ){ return true; }else{ return false; @@ -343,9 +343,7 @@ class Ticket{ */ public function create(){ $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket (Timestamp, Title, Status, Queue, Ticket_Category, Author, Priority) VALUES (now(), :title, :status, :queue, :tcat, :author, :priority)"; - $values = Array('title' => $this->title, 'status' => $this->status, 'queue' => $this->queue, 'tcat' => $this->ticket_category, 'author' => $this->author, 'priority' => $this->priority); - $this->tId = $dbl->executeReturnId($query, $values); ; + $this->tId = $dbl->executeReturnId("ticket", Array('Timestamp'=>now(), 'Title' => $this->title, 'Status' => $this->status, 'Queue' => $this->queue, 'Ticket_Category' => $this->ticket_category, 'Author' => $this->author, 'Priority' => $this->priority)); } @@ -356,7 +354,7 @@ class Ticket{ */ public function load_With_TId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket WHERE TId=:id", array('id' => $id)); + $statement = $dbl->select("ticket", array('id' => $id), "TId=:id"); $row = $statement->fetch(); $this->tId = $row['TId']; $this->timestamp = $row['Timestamp']; @@ -374,9 +372,7 @@ class Ticket{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ticket SET Timestamp = :timestamp, Title = :title, Status = :status, Queue = :queue, Ticket_Category = :tcat, Author = :author, Priority = :priority WHERE TId=:id"; - $values = Array('id' => $this->tId, 'timestamp' => $this->timestamp, 'title' => $this->title, 'status' => $this->status, 'queue' => $this->queue, 'tcat' => $this->ticket_category, 'author' => $this->author, 'priority' => $this->priority); - $statement = $dbl->execute($query, $values); + $dbl->update("ticket", Array('Timestamp' => $this->timestamp, 'Title' => $this->title, 'Status' => $this->status, 'Queue' => $this->queue, 'Ticket_Category' => $this->ticket_category, 'Author' => $this->author, 'Priority' => $this->priority), "TId=$this->tId"); } @@ -575,4 +571,4 @@ class Ticket{ $this->priority = $p; } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php index 92e603d12..f6941febe 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php @@ -16,10 +16,7 @@ class Ticket_Category{ */ public static function createTicketCategory( $name) { $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket_category (Name) VALUES (:name)"; - $values = Array('name' => $name); - $dbl->execute($query, $values); - + $dbl->insert("ticket_category", Array('Name' => $name)); } @@ -40,7 +37,7 @@ class Ticket_Category{ */ public static function getAllCategories() { $dbl = new DBLayer("lib"); - $statement = $dbl->executeWithoutParams("SELECT * FROM ticket_category"); + $statement = $dbl->select("ticket_category", array(null), "1"); $row = $statement->fetchAll(); $result = Array(); foreach($row as $category){ @@ -70,7 +67,7 @@ class Ticket_Category{ */ public function load_With_TCategoryId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_category WHERE TCategoryId=:id", array('id' => $id)); + $statement = $dbl->select("ticket_category", array('id' => $id), "TCategoryId=:id"); $row = $statement->fetch(); $this->tCategoryId = $row['TCategoryId']; $this->name = $row['Name']; @@ -82,9 +79,7 @@ class Ticket_Category{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ticket_category SET Name = :name WHERE TCategoryId=:id"; - $values = Array('id' => $this->tCategoryId, 'name' => $this->name); - $statement = $dbl->execute($query, $values); + $dbl->update("ticket_category", Array('Name' => $this->name), "TCategoryId = $this->tCategoryId"); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -126,4 +121,4 @@ class Ticket_Category{ } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php index 445cad867..8b7787f8e 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php @@ -43,9 +43,7 @@ class Ticket_Content{ */ public function create() { $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket_content (Content) VALUES (:content)"; - $values = Array('content' => $this->content); - $this->tContentId = $dbl->executeReturnId($query, $values); ; + $this->tContentId = $dbl->executeReturnId("ticket_content", Array('Content' => $this->content)); } @@ -56,7 +54,7 @@ class Ticket_Content{ */ public function load_With_TContentId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_content WHERE TContentId=:id", array('id' => $id)); + $statement = $dbl->select("ticket_content", array('id' => $id), "TContentId=:id"); $row = $statement->fetch(); $this->tContentId = $row['TContentId']; $this->content = $row['Content']; @@ -67,9 +65,7 @@ class Ticket_Content{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ticket_content SET Content = :content WHERE TContentId=:id"; - $values = Array('id' => $this->tContentId, 'content' => $this->content); - $statement = $dbl->execute($query, $values); + $dbl->update("ticket_content", Array('Content' => $this->content), "TContentId = $this->tContentId"); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -110,4 +106,4 @@ class Ticket_Content{ $this->tContentId = $c; } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php index fc852d093..eb7c8ebc5 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php @@ -52,7 +52,7 @@ class Ticket_Info{ public static function TicketHasInfo($ticket_id) { $dbl = new DBLayer("lib"); //check if ticket is already assigned - if( $dbl->execute(" SELECT * FROM `ticket_info` WHERE `Ticket` = :ticket_id", array('ticket_id' => $ticket_id) )->rowCount() ){ + if( $dbl->select("`ticket_info`", array('ticket_id' => $ticket_id), "`Ticket` = :ticket_id")->rowCount() ){ return true; }else{ return false; @@ -102,7 +102,7 @@ class Ticket_Info{ */ public function load_With_TInfoId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_info WHERE TInfoId=:id", array('id' => $id)); + $statement = $dbl->select("ticket_info", array('id' => $id), "TInfoId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -115,7 +115,7 @@ class Ticket_Info{ */ public function load_With_Ticket( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_info WHERE Ticket=:id", array('id' => $id)); + $statement = $dbl->select("ticket_info", array('id' => $id), "Ticket=:id"); $row = $statement->fetch(); $this->set($row); } @@ -127,12 +127,10 @@ class Ticket_Info{ */ public function create() { $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket_info ( Ticket, ShardId, UserPosition,ViewPosition, ClientVersion, PatchVersion,ServerTick, ConnectState, LocalAddress, Memory, OS, -Processor, CPUID, CpuMask, HT, NeL3D, UserId) VALUES ( :ticket, :shardid, :userposition, :viewposition, :clientversion, :patchversion, :servertick, :connectstate, :localaddress, :memory, :os, :processor, :cpuid, :cpu_mask, :ht, :nel3d, :user_id )"; - $values = Array('ticket' => $this->getTicket(), 'shardid' => $this->getShardId(), 'userposition' => $this->getUser_Position(), 'viewposition' => $this->getView_Position(), 'clientversion' => $this->getClient_Version(), -'patchversion' => $this->getPatch_Version(), 'servertick' => $this->getServer_Tick(), 'connectstate' => $this->getConnect_State(), 'localaddress' => $this->getLocal_Address(), 'memory' => $this->getMemory(), 'os'=> $this->getOS(), 'processor' => $this->getProcessor(), 'cpuid' => $this->getCPUId(), -'cpu_mask' => $this->getCpu_Mask(), 'ht' => $this->getHT(), 'nel3d' => $this->getNel3D(), 'user_id' => $this->getUser_Id()); - $dbl->execute($query, $values); + $values = Array('Ticket' => $this->getTicket(), 'ShardId' => $this->getShardId(), 'UserPosition' => $this->getUser_Position(), 'ViewPosition' => $this->getView_Position(), 'ClientVersion' => $this->getClient_Version(), +'PatchVersion' => $this->getPatch_Version(), 'ServerTick' => $this->getServer_Tick(), 'ConnectState' => $this->getConnect_State(), 'LocalAddress' => $this->getLocal_Address(), 'Memory' => $this->getMemory(), 'OS'=> $this->getOS(), 'Processor' => $this->getProcessor(), 'CPUID' => $this->getCPUId(), +'CpuMask' => $this->getCpu_Mask(), 'HT' => $this->getHT(), 'NeL3D' => $this->getNel3D(), 'UserId' => $this->getUser_Id()); + $dbl->insert("ticket_info",$values); } @@ -411,4 +409,4 @@ Processor, CPUID, CpuMask, HT, NeL3D, UserId) VALUES ( :ticket, :shardid, :user } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php index 8c7439bc0..6693fe3ce 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php @@ -82,9 +82,8 @@ class Ticket_Log{ global $TICKET_LOGGING; if($TICKET_LOGGING){ $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket_log (Timestamp, Query, Ticket, Author) VALUES (now(), :query, :ticket, :author )"; - $values = Array('ticket' => $ticket_id, 'author' => $author_id, 'query' => json_encode(array($action,$arg))); - $dbl->execute($query, $values); + $values = Array('Timestamp'=>now(), 'Query' => json_encode(array($action,$arg)), 'Ticket' => $ticket_id, 'Author' => $author_id); + $dbl->insert("ticket_log", $values); } } @@ -148,7 +147,7 @@ class Ticket_Log{ */ public function load_With_TLogId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_log WHERE TLogId=:id", array('id' => $id)); + $dbl->select("ticket_log", array('id' => $id), "TLogId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -159,9 +158,10 @@ class Ticket_Log{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ticket_log SET Timestamp = :timestamp, Query = :query, Author = :author, Ticket = :ticket WHERE TLogId=:id"; - $values = Array('id' => $this->getTLogId(), 'timestamp' => $this->getTimestamp(), 'query' => $this->getQuery(), 'author' => $this->getAuthor(), 'ticket' => $this->getTicket() ); - $statement = $dbl->execute($query, $values); + + $values = Array('timestamp' => $this->getTimestamp(), 'query' => $this->getQuery(), 'author' => $this->getAuthor(), 'ticket' => $this->getTicket() ); + $dbl->update("ticket_log", $values, "TLogId = $this->getTLogId()"); + } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -273,4 +273,4 @@ class Ticket_Log{ } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php index 8e784543d..2675fcfbe 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php @@ -123,9 +123,7 @@ class Ticket_Reply{ */ public function create(){ $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket_reply (Ticket, Content, Author, Timestamp, Hidden) VALUES (:ticket, :content, :author, now(), :hidden)"; - $values = Array('ticket' => $this->ticket, 'content' => $this->content, 'author' => $this->author, 'hidden' => $this->hidden); - $this->tReplyId = $dbl->executeReturnId($query, $values); + $this->tReplyId = $dbl->executeReturnId("ticket_reply", Array('Ticket' => $this->ticket, 'Content' => $this->content, 'Author' => $this->author,'Timestamp'=>now(), 'Hidden' => $this->hidden)); } /** @@ -135,7 +133,7 @@ class Ticket_Reply{ */ public function load_With_TReplyId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_reply WHERE TReplyId=:id", array('id' => $id)); + $statement = $dbl->select("ticket_reply", array('id' => $id), "TReplyId=:id"); $row = $statement->fetch(); $this->tReplyId = $row['TReplyId']; $this->ticket = $row['Ticket']; @@ -150,9 +148,7 @@ class Ticket_Reply{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ticket SET Ticket = :ticket, Content = :content, Author = :author, Timestamp = :timestamp, Hidden = :hidden WHERE TReplyId=:id"; - $values = Array('id' => $this->tReplyId, 'timestamp' => $this->timestamp, 'ticket' => $this->ticket, 'content' => $this->content, 'author' => $this->author, 'hidden' => $this->hidden); - $statement = $dbl->execute($query, $values); + $dbl->update("ticket", Array('Ticket' => $this->ticket, 'Content' => $this->content, 'Author' => $this->author, 'Timestamp' => $this->timestamp, 'Hidden' => $this->hidden), "TReplyId=$this->tReplyId, "); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -249,4 +245,4 @@ class Ticket_Reply{ public function setHidden($h){ $this->hidden = $h; } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php index 46125e284..0937b48b0 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php @@ -21,10 +21,7 @@ class Ticket_User{ */ public static function createTicketUser( $extern_id, $permission) { $dbl = new DBLayer("lib"); - $query = "INSERT INTO ticket_user (Permission, ExternId) VALUES (:perm, :ext_id)"; - $values = Array('perm' => $permission, 'ext_id' => $extern_id); - $dbl->execute($query, $values); - + $dbl->insert("ticket_user",array('Permission' => $permission, 'ExternId' => $extern_id)); } @@ -73,7 +70,7 @@ class Ticket_User{ */ public static function getModsAndAdmins() { $dbl = new DBLayer("lib"); - $statement = $dbl->executeWithoutParams("SELECT * FROM `ticket_user` WHERE `Permission` > 1"); + $statement = $dbl->select("ticket_user", array(null), "`Permission` > 1" ); $rows = $statement->fetchAll(); $result = Array(); foreach($rows as $user){ @@ -93,7 +90,7 @@ class Ticket_User{ public static function constr_ExternId( $id) { $instance = new self(); $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_user WHERE ExternId=:id", array('id' => $id)); + $statement = $dbl->select("ticket_user" ,array('id'=>$id) ,"ExternId=:id"); $row = $statement->fetch(); $instance->tUserId = $row['TUserId']; $instance->permission = $row['Permission']; @@ -196,7 +193,7 @@ class Ticket_User{ */ public function load_With_TUserId( $id) { $dbl = new DBLayer("lib"); - $statement = $dbl->execute("SELECT * FROM ticket_user WHERE TUserId=:id", array('id' => $id)); + $statement = $dbl->select("ticket_user" ,array('id'=>$id), "TUserId=:id" ); $row = $statement->fetch(); $this->tUserId = $row['TUserId']; $this->permission = $row['Permission']; @@ -209,9 +206,7 @@ class Ticket_User{ */ public function update(){ $dbl = new DBLayer("lib"); - $query = "UPDATE ticket_user SET Permission = :perm, ExternId = :ext_id WHERE TUserId=:id"; - $values = Array('id' => $this->tUserId, 'perm' => $this->permission, 'ext_id' => $this->externId); - $statement = $dbl->execute($query, $values); + $dbl->update("ticket_user" ,array('Permission' => $this->permission, 'ExternId' => $this->externId) ,"TUserId=$this->tUserId"); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// @@ -266,4 +261,4 @@ class Ticket_User{ } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php index f83f46576..e9463b0b0 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php @@ -291,9 +291,10 @@ class Users{ //make connection with and put into shard db $values['user_id']= $user_id; $dbs = new DBLayer("shard"); - $dbs->execute("INSERT INTO user (Login, Password, Email) VALUES (:name, :pass, :mail)",$values); + $dbs->insert("user", $values); $dbr = new DBLayer("ring"); - $dbr->execute("INSERT INTO ring_users (user_id, user_name, user_type) VALUES (:user_id, :name, 'ut_pioneer')",$values); + $values['user_type'] = 'ut_pioneer'; + $dbr->insert("ring_users", $values); ticket_user::createTicketUser( $user_id, 1); return "ok"; } @@ -301,7 +302,7 @@ class Users{ //oh noooz, the shard is offline! Put in query queue at ams_lib db! try { $dbl = new DBLayer("lib"); - $dbl->execute("INSERT INTO ams_querycache (type, query, db) VALUES (:type, :query, :db)",array("type" => "createUser", + $dbl->insert("ams_querycache", array("type" => "createUser", "query" => json_encode(array($values["name"],$values["pass"],$values["mail"])), "db" => "shard")); ticket_user::createTicketUser( $user_id , 1 ); return "shardoffline"; @@ -323,21 +324,20 @@ class Users{ try { $values = array('username' => $pvalues[0]); $dbs = new DBLayer("shard"); - $sth = $dbs->execute("SELECT UId FROM user WHERE Login= :username;", $values); + $sth = $dbs->selectWithParameter("UId", "user", $values, "Login= :username"); $result = $sth->fetchAll(); foreach ($result as $UId) { - $ins_values = array('id' => $UId['UId']); - $dbs->execute("INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES (:id, 'r2', 'OPEN');", $ins_values); - $dbs->execute("INSERT INTO permission (UId, ClientApplication, AccessPrivilege) VALUES (:id , 'ryzom_open', 'OPEN');", $ins_values); + $ins_values = array('UId' => $UId['UId'], 'clientApplication' => 'r2', 'AccessPrivilege' => 'OPEN'); + $dbs->insert("permission", $ins_values); + $ins_values['clientApplication'] = 'ryzom_open'; + $dbs->insert("permission", $ins_values); } } catch (PDOException $e) { //oh noooz, the shard is offline! Put it in query queue at ams_lib db! $dbl = new DBLayer("lib"); - $dbl->execute("INSERT INTO ams_querycache (type, query, db) VALUES (:type, :query, :db)",array("type" => "createPermissions", - "query" => json_encode(array($pvalues[0])), "db" => "shard")); - - + $dbl->insert("ams_querycache", array("type" => "createPermissions", + "query" => json_encode(array($pvalues[0])), "db" => "shard")); } return true; } @@ -421,19 +421,19 @@ class Users{ */ protected static function setAmsPassword($user, $pass){ - $values = Array('user' => $user, 'pass' => $pass); + $values = Array('Password' => $pass); try { //make connection with and put into shard db $dbs = new DBLayer("shard"); - $dbs->execute("UPDATE user SET Password = :pass WHERE Login = :user ",$values); + $dbs->update("user", $values, "Login = $user"); return "ok"; } catch (PDOException $e) { //oh noooz, the shard is offline! Put in query queue at ams_lib db! try { $dbl = new DBLayer("lib"); - $dbl->execute("INSERT INTO ams_querycache (type, query, db) VALUES (:type, :query, :db)",array("type" => "change_pass", + $dbl->insert("ams_querycache", array("type" => "change_pass", "query" => json_encode(array($values["user"],$values["pass"])), "db" => "shard")); return "shardoffline"; }catch (PDOException $e) { @@ -451,19 +451,19 @@ class Users{ */ protected static function setAmsEmail($user, $mail){ - $values = Array('user' => $user, 'mail' => $mail); + $values = Array('Email' => $mail); try { //make connection with and put into shard db $dbs = new DBLayer("shard"); - $dbs->execute("UPDATE user SET Email = :mail WHERE Login = :user ",$values); + $dbs->update("user", $values, "Login = $user"); return "ok"; } catch (PDOException $e) { //oh noooz, the shard is offline! Put in query queue at ams_lib db! try { $dbl = new DBLayer("lib"); - $dbl->execute("INSERT INTO ams_querycache (type, query, db) VALUES (:type, :query, :db)",array("type" => "change_mail", + $dbl->insert("ams_querycache", array("type" => "change_mail", "query" => json_encode(array($values["user"],$values["mail"])), "db" => "shard")); return "shardoffline"; }catch (PDOException $e) { @@ -474,4 +474,4 @@ class Users{ } - \ No newline at end of file + diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php b/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php index d8e59d1f9..78916e606 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php @@ -53,7 +53,7 @@ class WebUsers extends Users{ */ protected function checkUserNameExists($username){ $dbw = new DBLayer("web"); - return $dbw->execute("SELECT * FROM ams_user WHERE Login = :name",array('name' => $username))->rowCount(); + return $dbw->select("ams_user", array('name' => $username), "Login = :name")->rowCount(); } @@ -65,7 +65,7 @@ class WebUsers extends Users{ */ protected function checkEmailExists($email){ $dbw = new DBLayer("web"); - return $dbw->execute("SELECT * FROM ams_user WHERE Email = :email",array('email' => $email))->rowCount(); + return $dbw->select("ams_user" ,array('email' => $email),"Email = :email")->rowCount(); } @@ -78,7 +78,7 @@ class WebUsers extends Users{ public static function checkLoginMatch($username,$password){ $dbw = new DBLayer("web"); - $statement = $dbw->execute("SELECT * FROM ams_user WHERE Login=:user", array('user' => $username)); + $statement = $dbw->select("ams_user", array('value' => $value),"Login=:value OR Email=:value"); $row = $statement->fetch(); $salt = substr($row['Password'],0,2); $hashed_input_pass = crypt($password, $salt); @@ -97,7 +97,7 @@ class WebUsers extends Users{ */ public static function getId($username){ $dbw = new DBLayer("web"); - $statement = $dbw->execute("SELECT * FROM ams_user WHERE Login=:username", array('username' => $username)); + $statement = $dbw->select("ams_user", array('username' => $username), "Login=:username"); $row = $statement->fetch(); return $row['UId']; } @@ -110,7 +110,7 @@ class WebUsers extends Users{ */ public static function getIdFromEmail($email){ $dbw = new DBLayer("web"); - $statement = $dbw->execute("SELECT * FROM ams_user WHERE Email=:email", array('email' => $email)); + $statement = $dbw->select("ams_user", array('email' => $email), "Email=:email"); $row = $statement->fetch(); if(!empty($row)){ return $row['UId']; @@ -134,7 +134,7 @@ class WebUsers extends Users{ public function getUsername(){ $dbw = new DBLayer("web"); if(! isset($this->login) || $this->login == ""){ - $statement = $dbw->execute("SELECT * FROM ams_user WHERE UId=:id", array('id' => $this->uId)); + $statement = $dbw->select("ams_user", array('id' => $this->uId), "UId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -148,7 +148,7 @@ class WebUsers extends Users{ public function getEmail(){ $dbw = new DBLayer("web"); if(! isset($this->email) || $this->email == ""){ - $statement = $dbw->execute("SELECT * FROM ams_user WHERE UId=:id", array('id' => $this->uId)); + $statement = $dbw->select("ams_user", array('id' => $this->uId), "UId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -160,7 +160,7 @@ class WebUsers extends Users{ */ public function getHashedPass(){ $dbw = new DBLayer("web"); - $statement = $dbw->execute("SELECT * FROM ams_user WHERE UId=:id", array('id' => $this->uId)); + $statement = $dbw->select("ams_user", array('id' => $this->uId), "UId=:id"); $row = $statement->fetch(); return $row['Password']; } @@ -174,7 +174,7 @@ class WebUsers extends Users{ $dbw = new DBLayer("web"); if(! (isset($this->firstname) && isset($this->lastname) && isset($this->gender) && isset($this->country) && isset($this->receiveMail) ) || $this->firstname == "" || $this->lastname == "" || $this->gender == "" || $this->country == "" || $this->receiveMail == ""){ - $statement = $dbw->execute("SELECT * FROM ams_user WHERE UId=:id", array('id' => $this->uId)); + $statement = $dbw->select("ams_user", array('id' => $this->uId), "UId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -189,7 +189,7 @@ class WebUsers extends Users{ public function getReceiveMail(){ $dbw = new DBLayer("web"); if(! isset($this->receiveMail) || $this->receiveMail == ""){ - $statement = $dbw->execute("SELECT * FROM ams_user WHERE UId=:id", array('id' => $this->uId)); + $statement = $dbw->select("ams_user", array('id' => $this->uId), "UId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -203,7 +203,7 @@ class WebUsers extends Users{ public function getLanguage(){ $dbw = new DBLayer("web"); if(! isset($this->language) || $this->language == ""){ - $statement = $dbw->execute("SELECT * FROM ams_user WHERE UId=:id", array('id' => $this->uId)); + $statement = $dbw->select("ams_user", array('id' => $this->uId), "UId=:id"); $row = $statement->fetch(); $this->set($row); } @@ -234,11 +234,11 @@ class WebUsers extends Users{ $hashpass = crypt($pass, WebUsers::generateSALT()); $reply = WebUsers::setAmsPassword($user, $hashpass); - $values = Array('user' => $user, 'pass' => $hashpass); + $values = Array('pass' => $hashpass); try { //make connection with and put into shard db $dbw = new DBLayer("web"); - $dbw->execute("UPDATE ams_user SET Password = :pass WHERE Login = :user ",$values); + $dbw->update("ams_user", $values,"Login = $user"); } catch (PDOException $e) { //ERROR: the web DB is offline @@ -256,11 +256,11 @@ class WebUsers extends Users{ */ public static function setEmail($user, $mail){ $reply = WebUsers::setAmsEmail($user, $mail); - $values = Array('user' => $user, 'mail' => $mail); + $values = Array('Email' => $mail); try { //make connection with and put into shard db $dbw = new DBLayer("web"); - $dbw->execute("UPDATE ams_user SET Email = :mail WHERE Login = :user ",$values); + $dbw->update("ams_user", $values, "Login = $user"); } catch (PDOException $e) { //ERROR: the web DB is offline @@ -276,11 +276,11 @@ class WebUsers extends Users{ * @param $receivemail the receivemail setting . */ public static function setReceiveMail($user, $receivemail){ - $values = Array('user' => $user, 'receivemail' => $receivemail); + $values = Array('Receivemail' => $receivemail); try { //make connection with and put into shard db $dbw = new DBLayer("web"); - $dbw->execute("UPDATE ams_user SET ReceiveMail = :receivemail WHERE UId = :user ",$values); + $dbw->update("ams_user", $values, "UId = $user" ); } catch (PDOException $e) { //ERROR: the web DB is offline @@ -295,11 +295,11 @@ class WebUsers extends Users{ * @param $language the new language value. */ public static function setLanguage($user, $language){ - $values = Array('user' => $user, 'language' => $language); + $values = Array('Language' => $language); try { //make connection with and put into shard db $dbw = new DBLayer("web"); - $dbw->execute("UPDATE ams_user SET Language = :language WHERE UId = :user ",$values); + $dbw->update("ams_user", $values, "UId = $user"); } catch (PDOException $e) { //ERROR: the web DB is offline @@ -344,15 +344,15 @@ class WebUsers extends Users{ $lang = $DEFAULT_LANGUAGE; } - $values = Array('name' => $name, 'pass' => $pass, 'mail' => $mail, 'lang' => $lang); + $values = Array('Login' => $name, 'Password' => $pass, 'Email' => $mail, 'Language' => $lang); try { $dbw = new DBLayer("web"); - return $dbw->executeReturnId("INSERT INTO ams_user (Login, Password, Email, Language) VALUES (:name, :pass, :mail, :lang)",$values); + return $dbw->executeReturnId("ams_user", $values); } catch (PDOException $e) { //ERROR: the web DB is offline } } -} \ No newline at end of file +} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php index fa08ef1a5..a40e22450 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php @@ -66,15 +66,14 @@ function write_user($newUser){ $hashpass = crypt($newUser["pass"], WebUsers::generateSALT()); $params = array( - 'name' => $newUser["name"], - 'pass' => $hashpass, - 'mail' => $newUser["mail"] + 'Login' => $newUser["name"], + 'Password' => $hashpass, + 'Email' => $newUser["mail"] ); - try{ //make new webuser - $user_id = WebUsers::createWebuser($params['name'], $params['pass'], $params['mail']); - + $user_id = WebUsers::createWebuser($params['Login'], $params['Password'], $params['Email']); + //Create the user on the shard + in case shard is offline put copy of query in query db //returns: ok, shardoffline or liboffline $result = WebUsers::createUser($params, $user_id); From c4ff97cefd48b36fe3d655346e0ee4353885e0cc Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 2 Jun 2014 01:05:37 +0530 Subject: [PATCH 036/282] template for plugins in AMS --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 262 ++++++++++++++++++ .../ryzom_ams/ams_lib/translations/en.ini | 10 + .../server/ryzom_ams/www/html/inc/plugins.php | 45 +++ .../ryzom_ams/www/html/installer/libsetup.php | 15 + .../ryzom_ams/www/html/templates/plugins.tpl | 89 ++++++ 5 files changed, 421 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php new file mode 100644 index 000000000..df3af960c --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -0,0 +1,262 @@ + +setId($values['PluginId']); + + $this->setPluginName($values['PluginName']); + + $this->setPluginVersion($values['PluginVersion']); + + $this->setPluginPermission($values['PluginPermission']); + + $this->setIsActive($values['IsActive']); + + } + + + + + + /** + + * loads the object's attributes. + + */ + + public function load_With_SID( ) { + + $dbl = new DBLayer("lib"); + + $statement = $dbl->executeWithoutParams("SELECT * FROM plugins"); + + $row = $statement->fetch(); + + $this->set($row); + + } + + + + + + /** + + * updates the entry. + + */ + + public function update(){ + + $dbl = new DBLayer("lib"); + + $query = "UPDATE plugins SET PluginPermission= :t, PluginVersion = :q, IsActive = :d WHERE PluginName=:p_n"; + + $values = Array('p_n' => $this->getPluginName(), 't' => $this->getPluginPermission(), 'q' => $this->getPluginVersion(), 'd' => $this->getIsActive()); + + $statement = $dbl->execute($query, $values); + + } + + + + + + public function getId(){ + + return $this->Id; + + } + + + + /** + + * get plugin permission attribute of the object. + + */ + + public function getPluginPermission(){ + + return $this->plugin_permission; + + } + + + + /** + + * get plugin version attribute of the object. + + */ + + public function getPluginVersion(){ + + return $this->plugin_version; + + } + + + + /** + + * get plugin is active attribute of the object. + + */ + + public function getIsActive(){ + + return $this->plugin_isactive; + + } + + + + /** + + * get plugin name attribute of the object. + + */ + + public function getPluginName(){ + + return $this->plugin_name; + + } + + + + + + + + /** + + * set plugin id attribute of the object. + + * @param $s integer id + + */ + + public function setId($s){ + + $this->Id = $s; + + } + + + + /** + + * set plugin permission attribute of the object. + + * @param $t type of the query, set permission + + */ + + public function setPluginPermission($t){ + + + + $this->plugin_permission = $t; + + } + + + + /** + + * set plugin version attribute of the object. + + * @param $q string to set plugin version + + */ + + public function setPluginVersion($q){ + + $this->plugin_version= $q; + + } + + + + /** + + * set plugin is active attribute of the object. + + * @param $d tinyint to set plugin is active or not . + + */ + + public function setIsActive($d){ + + $this->plugin_isactive= $d; + + } + + + + /** + + * set plugin name attribute of the object. + + * @param $p_n string to set plugin name. + + */ + + public function setPluginName($p_n){ + + $this->plugin_name= $p_n; + + } + + + +} + + diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini index 586d49241..0d1b9cfb6 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini @@ -53,6 +53,16 @@ name = "Name" email = "Email" action = "Action" +[plugins] +plugin_title = "Plugin List" +plugin_info = "Here you can see the entire list of plugins . You can easily remove plugins ,activate them and add permissions" +plugins= "Plugins" +plugin_id = "ID" +plugin_name = "Name" +plugin_version= "Version" +plugin_permission= "Owner/Access Permission" +plugin_is_active= "On/Off" + [show_ticket] t_title = "Ticket" title = "Title" diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php b/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php new file mode 100644 index 000000000..61bdb0278 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php @@ -0,0 +1,45 @@ +init(); + print_r(plugin::$plugins);**/ + + $pagination = new Pagination("SELECT * FROM plugins","lib",5,"Plugincache"); + $pageResult['plug']= Gui_Elements::make_table($pagination->getElements() , Array ("getId","getPluginName","getPluginVersion","getPluginPermission","getIsActive"), Array("id","plugin_name","plugin_version","plugin_permission","plugin_isactive")); + $pageResult['links'] = $pagination->getLinks(5); + $pageResult['lastPage'] = $pagination->getLast(); + $pageResult['currentPage'] = $pagination->getCurrent(); + + global $INGAME_WEBPATH; + $pageResult['ingame_webpath'] = $INGAME_WEBPATH; + + //check if shard is online + try{ + $dbs = new DBLayer("shard"); + $pageResult['shard'] = "online"; + }catch(PDOException $e){ + $pageResult['shard'] = "offline"; + } + return( $pageResult); + }else{ + //ERROR: No access! + $_SESSION['error_code'] = "403"; + header("Location: index.php?page=error"); + exit; + } + +} + + diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index 932d6d2db..5aea5c200 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -154,6 +154,21 @@ ENGINE = InnoDB; + -- ----------------------------------------------------- + -- Table `" . $cfg['db']['lib']['name'] ."`.`plugins` + -- ----------------------------------------------------- + DROP TABLE IF EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ; + + CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ( + `PluginId` INT(10) NOT NULL AUTO_INCREMENT, + `PluginName` VARCHAR(11) NOT NULL, + `PluginPermission` VARCHAR(5) NOT NULL, + `PluginVersion` INT(11) NOT NULL, + `IsActive` TINYINT(1) NOT NULL, + PRIMARY KEY (`PluginId`) ) + ENGINE = InnoDB; + + -- ----------------------------------------------------- -- Table `" . $cfg['db']['lib']['name'] ."`.`ticket` -- ----------------------------------------------------- diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl new file mode 100644 index 000000000..4d4703875 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl @@ -0,0 +1,89 @@ + +{block name=content} +

+
+ +
+

{$plugin_info}

+ + + + + + + + + + + + + {foreach from=$plug item=element} + + + + + + + + {/foreach} + + +
{$plugin_id}{$plugin_permission}{$plugin_name}{$plugin_version}{$plugin_is_active}
{$element.id}{$element.plugin_permission}{$element.plugin_name}{$element.plugin_version}{$element.plugin_isactive}
+
+
    +
  • «
  • + {foreach from=$links item=link} +
  • {$link}
  • + {/foreach} +
  • »
  • +
+
+
+ +
+
+
+

Actions

+
+ + +
+
+
+
+
+ + +
+
+
+
+ +
+{/block} \ No newline at end of file From bf47b07fe000a3e1ce1a58b432f3db3e7a7f69ff Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Sun, 1 Jun 2014 19:52:54 +0000 Subject: [PATCH 037/282] changes indentation and extra spaces --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 157 +----------------- 1 file changed, 9 insertions(+), 148 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index df3af960c..2d9e5de06 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -1,262 +1,123 @@ - -setId($values['PluginId']); - $this->setPluginName($values['PluginName']); - $this->setPluginVersion($values['PluginVersion']); - $this->setPluginPermission($values['PluginPermission']); - - $this->setIsActive($values['IsActive']); - + $this->setIsActive($values['IsActive']); } - - - - /** - * loads the object's attributes. - */ - public function load_With_SID( ) { - $dbl = new DBLayer("lib"); - $statement = $dbl->executeWithoutParams("SELECT * FROM plugins"); - $row = $statement->fetch(); - $this->set($row); - } - - - - /** - * updates the entry. - */ - public function update(){ - $dbl = new DBLayer("lib"); - - $query = "UPDATE plugins SET PluginPermission= :t, PluginVersion = :q, IsActive = :d WHERE PluginName=:p_n"; - - $values = Array('p_n' => $this->getPluginName(), 't' => $this->getPluginPermission(), 'q' => $this->getPluginVersion(), 'd' => $this->getIsActive()); - - $statement = $dbl->execute($query, $values); - + $values = Array('t' => $this->getPluginPermission(), 'q' => $this->getPluginVersion(), 'd' => $this->getIsActive()); + $dbl->update("plugins", $values, "PluginName= $this->getPluginName()"); } - - - - public function getId(){ - return $this->Id; - } - - /** - * get plugin permission attribute of the object. - */ - public function getPluginPermission(){ - - return $this->plugin_permission; - + return $this->plugin_permission; } - - /** - * get plugin version attribute of the object. - */ - public function getPluginVersion(){ - return $this->plugin_version; - } - - /** - * get plugin is active attribute of the object. - */ - public function getIsActive(){ - return $this->plugin_isactive; - } - - /** - * get plugin name attribute of the object. - */ - public function getPluginName(){ - return $this->plugin_name; - } - - - - - - /** - * set plugin id attribute of the object. - * @param $s integer id - */ public function setId($s){ - $this->Id = $s; - } - - /** - * set plugin permission attribute of the object. - * @param $t type of the query, set permission - */ - public function setPluginPermission($t){ - - - $this->plugin_permission = $t; - } - - /** - * set plugin version attribute of the object. - * @param $q string to set plugin version - */ - public function setPluginVersion($q){ - $this->plugin_version= $q; - } - - /** - * set plugin is active attribute of the object. - * @param $d tinyint to set plugin is active or not . - */ - public function setIsActive($d){ - $this->plugin_isactive= $d; - } - - - + /** - * set plugin name attribute of the object. - * @param $p_n string to set plugin name. - */ - public function setPluginName($p_n){ - $this->plugin_name= $p_n; - } - - - -} - - +} \ No newline at end of file From c15eebaadfb41e6a87755508d0d5b619993687b4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 4 Jun 2014 22:09:11 +0200 Subject: [PATCH 038/282] First iteration of the new splash screen. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 3 +- code/studio/src/main.cpp | 10 +++- code/studio/src/splash_screen.cpp | 85 +++++++++++++++++++++++++++++++ code/studio/src/splash_screen.h | 42 +++++++++++++++ 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/splash_screen.cpp create mode 100644 code/studio/src/splash_screen.h diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index e41bd4778..216acdac2 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -11,7 +11,8 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h - settings_dialog.h ) + settings_dialog.h + splash_screen.h ) SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index 1f316f677..8cb056037 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -37,11 +37,12 @@ #include #include #include -#include +//#include #include #include #include "settings_dialog.h" +#include "splash_screen.h" #ifdef HAVE_OVQT_CONFIG_H #include "ovqt_config.h" @@ -141,8 +142,11 @@ int main(int argc, char **argv) QApplication app(argc, argv); #endif // NL_OS_WINDOWS - QSplashScreen *splash = new QSplashScreen(); + SplashScreen *splash = new SplashScreen(); splash->setPixmap(QPixmap(":/images/studio_splash.png")); + splash->setProgressBarEnabled( true ); + splash->setText( "Starting up..." ); + splash->setProgress( 0 ); splash->show(); QSettings::setDefaultFormat(QSettings::IniFormat); @@ -184,6 +188,8 @@ int main(int argc, char **argv) #endif pluginManager.setPluginPaths(pluginPaths); + splash->setText( "Loading plugins..." ); + splash->setProgress( 20 ); pluginManager.loadPlugins(); splash->hide(); diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp new file mode 100644 index 000000000..bddfd1dc2 --- /dev/null +++ b/code/studio/src/splash_screen.cpp @@ -0,0 +1,85 @@ +#include "splash_screen.h" +#include +#include +#include +#include + +SplashScreen::SplashScreen() : +QSplashScreen() +{ + progress = 0; + textX = 5; + textY = 20; + pbLeft = 0; + pbTop = 0; + pbWidth = 100; + pbHeight = 20; +} + +SplashScreen::~SplashScreen() +{ +} + +void SplashScreen::setPixmap( const QPixmap &pixmap ) +{ + QSplashScreen::setPixmap( pixmap ); + + if( this->pixmap().width() > 0 ) + pbWidth = this->pixmap().width(); + + if( this->pixmap().height() > 0 ) + pbTop = this->pixmap().height() - pbHeight; + + textY = pbTop - pbHeight; +} + +void SplashScreen::setText( const QString &text ) +{ + this->text = text; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::clearText() +{ + setText( "" ); +} + +void SplashScreen::setProgress( int percent ) +{ + progress = percent; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::drawContents( QPainter *painter ) +{ + QSplashScreen::drawContents( painter ); + + if( progressBarEnabled ) + { + QStyleOptionProgressBarV2 pbStyle; + pbStyle.initFrom( this ); + pbStyle.state = QStyle::State_Enabled; + pbStyle.textVisible = false; + pbStyle.minimum = 0; + pbStyle.maximum = 100; + pbStyle.progress = progress; + pbStyle.invertedAppearance = false; + pbStyle.rect = QRect( 0, pbTop, pbWidth, pbHeight ); + + style()->drawControl( QStyle::CE_ProgressBar, &pbStyle, painter, this ); + } + + if( !text.isEmpty() ) + { + QPen oldPen = painter->pen(); + QPen pen; + pen.setColor( Qt::white ); + painter->setPen( pen ); + painter->drawText( textX, textY, text ); + painter->setPen( oldPen ); + } +} + + diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h new file mode 100644 index 000000000..5d1889da5 --- /dev/null +++ b/code/studio/src/splash_screen.h @@ -0,0 +1,42 @@ +#ifndef SPLASH_SCREEN_H +#define SPLASH_SCREEN_H + + +#include + +class SplashScreen : public QSplashScreen +{ + Q_OBJECT +public: + SplashScreen(); + ~SplashScreen(); + + void setPixmap( const QPixmap &pixmap ); + + void setText( const QString &text ); + void clearText(); + void setTextXY( int x, int y ){ textX = x; textY = y; } + void setProgress( int percent ); + + void setProgressBarEnabled( bool b ){ progressBarEnabled = b; } + void setProgressBarRect( int left, int top, int width, int height ){} + +protected: + void drawContents( QPainter *painter ); + +private: + int progress; + int pbLeft; + int pbTop; + int pbWidth; + int pbHeight; + + QString text; + int textX; + int textY; + + bool progressBarEnabled; +}; + +#endif + From cfa12b6d81c23a559144f56062108a8ffa461932 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 4 Jun 2014 22:30:32 +0200 Subject: [PATCH 039/282] Somehow I always forget the banners... --HG-- branch : gsoc2014-dfighter --- code/studio/src/splash_screen.cpp | 17 +++++++++++++++++ code/studio/src/splash_screen.h | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index bddfd1dc2..303459ff0 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -1,3 +1,20 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "splash_screen.h" #include #include diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h index 5d1889da5..3fa2458cb 100644 --- a/code/studio/src/splash_screen.h +++ b/code/studio/src/splash_screen.h @@ -1,3 +1,20 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef SPLASH_SCREEN_H #define SPLASH_SCREEN_H From 91463f9fa244c26cf24862b100a8ea2e41365b46 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 5 Jun 2014 01:57:13 +0200 Subject: [PATCH 040/282] The splash screen will now inform the user about what's happening. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 3 +- .../src/extension_system/iplugin_manager.h | 4 ++ .../src/extension_system/plugin_manager.cpp | 3 + code/studio/src/main.cpp | 14 ++++- code/studio/src/pm_watcher.cpp | 61 ++++++++++++++++++ code/studio/src/pm_watcher.h | 63 +++++++++++++++++++ 6 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/pm_watcher.cpp create mode 100644 code/studio/src/pm_watcher.h diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 216acdac2..9bc071bf2 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -12,7 +12,8 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h settings_dialog.h - splash_screen.h ) + splash_screen.h + pm_watcher.h ) SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index e38748e77..1c8eea5d4 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -133,6 +133,10 @@ Q_SIGNALS: /// Signal that the list of available plugins has changed. void pluginsChanged(); + + void pluginLoading( const char *plugin ); + void pluginInitializing( const char *plugin ); + void pluginStarting( const char *plugin ); }; }; // namespace ExtensionSystem diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index a976583fb..4dcb40d31 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -218,6 +218,7 @@ void PluginManager::setPluginState(PluginSpec *spec, int destState) spec->resolveDependencies(m_pluginSpecs); return; case State::Running: + Q_EMIT pluginStarting( spec->name().toUtf8().data() ); spec->initializeExtensions(); return; case State::Deleted: @@ -239,9 +240,11 @@ void PluginManager::setPluginState(PluginSpec *spec, int destState) switch (destState) { case State::Loaded: + Q_EMIT pluginLoading( spec->name().toUtf8().data() ); spec->loadLibrary(); return; case State::Initialized: + Q_EMIT pluginInitializing( spec->name().toUtf8().data() ); spec->initializePlugin(); break; case State::Stopped: diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index 8cb056037..e758037c0 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -43,6 +43,7 @@ #include "settings_dialog.h" #include "splash_screen.h" +#include "pm_watcher.h" #ifdef HAVE_OVQT_CONFIG_H #include "ovqt_config.h" @@ -107,6 +108,7 @@ static inline QString msgCoreLoadFailure(const QString &why) return QCoreApplication::translate("Application", "Failed to load Core plugin: %1").arg(why); } + #ifdef NL_OS_WINDOWS int __stdcall WinMain(void *hInstance, void *hPrevInstance, void *lpCmdLine, int nShowCmd) #else // NL_OS_WINDOWS @@ -173,6 +175,9 @@ int main(int argc, char **argv) app.installTranslator(&translator); app.installTranslator(&qtTranslator); + splash->setText( "Loading plugins..." ); + splash->setProgress( 20 ); + #if defined(NL_OS_MAC) QDir::setCurrent(qApp->applicationDirPath() + QString("/../Resources")); NLMISC::CLibrary::addLibPath((qApp->applicationDirPath() + QString("/../PlugIns/nel")).toUtf8().constData()); @@ -188,10 +193,15 @@ int main(int argc, char **argv) #endif pluginManager.setPluginPaths(pluginPaths); - splash->setText( "Loading plugins..." ); - splash->setProgress( 20 ); + + PluginManagerWatcher watcher; + watcher.setPluginManager( &pluginManager ); + watcher.setSplashScreen( splash ); + watcher.connect(); + pluginManager.loadPlugins(); + watcher.disconnect(); splash->hide(); ExtensionSystem::IPluginSpec *corePlugin = pluginManager.pluginByName("Core"); diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp new file mode 100644 index 000000000..350fd886a --- /dev/null +++ b/code/studio/src/pm_watcher.cpp @@ -0,0 +1,61 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "pm_watcher.h" +#include "extension_system\iplugin_manager.h" +#include "splash_screen.h" + +void PluginManagerWatcher::connect() +{ + QObject::connect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::disconnect() +{ + QObject::disconnect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::onPluginLoading( const char *plugin ) +{ + QString s = "Loading plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginInitializing( const char *plugin ) +{ + QString s = "Initializing plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginStarting( const char *plugin ) +{ + QString s = "Starting plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + + + diff --git a/code/studio/src/pm_watcher.h b/code/studio/src/pm_watcher.h new file mode 100644 index 000000000..fe2755783 --- /dev/null +++ b/code/studio/src/pm_watcher.h @@ -0,0 +1,63 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PM_WATCHER_H +#define PM_WATCHER_H + +#include + +namespace ExtensionSystem +{ + class IPluginManager; +} + +class SplashScreen; +class PluginManager; + +class PluginManagerWatcher : public QObject +{ + Q_OBJECT +public: + PluginManagerWatcher(){ + sp = NULL; + pm = NULL; + } + + ~PluginManagerWatcher(){ + sp = NULL; + pm = NULL; + } + + void setSplashScreen( SplashScreen *s ){ sp = s; } + void setPluginManager( ExtensionSystem::IPluginManager *m ){ pm = m; } + + void connect(); + void disconnect(); + +private Q_SLOTS: + void onPluginLoading( const char *plugin ); + void onPluginInitializing( const char *plugin ); + void onPluginStarting( const char *plugin ); + +private: + SplashScreen *sp; + ExtensionSystem::IPluginManager *pm; +}; + + +#endif + From 2ce11cc2f9e54faba63839ffc562e1e5e9108901 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 16:41:39 +0200 Subject: [PATCH 041/282] Line endings... --HG-- branch : gsoc2014-dfighter --- code/studio/src/pm_watcher.cpp | 114 ++++++++++++++++----------------- code/studio/src/pm_watcher.h | 70 ++++++++++---------- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp index 350fd886a..1a029a1a3 100644 --- a/code/studio/src/pm_watcher.cpp +++ b/code/studio/src/pm_watcher.cpp @@ -1,61 +1,61 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "pm_watcher.h" -#include "extension_system\iplugin_manager.h" -#include "splash_screen.h" - -void PluginManagerWatcher::connect() +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "pm_watcher.h" +#include "extension_system\iplugin_manager.h" +#include "splash_screen.h" + +void PluginManagerWatcher::connect() { QObject::connect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); - QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); - QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); -} - -void PluginManagerWatcher::disconnect() + QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::disconnect() { QObject::disconnect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); - QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); - QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); -} - -void PluginManagerWatcher::onPluginLoading( const char *plugin ) -{ - QString s = "Loading plugin "; - s += plugin; - s += "..."; - sp->setText( s ); -} - -void PluginManagerWatcher::onPluginInitializing( const char *plugin ) -{ - QString s = "Initializing plugin "; - s += plugin; - s += "..."; - sp->setText( s ); -} - -void PluginManagerWatcher::onPluginStarting( const char *plugin ) -{ - QString s = "Starting plugin "; - s += plugin; - s += "..."; - sp->setText( s ); -} - - - + QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::onPluginLoading( const char *plugin ) +{ + QString s = "Loading plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginInitializing( const char *plugin ) +{ + QString s = "Initializing plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginStarting( const char *plugin ) +{ + QString s = "Starting plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + + + diff --git a/code/studio/src/pm_watcher.h b/code/studio/src/pm_watcher.h index fe2755783..a36bae57b 100644 --- a/code/studio/src/pm_watcher.h +++ b/code/studio/src/pm_watcher.h @@ -1,33 +1,33 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef PM_WATCHER_H -#define PM_WATCHER_H - -#include - -namespace ExtensionSystem -{ - class IPluginManager; -} - -class SplashScreen; -class PluginManager; - +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PM_WATCHER_H +#define PM_WATCHER_H + +#include + +namespace ExtensionSystem +{ + class IPluginManager; +} + +class SplashScreen; +class PluginManager; + class PluginManagerWatcher : public QObject { Q_OBJECT @@ -56,8 +56,8 @@ private Q_SLOTS: private: SplashScreen *sp; ExtensionSystem::IPluginManager *pm; -}; - - -#endif - +}; + + +#endif + From f177a49a9e381939c7c33f3902dc891435903095 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 16:56:10 +0200 Subject: [PATCH 042/282] Instead of drawing the progressbar on the splash image, draw it below it. Also move the status text closer to the progress bar. --HG-- branch : gsoc2014-dfighter --- code/studio/src/splash_screen.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 303459ff0..984c8d62c 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -45,9 +45,11 @@ void SplashScreen::setPixmap( const QPixmap &pixmap ) pbWidth = this->pixmap().width(); if( this->pixmap().height() > 0 ) - pbTop = this->pixmap().height() - pbHeight; + pbTop = this->pixmap().height(); - textY = pbTop - pbHeight; + textY = pbTop - pbHeight / 2; + + resize( pbWidth, pbTop + pbHeight ); } void SplashScreen::setText( const QString &text ) From f0a312a6e5653dfb9206998e32273ba8a4f193e2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 17:23:06 +0200 Subject: [PATCH 043/282] Progress bar will now actually show progress. --HG-- branch : gsoc2014-dfighter --- .../src/extension_system/iplugin_manager.h | 6 +++ .../src/extension_system/plugin_manager.cpp | 7 ++++ code/studio/src/pm_watcher.cpp | 42 +++++++++++++++++++ code/studio/src/pm_watcher.h | 9 ++++ code/studio/src/splash_screen.cpp | 7 ++++ code/studio/src/splash_screen.h | 1 + 6 files changed, 72 insertions(+) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index 1c8eea5d4..15fa4a336 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -134,9 +134,15 @@ Q_SIGNALS: /// Signal that the list of available plugins has changed. void pluginsChanged(); + void pluginCount( int count ); + void pluginLoading( const char *plugin ); void pluginInitializing( const char *plugin ); void pluginStarting( const char *plugin ); + + void pluginsLoaded(); + void pluginsInitialized(); + void pluginsStarted(); }; }; // namespace ExtensionSystem diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 4dcb40d31..265268896 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -92,17 +92,24 @@ void PluginManager::loadPlugins() setPluginState(spec, State::Resolved); QList queue = loadQueue(); + Q_EMIT pluginCount( queue.count() ); Q_FOREACH (PluginSpec *spec, queue) setPluginState(spec, State::Loaded); + + Q_EMIT pluginsLoaded(); Q_FOREACH (PluginSpec *spec, queue) setPluginState(spec, State::Initialized); + + Q_EMIT pluginsInitialized(); QListIterator it(queue); it.toBack(); while (it.hasPrevious()) setPluginState(it.previous(), State::Running); + + Q_EMIT pluginsStarted(); Q_EMIT pluginsChanged(); } diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp index 1a029a1a3..85c6d267b 100644 --- a/code/studio/src/pm_watcher.cpp +++ b/code/studio/src/pm_watcher.cpp @@ -19,11 +19,25 @@ #include "extension_system\iplugin_manager.h" #include "splash_screen.h" +namespace +{ + enum Progress + { + PLUGINS_LOADED = 10, + PLUGINS_INITIALIZED = 90, + PLUGINS_STARTED = 100 + }; +} + void PluginManagerWatcher::connect() { QObject::connect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginsLoaded() ), this, SLOT( onPluginsLoaded() ) ); + QObject::connect( pm, SIGNAL( pluginsInitialized() ), this, SLOT( onPluginsInitialized() ) ); + QObject::connect( pm, SIGNAL( pluginsStarted() ), this, SLOT( onPluginsStarted() ) ); + QObject::connect( pm, SIGNAL( pluginCount( int ) ), this, SLOT( onPluginCount( int ) ) ); } void PluginManagerWatcher::disconnect() @@ -31,6 +45,10 @@ void PluginManagerWatcher::disconnect() QObject::disconnect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginsLoaded() ), this, SLOT( onPluginsLoaded() ) ); + QObject::disconnect( pm, SIGNAL( pluginsInitialized() ), this, SLOT( onPluginsInitialized() ) ); + QObject::disconnect( pm, SIGNAL( pluginsStarted() ), this, SLOT( onPluginsStarted() ) ); + QObject::disconnect( pm, SIGNAL( pluginCount( int ) ), this, SLOT( onPluginCount( int ) ) ); } void PluginManagerWatcher::onPluginLoading( const char *plugin ) @@ -39,6 +57,8 @@ void PluginManagerWatcher::onPluginLoading( const char *plugin ) s += plugin; s += "..."; sp->setText( s ); + + sp->advanceProgress( PLUGINS_LOADED / pluginCount ); } void PluginManagerWatcher::onPluginInitializing( const char *plugin ) @@ -47,6 +67,8 @@ void PluginManagerWatcher::onPluginInitializing( const char *plugin ) s += plugin; s += "..."; sp->setText( s ); + + sp->advanceProgress( ( PLUGINS_INITIALIZED - PLUGINS_LOADED ) / pluginCount ); } void PluginManagerWatcher::onPluginStarting( const char *plugin ) @@ -55,7 +77,27 @@ void PluginManagerWatcher::onPluginStarting( const char *plugin ) s += plugin; s += "..."; sp->setText( s ); + + sp->advanceProgress( ( PLUGINS_STARTED - PLUGINS_INITIALIZED ) / pluginCount ); } +void PluginManagerWatcher::onPluginsLoaded() +{ + sp->setProgress( PLUGINS_LOADED ); +} +void PluginManagerWatcher::onPluginsInitialized() +{ + sp->setProgress( PLUGINS_INITIALIZED ); +} + +void PluginManagerWatcher::onPluginsStarted() +{ + sp->setProgress( PLUGINS_STARTED ); +} + +void PluginManagerWatcher::onPluginCount( int count ) +{ + pluginCount = count; +} \ No newline at end of file diff --git a/code/studio/src/pm_watcher.h b/code/studio/src/pm_watcher.h index a36bae57b..e37e81401 100644 --- a/code/studio/src/pm_watcher.h +++ b/code/studio/src/pm_watcher.h @@ -32,9 +32,11 @@ class PluginManagerWatcher : public QObject { Q_OBJECT public: + PluginManagerWatcher(){ sp = NULL; pm = NULL; + pluginCount = 0; } ~PluginManagerWatcher(){ @@ -53,9 +55,16 @@ private Q_SLOTS: void onPluginInitializing( const char *plugin ); void onPluginStarting( const char *plugin ); + void onPluginsLoaded(); + void onPluginsInitialized(); + void onPluginsStarted(); + + void onPluginCount( int count ); + private: SplashScreen *sp; ExtensionSystem::IPluginManager *pm; + int pluginCount; }; diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 984c8d62c..2bd67c11c 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -71,6 +71,13 @@ void SplashScreen::setProgress( int percent ) QCoreApplication::instance()->processEvents(); } +void SplashScreen::advanceProgress( int percent ) +{ + progress += percent; + repaint(); + QCoreApplication::instance()->processEvents(); +} + void SplashScreen::drawContents( QPainter *painter ) { QSplashScreen::drawContents( painter ); diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h index 3fa2458cb..ec6cd3da8 100644 --- a/code/studio/src/splash_screen.h +++ b/code/studio/src/splash_screen.h @@ -34,6 +34,7 @@ public: void clearText(); void setTextXY( int x, int y ){ textX = x; textY = y; } void setProgress( int percent ); + void advanceProgress( int percent ); void setProgressBarEnabled( bool b ){ progressBarEnabled = b; } void setProgressBarRect( int left, int top, int width, int height ){} From c2a951fd6ceb34db9b07329d6deea38299a855b9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 18:10:43 +0200 Subject: [PATCH 044/282] Progressbar should look nicer on the splash screen now. --HG-- branch : gsoc2014-dfighter --- code/studio/src/images/studio_splash.png | Bin 137855 -> 154305 bytes code/studio/src/splash_screen.cpp | 10 ++++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/code/studio/src/images/studio_splash.png b/code/studio/src/images/studio_splash.png index 1ec9d823ff81a9644135871393fec9f49dab11ed..06f0504b9f7d5d426fddbf0b99541c2b48a1ffd0 100644 GIT binary patch literal 154305 zcmV)xK$E|TP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf5dZ)S5dnW>Uy%R+|D{PpK~#8N?A-~V zW!YI5`rTdKRn=A1^PDC_cLtI$DI!k<2_QolB^VGv#P?JNgAhOjo~VR?iu&|D2?~nu z`NZLgGav$rNJ0ppq6{YKbay(WGjzH;Jr6baTfeo>|J1s>_Br=V_tvfI`d6>s`>egz zx4vn8-?#S}?j>({!yBIMF5)6C;vz2MA}-=0oP5_w4CsEAM1@?|a`{k7PJ_@L>1!(@%E~Km71y^ch@t-F5Za(W6HvJ>$6PrklD4 zAAGQ$-+Jq<-80WT)9v5CzkBMbr@CXuj&;{ub4~Za0}qVq?Ad3Z?QXc?hVIEHpR8j8 z{WsrybN8VSeQ2hxjk*2y+q);8c%sfXPM_oDmtWo;K76=)l<&pvC1Ew?!W*3 zDP41}xZ;Z19)JAt?v`6_sWPJ(*~xS0(4p?yYp?Adee}^fhg|fwZ{NOp9o^?W?|I!j z-tms^(n~L`#x7Q@~&??SnIaiZmaf>{;WwB zyzr$V=#zZMj~}1(^uTZI*8)#KFB;#Yf9HJ6x?}60XAB=egFN`OF1g8To<3u&jc2mA zdfrWtO{}p$$abNjT9Q4pz1N6w&j}PgT~hwZ2aXpC?7da7$lUG5tg`+azxg|A5p?O~ zbqy-ZwpCzOom*SqcOj!_YI3$ZPM$bf6OE)V;7bG&-l{ejLPD1)C5j|63FC>90FO_S z=}zH;AN*i<`t<2(LX!Yki60-XZKpri@oP=Gz!!Ro zj{q&au+tFcn}^Su*n zj%z;$V)@!AI!e5{kkmz{Rr6f*F%Lcc*{IhSpfiSP0VJpon>!dmc&rIlNy5vt^1sQ7 z7e0!_{@1rPAixXa5`e@im`fh)unN#KS0N!`u#3V#Vv#r`ynL#0OA#c=(@U;<%}(s!t^ux-QB(K?<5)tO~9waWr8}JNg`~+ZjyuK#>NtOn_eC0dHIBlR(i) zl7wc-vmo(%nq*FWLUrtD<=ImP{L?3!Pxm zCty1P{G5y8Yd27K<>c%lRs!{vW}nnH`FGx8BFidRXx@VKqt8XK@6$j1)4$tY)_?w$ zw{8hS2_O=UpgYzCD#2&0fdDRG4x51B&S+Q|rD0xxHLh*urVwaRMJ;pMpcmvCpeb16 zyB)izvUVGi3!Wu)Nlj9bbR;$j7vD*QDJr8Y^K#eh4qAbr&v@6-a<0$YI`ry1^Sx#x zI!D|3`zP1hW=?Dt+qV66UeS3wXI7IetR;auCx1IXyz28BkCLKe3OsW0JJ&&9-qJA- zpW)X$wBxT_0zJvpb#x?NeBjAma97WN_FcNK(&R_3&EVird2_PwCIlf z^pCdn_yIoHnGRaC`lxTwl`Hd|u+`KqXuw@S}fko#n zOMf{2Gd}54y5Iio-`?zppzEgCz-GvY8i&v)z=Gg6M2dnj2&96M;z5FIAwVsw&@otB zfVR#oK9)fec7mvcC&?&?$e>>`Fb4m5a-%6;9E~#vj0s<^DW)VUv?T{gu7$A*68306 zbi4(H+~FgKD~C7jQlL_nI7zn&d1&kW~_zg*;Ju-}~Oz z7hIG6LZlwp%r~QaNEH(FC7b{auRRrc|yhkVm3 zPXg%OIQ;Ps#SOV7^M!pzpjrXg*o#55M$_-@GLjznLZTGC(h2PyDl& zqR@KQ<}<*4bT!W(jTws{iqIjfjeZNS+2=yX^hTEn&zRsMb_)}|Z(?Ok1RY zT7~}ie#>`mEr8ze1Al#T=?nyKLF`PNSyn#%x5757CI7_KwgvS#9j(6iOU$rI9!skqCvs|J`>v{NiXW4 zSx<2zkxAg_YIs9036?(UBg{fu0yZ8W3IVSrenm=(fF#1;jyvwCvXGT7ozoRvy#4KO zuXE9%4^ZS;7acMhN3Z(uHUwGLEr0->eB(`_gIC2Z`IF4I6k(NC(PQ~<*#gvF$1nQJ zB5RQeuk@#&U^{xkH(%jH`q(KpS=2v*>Ln9j3Fw30v1f{%JV|6jJg}j?k3ZLk>*^mu z-}x3Vb{d;{(ti;fM0Mpo{EVnDwla4M&Rr&soK*n*z(4-KCzpC4=B|1yxStCQgWl3X zv&?M^pk?Q8hn)-xg0&>*Yv3T*3+{rtL?W?B;KRhVXaOX7DH0^W&}DmfzLJTjEE24v zWP&FBNp>J<=5sdI%oB-43LtiIU1GGhf(|`4!cUSt=m!bZxI9^yRRDqC8A4yNWUa`g z87B!l_w6I&Uh#@o)Td#_rugAE*0vs=GM{X-bZh>m3LrkKpfHZS;epN}{0(mkmMws` z6jDoqEOc&7wmaqNNZ~y`6+Q4P{CYwqtUdKqU)+*YYeC+zCo+MeDn3C!{4NNs=+;pI z1fKknlRYnDanu;spIpRVMsfMQS_)-9u7XA9E;23!(DXylKlyV%Qv*obhIh^95=0_c z+A5GV1m7g^O<*^Ig5aJcr_hm1$s!p#ddeYz50NJu+u0FaNyu;hushv&OF!&0N@~cyucL;SGJ9VO^IWw`mKo9i)8DPHh` z7j!Rt;R|aYUVJzjjp37)-2&U=IsT9$5a`2odI;E2;jk0n1F<1{YWSl6YTwd4QF5JL z^(lPVQW26O70>h;{~;fHpwHLnTjL{b)5j*{J9e!9(M+`CLtf)$24Qcqhwt zpmVx27EgR6PnOs|v{THXtB)>xIGGOgZP&<+uH$x%y%d)8qOq6P^yY|9{dC9Hcu$L8 zJ8F2vBOi+oDuD5%XmUgsy&yipUe?1my`ayIX!0NQ%%z9;XuzKM#EYYKQo!NITspjn z3pgn}*Dy(Yd+DjrI=Oh+xf!1)K)d!WuyYN;P9T)*6btJpec41f4+5_{`FLwha5o!xNi3#Yz7&Pey%{=u9E%Wq6U$a1Go>UlP zzH@W8OMKM>w($cz(k;ET$s4Te8hvi(i~NFKC2C{&jL$ofm9E)$-xikE;=Burk{P&XT9M!u=p5z@*_|0=J`Pj z^YCFF|3ROBqaQw>3m_@4xzKNnpQ{iPV&ij;!o)g7*{t|B3*Yyx|NHKK4gOq1;1bN% zEr2!=404y9yG#W|lGzwi04YZDK~?-KFa&i4hGf?k666)YB@YRB7SQqd-`rtv$6xxb zA<57onvxT^E)kJIpTs4p<0t22H6I@e3*#j0ptXgyBsFX6k52SUOn?v9(Q<4N85D%p zm$-&{4Q=%Bl41v4dN!x!X&taNS%);8D`MsqCoRZj9KGV#=Vs9M8s7>@YXof1HgvCG zTm&g9R|U=AykY?q#D4sRe00QK&h1<0&zJW19OElDMbD1{B)yjF}kN=j%+ z8s;c`JnfK(>0eTsSCo+p4fJzYZ(RiqxP~X|S=%*zDQ3JSf-mxq6&S{vM?OyyBDZn$ zJFj4<=AR_#?LgK%U279G;LlpC794bo&-_FI8R*(mA|Q(*$olzK+jdyH04i&+-8uzO zi?$fDZ`j`+VrSP*pMJI!x*w>o_46rm^9SqGIh|~Rm%uvw#-2o%-s3~;e4(J%{KRJ# zbN7ol-%-Nkh49wcBJ)xJ&Hj$*3J{3)G6bnrmAXptBWMf8H{En|O}GN4q$OYq%t^e< zK(Z5nAx{+~I>|u-lXRCtNhD~DHHCtJ4_>z*Pl_LR+$qXZc<=?hl2;;9n0PHg<5vsK ztQSab^n;f56$;is13d+fqry(oGv4~HyVJ)9y&FRYwA!Yyvfi-h8}cy*S2J#2t7Auw zv#u}G0&**Q>6(7nBKD6?a(+G{^0E;-l1I@?=Dw(Zw)zHp@+)uCI){@d`louWzBU2t z@@ISa10VQ6<;RmKg`dA-kB1{i4%fmnp#AgD29tPqe!9*@tb%Ity<_lI_l$Xq&Rwej zl86NycS8bzw^H%}!o9ZP1wsi}Qe75RmIcL0(L)~+lDQ8&@Sz&K6)fxO1r2ME$B_*L zTlCYf5Yp%My6Xw}M~!X5w?v}&@!C4% zR=g;FoTqT{WGXy3w?03d^^_@z35^Q@iaiB^qvkCmI-p-r1S&SqXYh+W1&tplbp0-t zB9`y@wjz7mdy0}Lo;>qc?8PL0m*Qw$&}aOMKjP!wd+)7pP3ybmmRsvh0G{~bk+Lqo zvxnmA+FnIXf_s;}i`YppeSCEC?_6S?y|T#MrK$mijUbc+FX`x$>}-5*(Int%>oC6; zP|d#p{}Q#r;MQCFz$ZBihKiEBC9w_^65+#9AiwVV{u@sMv9~xNpAGUhhNHyc4mrVh z8Cb`B_RU?krwqQ`rQonO8!I|egs?r?`3IdCA2|0m-Q}0>uSJzRdNk2CUV_t%%N@UQ zWQ!h$wjh)F5tdu2JJ%`F9Z)QNa~TtNwY8{bHRxlDT6tY+C>c99ja0qDS((UxF`pKkl{!Cqc#& z7LW)9h&%;3A5oPxN8j|2LXeCUtneT=eYw6V&~ZM*nWE(QvE#My1h4Z1M1Xcw04O5z zc_+zGBAEv=ppSp!C6_!|K#OcwUEO~c$9m+&TjueByzRta=tW^@EFSrZw+F5(i3=1u zqTIE_T4OB&(>1t2;_Jk7CWuG=*N$uhg?Yjirm;svSBl{Bp2PkLIACnJlZ)z!HM z9i@dadygL2o=w^(5{iW+dgtb`pD}EFK7wueA3O2^A3j#lw1xg6;4f(S0W^gOx_SBn zuFJvd>{0$gM`-i0=rpm-zA$c+K+~G| ziM

cvIxzP2mQ3VS7G+A3h#?wm!26mKl2y7cmoDsI+tDPm{G*#g->P(oZ(wyk@fs z5J{4bngXG1u6YYhQdIz8)KjLHz3gSvV4kE4?HUlJwrx`=)V9#Hra*^J{3vuH8+q4( zgoF+qli3~SI>=MGF*%kIWZz+2A=OZM@RxbKiG`0OHMq&qGw;@`4r0Btu zpo|tDk+d8oU!Nptd|M>uG4(cWl-o zG}G7*1cuN>xo)qO~2<Z!y$I;%h+MO#24k6^V36c@v>3Cg(>9`fo5fiZNJLdg>&uV4AfS9TxuQ6E)h&mAP$ z@iglRf$I`N)^W^Rrq&UB&80U_CIHWpgxAJOAl7V=0M7^TW;_h#Sp?R{kK!lE|9k;? z$^MF$zoI@}RTSDAS`xD{(F=XDeG1F?60*KA43z#%3HIeG$cjYUO>Dyo`~tP4l_s!D zrV@dcgf9sTJZ%$n1os5^B;ql+<1*ej=Mt~=1dn`XVo~4)jh2`2k>a6Of5r@g#Y8yUTjy#uwi4J5=+ftJ6dQaz`!sgrd*TSa z@@IR`b^OiKhyBp*&t+hI8k<)>OH8H@jlX5D;Q>#%!7vuj7jY5i6vgF>2TxvX9`p9p z@Bh7@T5oWs1<-$b+gm1=X2a%oH?*msBM75q152ik*_bw|*KGqExa~7ep8&7n&xZFE zX$e4K;Ary;I0Av-07<|J5`xyE&3HwV0ES)y4qlS@yjBq8gT)F9JmNcdY>F2=GnV8h zz$S>Lp^eWra0#0F+GOcEdcJ;pO_5VVC2x|Sb@9^bPNN^e8y&?FJ{3CAlfnWGa)UY6 zm4L~Ie`DJ~Za%u?#sglnZtq9^AN2%s(^+(YHoG~};XIH#^y$iaL!@XR-*(M7$&CGc z02M-W-i8{(vIS7=$p=#S*%$ixu50weZ|K(%@QhA?9+~MH4=OyivL0Ua;fEbt4C$2UAbzkc%p11s zweX4;cEKCp@x+#I;vqbdXVZ4Oh>KVh{B|cWMmGh}^lyRvjeqdNlS|{UF(ewnxkZYO zb%3@+1_Ffyq;JT$-yG(4=4(fPd(*x7~}Nl zimdp+r=TM^;Zq-ddM!}3IDFV!9{n}rF2C&Z?)n@09}e^gTmU1F;3m+;E{Yf5Fd?Ia zPVVT@8pgch6|bltFm_!)WMgz3@g;zJYf!NEny%0bJc+_rg1NP=tBAo%k^)&JVsF6- z%$oJ^PbNSI5~MxR8S0{iHRus7=P3%}Pjo^K$sqQQp9~RwkDr-v5!GPgbF@AQTind!R)`8?s{E3PY+gIr^u zRbgE*BL20Ao)!UXp;RBCPfUm3=x?V%4#oVewJJ+Rc0R}V`7%40N7v@rFIs%rp5pr{ zs9xJ8FTCKHuUy1M>>7&8@5qy(hVEbbGk>oBEwJV- zu(#F?Fslh{f};)5_DfiO(%<^jV%dg{mc)vtP1=r;Oxv}GP4LOxi~xy-Vk&es2}Yu@ zsWVTa+XSqOp5kW~O@R&{lA=ilUO4G31pEbmj>ae~7D-I> zO+V~K{^^{ezSzJz=_hOWYe7ciTF_ZrOK+~R1>dm;_|6bRy)IJp z1ojO-wl?5b^BTWe_BmcOynDKpn1a9f%|%?qj-t5wP836*`N@N~z<%b@gSq(uK-lPAT2If7H>>3_Tgu@i+JU8I08j_u5)Cq)ff#?zgr z2T6RcwQoi0H{U#ZlgzDY3}3*%BE(!{HETu>=6EdupkuwPl|;c7>}{-h0x|y0H!npU z9hjGZELnK1Kx1z*8E1a{Wf{b`JZZz1^XNRU@q};oWg~s_K;Hca_E#GxVPuYD>|Xmy zi|xqOqP25iu6cCf8XZ_;=EI(va1n|zGlv4?BMI=BDw=U!HYeIp+5VH>`|W_Vl_*;{mO4^`jU%h*oIdl>Pd_>ox3$JxzS z+I{iBp5a^G@?{TuGjB)RE16@yx54cLjZg6d`(Y9AL-7f%?O>c(gAe{5KJcuG8~7H7 z@QWW$f_>q`xk3qV+E@%^((QN8MO?%LHAM25&HBvDZ-H4%rO$a46+0OuttGM9WD;5e zhC3liQ=cNprpnU+O@ZM0vUfx_<)U|U%K*Rb*2s|{lRNZTAZL;zzQ{%2GujeO{v>&{^NP z04`|aLtlLgRuU|FuIqP>2mSTw$fUrMz#Xlr&p0i?GyIZ)typIGLC$%(JfzNk5$1((6{f% zOmB3!j{bu1JEoIG(HDi27b9qGwbQT`nVuxmq;DPY3;w{T*?`UIojvn(#y&GfQ9(|7 zoZXGL&lB_Trk`)&(Q9@zmyfhS!*#Zw2Xy$EHSlO&*27EuH`n<$zO(1uoRG)sA%9xk z=f#)zU%tQc89(2GGH>bt<$%sbT*MT`9ZHs%yjUJ*y#>}5Kpd1Kb9S3@C!H^ANeni2 z1Z#P)8ErJ1%BHhn1U_R{fqCenxk-es0OK5=HoRcg!loxLxr`TJ$e!e*co8rp*aR`x zBwodmM2J2b^x#fSLKbMM4kth(pi4n3zj5T6vHIEq2ycR!btT6dxEfvI$qyAi~Y`4d_jE3{)$h~gE{;p`;VU) zZ?65p#`B71bMoZXx_p-Z@p1lbUF*4_3d9R^jj{KPOT6s#d_&Px=-_g=6ZW)?u4%*L|ecdPiBZp`Y?eet8u<5wHV z6A8gOEt|$h8QmD$z$TS&(N3b>BECE82=7GFlJc`p{-u{V8_v<+W?jja*&f>&=VcgdDe(utqW`5 zgAd{5>9X#+J3hRv5<9kg@)NYS+G$v89hrvU7wFLaD7`@!e@N^T1MI=vM8tOXiDD$h zvi|sseJ7sUpRUuJ{gc>d9{Ke1v&1eCZ|qO;61~JFuuh62^Q>dNV`Xh3v<>(?-sv&& z)Z(bTZksjng1&}Nu_*#PWuq-ZV><{+HZT4Jmih#x1Q&rvbG;TB zC1~JB&=3T?ukJ`T%{;Q<*BrDY+ypsrRJa&JUm(bkB>{nsyjL%HMK*K=QZQCm8_C;xT`Z_CnHwDEpwN{mB4158dVF9#E>|w7I5&XkG;fwJ% z{H7@4Z`KrN?Pu%S+kDj?bF<`n_FDEBU-h{peb#UT1$gG~=7>M8iy_uEZkCR$nVYV8 zjcokBZFJu@ypgeuC&MC%+;|cTHMApJ3;h=owmd;?U5c3VUI!C(6l?S+=Q~E^nfV0B zW{{LP&ZZoLjzg&pa_w3}B$>L-X(bO%ZZiZnip^l-qs7T>?jg)m^w{t=i=^!MP$@*7 zo@^*U!^XkS*xkgUKqm>`nm*`=Z#>YcKI=GUV>&k{^CTew(J^oRc#Sr>B~WuhgAT|p zAZF8(!F)l<+yq#<6dVK$=jM9fo}P`5J@803)=aPkfk)7@9z7a^j$^C0Bn@NDMGp^n z)9?k>B{%&D$bxI;;RhXa&50fYJh(1-CvdLnx8^NU00qY2FTAn^e*C&OS?Jdo{)cyV z(Uu?o2*@ap?HulHWX|aem=5KlxQ#3n0G)&6zn8 z=h}pkw-^tammJduszG1`DFP&8jYB(1ED~m$Xj2GrW-^%9R{HuR>h`Xi^E;1|qnC|i zvr5Fnf@>D&Dn%B)t?f=L0Z8z4Hzr6p$Def>Ae$}nWS%j2L{G8eocz}ET0;v>kDtv+ z5U>_HiW2&D9q{6sV1PbI%GMSzt!4Zo1(5ZvnIt5*pwrq#K-F(d)_m+SKXTazU~A$H z-{|G(lXd6?Epni*pI-6ry!9KOHQ)pIM1ww8@n3Ty&!Y2<)5t&;{z9kjw(&?7cg~CW z(K1Lv-W2Gce(@%-{!-+Fufo2bT>Z4CwMb8@KnWvlU%HCYZr-sOS^BTFy*|x+; zjl4c)Ar^^KZ6n{Xksr_aT3|@xH(57@vOrp}0WN$mGS|MGBzl*WeWhjKV1# zgV=?!7XDY9p*n=gZJWSa5?m7MqOke$^d=w3Yr(l)SG>4x^Fo|mALmZraDHG@CxJ<- z^PtGc+aK1}Y!GXuKaZZX`2+%E0?FH$1RP0Tv+3w48;o3d%aa5&t~l7s6Bug^Yb#L9 zr!PV8jyvwCbQFSUw0CyPU~I1^0K_)AIp8`Q~)6%-^^6|eY zFR+nW0f#3W*q^(|Z;phg)o{i?GxKs&h6n z-&k|-ZM;6g`nKmiuim|74Z&DZr;lyU1!}Mx)9W_-VlRRIce)5Fo>TuVq8Izc@5@L$ z*>~rn$XyjxQoNo+cC9ZSDr9og0pcOuf*A9zcfG5=9WGYfb=O_B-`*Ar&G%YDLU4XZ?oi4JZ;A@-sEXJfzN|ST!nYM}5VlRESjsK4I<%a!& z1GnJ*t*@NR&Cp<406qN3*?)&-)3DiW22U~81!qhll!Vt7G_HG+AgOXJcRt3MgAe1! zHtZN|2njfjnsw37(wa=`OV`f}p;&R&0bnSVpEzU~g>g)xkgLmo2?LKF?pqu${WAJ&ajE zQT#*Wzw9m9NG^Ed587Tt4e>?JsjTN1^d(8#d-Ug~LgAyJVP|iTv3d4No=|)3ZwZP+ ze&|$OLdV_`_mbef7Na6_nnEi#fqM;jd*aFQ!c33;u{IshK)j-}w#flw#ge!thtPK# z8{~#P&1bOKh;F^p;BPkI~b{l8@is>#ms6Zw$FS;2P8JDWurnIR! z4kwiq6+Sf?76;>q`EY8A0m;>zG3b|&@yyAx2FJAq#}rIL8_fg_u<1GUm<%?Hgl~O! zAquyAenpey(I!V`<7e7eXriI;u&yL9wvMskX}WP&0NR>>;VF;x@T@RlPdv{ndLVM5 zLly-JeF_MX39s~R9r{TTlq46Oy3X$ONB@eT`j%Lu13yqG&#98z0KXEvFd|um2Xt^oeoz3SO?9!uRp1#^f z*KMK1F8UNl^!wx!{U2l=HaCQ9OYio_ti~2>VsFiA;`BKIeU{ehd8+Fj#F+wUhe7d- z#qf*3hFQiK0wsqLEPb#|fx=nfVGH#eg{yyz>?Z%9w1LfWu2nja7Owx+AhD-Fhk~!;;`;0LFox}Plfs8zv#q_%KiE;ywNLB;ae-g*jlFeO(JH-k;(yb@9V|&6t=gi9&0G^l?dudr8avzXX^OJwa8}zi zLbFiskJg#kviz@qUC-;~U58vC*2-<{G_TPyy|)FF_MxW9E9_+KShMHs!Lj10ZOM-s zKgs!`jlGBOTFgRhu;~^w-vZnEr!Y1NLT4i^3W1I>I02)zOwWUH=5ZW>RHC#IwKx=d zlBvGjL0)zBRrROYIg`zcjzH_Warn{iI^%H`bc{i(ElvXcuA4&#cySb91aLvfIvh9S z(XKzaUjmCU<_Z?pmIwkxlO#^N@sd#i9O>e4?w5bE8=|*wJUY z#~G|;z}F|Jz!eY(qd@;hfkJSoPEF^7Hf+U9aS zG_=@^E%88)`iIaLdB(2KLfKNIK@#6E<{Rr`OyBE(?`iR&pw(aed^_EQw~S+>d0-cF z_yC>7M(hpzfWL%4J|ErMOZN0mf*eD?m}T=t;14B7ue$+yqo<=2+a?}HmViu`?dyMA zjgH%RvmMZCoBhY`VzIqTcWndojmuuOcg2L-4)?!H#_!Vj-gdr(&Z5}#9@;cE!5?j; zC05RB_FikJ+DeRe%umMHgZv5XT{j}JLl{TA3x z!RC{!CAww67&eZ(5KjYa$|!vv1WIe=X%K_z(*O<1q6C`-ZHZg(oqK|0J%Lvs zzz3rb!H}*29?=Ra&EjzAsG4nN@JLg^WAi65X45k!-i}NRDY0)vS@<|+5)p;CH8vaiT?2_9hR^*8F@D7l)Z*PpAIDtcO&>km)^|LeBR0D5R9V_ z$81EpU<*e)=?@*W$!t728SgHKZs^Du&3OL6m)HY8t?W<}+LAD*(pi4$d4=eY4fx4W zcfqiCs-F?qe*&PrVT>T^iNt;P-BOzEBm3WvI`)t?tI>O^_^E$Ls zZTkDm6?n2=?MX*5ec8sx+9y@(H2xy~$4}Dm&YxR9N(*+h01~(axp|LLw*%(AMMBwm zR4U<(fv}30wpekVLI@8MuB7Qag-8k?^aWk7C0k=`ItjCFf^!nPW?f15#V>ww_ktI^ zpl(bbU=!S}i?#;lSqF?m3taaW8+zuMPj&?pnemlkfMN0Hx=l|v`W6A1Vv7`6lA8Gv z99>Ixbg&3Xv=od9MV&hVjreM|w)*_Gf%nAB1S^mFdytD@3Wz&dlHU+xV=&6;xg?{?V z-XYg;tk<)6laTD)1R=Cq@G-t%zH9bU?BTU@W7y4+y{y*;v`t``80X2f3UU)Olz*p? z*vIdO_5!xtXz??FHN~6Zep(df%xmmKhi$V~+w4K|;YH))d`!a|-6U>g4`}+unV~Q2 z7Vt9`i}n(dU-l}0$#-}h;V+a_6}A@NK0)P;96Y1%Lf$pnKJoS9Oy<`i*nMm$_(KM`4f+ouD;rfUcmWpuj&`WX;BLolMrj zH-4;dY~-=Y^&4lNHB-o#j}Ce9ZhZRjkOGKJh6Rx8uF)f!d_nT_76*FZvrhOTKOGz6 z+<1JVtB;PIx{J0%KPxtQy)O6;zleTjA-Z#iZ7jR%t9qJTkKYVIw|eT*L=(k1G*4e z#<-@Ro$_QB&)Phm7sV`F&y#5t@agDrH(46M0M0W=HC>`8l% z+-<`T-SZ<)m4GjaJ#7;gHMUPPj^7W*lJAt_vFLM%Wo2g*u|pGMH>tZ#f^If#+f9Of z7cPMQ+uMJ$ZWPT#iOa-Q8pn5RX)xr_5!Y#)L!n?T#hL`#f>9(|2~J>jZZk-f8Yh-e zDagk68qnp?j*_Opz|iKS>93TVPbS5OfSk=^trRw%ewmX3$+@u#L4}&5zzy^y=qHH} z+brM&KTG5;z$SP zlOJDX;BT7i4?OT-y+$s)C*hexF8sJo$Ki)vZbz`XsqdL^lWK9 zzO7L!iv@%1EZ`9~T>xRr=fs}cP~r!EOXrKyqeHf11A1)1R@rMU;!o!C3+Ht1Ghk0W zd1gPg$Q=I1e%3VC9>S{_FkF8bERsyE6FxQpK8PmY+YMMR`?s|(y|Fu;v&o{iUli8d zL;WE#e4Y5~ImaKW&STw#~TQ+_#OKR~FyopKXiWbkR2b!~N01nD7^D+CJ-o zeCyhFCn2_MR{%{v10)Hj2}G+R#REs#4Jb5{;DFGQ?F~2fKMp17d$K|<0Y{Q%ur&R~ z1p*zza%u_GIY;%{Bm4&+?BB*R$LDlj_Oh4N&+BrUutEck_F#|8on-Js#M zLZvSjPgQyFZw%hqPyuHg8feltJ9|xLb0u)E>66VorN9?kd7Y*oKN;5snJG3La5suI z68`0`XF;3{H&+iLK z=*CIN0 z*80xzV0}%pNu!SRD6i#Tfu^_aL?w^YgIukzmSM0P-5d>p)U^70+H>{(eU)5ff>q+o`u7eId z`Efj##ZT`^lYgz zW&;HqWR1+(B+#U1y2A%OXLD-`Q^8fzQnbWYeIe9;K8TKI0q>EAe!R90TAnAq{IKL+w&Rxf!bNtN%dWsXeF_u2kj}G0T zowpuRSfuDUexm<7XaSCWM#Y%CU5L-fua9o|4F0T#Z*mNEX>He11nF0(dizj6ozWrw zjCG#Rv#<@B=*d_CpPuo92mCvd6HPjZ%$oq3z|NZnUE*`-FRNk}z1U$pup3>+4typ4 z5oC=a=sbG2UiQ^?@|nY))@jF;P})1;hJf~_`~q8k*&WSelc&Ku4ZffKYwyzWZWKS( z_htAuJHwXXRKM%`tprjm;E_x zHJ48E>e%&Vo7kNkvk9O{)-in6r+nJh4?(X}0JR^an}rl76uL;8rBq2%0!y;XI6?67 zl2mPW)pHCiQA)7hD&ZUet3Xu0DImZ#eVztLQVF`8$^5!8%DJ@;9=xI&9B+Ai>}@aL zDCh_-uHi{DUSWV%l6AhRMg}^w24{n;8D|C+J6dQ9TKK~!TKc`t21ZYx`TA{eI>0mj zW`RDIDS*fb^bgke)&6N1DeIFDkLZTa%)>t($(9XHKWv~`OA<5>F9Lz<&J{MsD4>#P z!xwv6mkf^R;7uc2OF!#@Yvw9eo%4rH;Cw28e7HaKN;q98NDo2pY(@9%Gc17k1Dn$^ zTb?ZKaPdugvM!rDHmasX z7i48`x*y8TAFRP1eDmt!BlI2rW@AU=7Lg0j(*kG*ftO9`2lxe=_S!r-v%i8>ZEgRG zi-}FE(iubL5T8g662861zMIn9CV@A0;Ct)nqm&D0$-N2SZzl_&bs-Mpk3ZRen`qk= zUCTE1&CQg(mN?^Do&Zfh1LWeO4N-4tNU}E7d*A!sT8!u$YbiD`vPi@15PVF~PZ9=w zHnwDz_b(}ufcW$lnYHmr84|E_36-*~1!#E7%Up@uQGiw$Dn^pbB}K<bd$x;)DGd}JTl2Lx@%GOK9M`^e3JXQ2KGtZ*V;T9Orw)TvS>SAl84PG zsR~}z5jKq0$+YWA5Ri@k+G~k>(Y(*ADqazx(J@2+! z=z5(s&|o_{b?&++PmZ1v(f?3p^w~r4gjRUHP*CkS3FJEy!21ud)1Sh3tO%OgwP~{u zUU!b)y$L?-MuXq-U;9@9&mZ%Ia~@n*TWndd+PA<8 z0h`fX#de8s5wuR0X5(5z@#3rP5|(7@n&c<}Di-jd5E%=g#!8IFqyV_%jyr0f;NsKn zdHUj96S%=w+kLajW3s$$B3YwhzV)>+v~p-5U}*{sJdjVz6EcOQKn3#>LQ8WN*yKbB zc#?bQNa|$3f1uD4P>nN3Q&8wLPU70KQdu_z!FD_Z#wk!wO$s_|Sr=_QIZBjtn_wUL zXX!wH?7@!K;1h}`uU$h+K^J*Xp6vhhhA}CI*n%zb)Ro)3u3bjBz1SvY>pXT`e2j(I@C7)L%o zYcGwV@{oTMe#-x5+F=&zygiB`Z>_AW%DZXoW&Ock=Wh`#T>ueU;*b=yWj0n2C)3Qg zQEhUGF@;F(8Wk>{+<1%1=C_$8rmX8Y#sk`D3c@LnlKlLZk6-`IU6h2GCrHLf*pV%? z6=3*-_UVNAkfT29YWahxia7m(n1t+!gbz?Fek5N|43JBL4XqaX#`=dqPop!k3#5^O zO!(GEe(T{O#T>co+lHmjTr%HOcuxQhW)%S~kB;WYwueiLzR^;=;7fv}|JJ69B2V-} z$2nR_6bc^eOCpzE+80eJ1o@RBDNmm0Od*WNR#vbMy`al}?c0m9u*Fgf*lnj!EON#! z*w|rKVt=656hYfPVQl%FHD(C=ur26!8jJF^D$wVD;-9^0Pv)s}o|Jle$#3TYofJQ4 zY`3qf?i>A2I{WqubxSx;StsQYNLu{23hqVYDCjV?J! zLXs+)DMSQKudOH0Su1Ub(9XHyNwFg6=IM^3brd*0Ln5FE4rIyQR*J45G+h%=@Z)Jv zyOyAiwxdEvVPQRMJ#+M#IwnP%WZ;MT@{~!xHPHwCo-}}YZ3~RgdJ?tqimWtx)KXB9 z5ntv28O)W;!5r)7dPP~!IE6xjZvt}?PRkQ`ou_GZub`k;deg6=gQmX+6+OnDi}=zI zWK^^{S`W|Yq)>J4DIuMOJ|0{r2Od%^NjUULPS@!L&6Y2PkiyAlD(H0hnWilm=x4W4 zyr#F&Iby@wu`j=;YktSqa;K-Mf}SRSm2zW@;~~V1$5ftXADK- z{l8ZC=g3cX3tQwpk8r;6d%j_*0!R|GNhPs%bGC?+X$KA*><*TKN3xMTHAzL{5D;y2 z3D&081T=I*TXCdcf*T@^A=wM8NlNJZ7LWt%y&(av|gL^1XoF% z+@1g!V;zN6BSUH(t=SP6`C{!+#P3+LE&)SSO8KDR2~yibxI3 z_AXJgu7)mIjM48XvE#*SI#qzt4I1c4PSHV|SaLUNtbXTofCiZWk9gCMXNa$upC>4@ z{AL*lW}qO!H-6|U~+G>X0*<16gN4*Db#aw#&S4|Ejdy>LELwJz8z#ZUWmM?e3}O@#eAYyZUVZSgZU z*0t&zd&oaF4e=rRNV|~by@<21sJRy|fNVqwR1lL?pmi__)+SakoGEtt-}5nE^3-f_ zGz3H&v~2-;HnN141g3#Cawn-Eu%1NZwYz;u(dL)T5(GlqT*Vk3^hspK=_8+WNAx_& zLErk4tn;iRK}H@l1SbhnfRaej#-qfEA5T0S$%7W!l0X{S^3+0t^_i#JZ@<0H#~Zou zra8B!B#tItW`UmR5fnrU5d{uC&;k17jV|a5eX>aGWF?2!?5mFs%*U_SiY2ep$YL$B zDl$`aLhP^#iU;)n_`$@x$&N2Nvj*Py6}==8fa@vBT=)9;vHt7YE$~N2^cG)2gZzp+ zwn~BQCl}~Y(M}gBl(Xh;f?mqP=Va|g(DG%E(A#y_^}hF9MRdYv_)ZFGag$%#OJ4Ik zW9_L~aNSt3!nu9yTLZ1$&n0%6i^PSr9bfP{j=kbnb1~s@J6;!xK!`}35`*L+>1Yy8 ziXEHS29!YBV#l4bWGHF0Z5FI0@fw3xl8-ecAZrK^DRLyLtYeOA_-xlfGf6$;S}0m1 zM(?lZ>4!OrA3vao|8^ZuH3aVzVUoNtXb42s!H2PEpl2-FuA5Jf(WTe=qgUtec*i@Y zZ|_(`;WXrXI~b2A>jN5h-+gy|?ej_Wi+1ZI0x#W?M?bwQCSqeWQ!6qZpH)t?f~IOo9GfgFVhy_>6tX&-jtJDNeY?hv_eIHcyJ% z{p7knbm+AfKlMU?*b^A>fpw6WkhYioe-)5#ucPYy0>Eeiw8gm!By^iDg^10jNgye9 zY+%i1Hg?#?(5@pOXcDu)X!BpoqeMWR_SZ0sJYz6is-6 z6kOy%*BXn06#o#LgWy5{RBYzBzSVu2YU;`^yoF-B9pmb%~gQU z8obN&8UXknA$k{_3HnO`MCbU>hYznEhdyB)K1H5IKxau%c`C#f?3)5n5$HPq&)=2X z2~^$eQP9hxU=Mr89Qs?;Z_Y=M-Jj@5@!ZBtu%C=^U92#MuK1MLB2L7g`JuS?VA+e) z;^zVbpXVoOo7w`)`0K7>?{4u64%3VpXRrx9ArROl{TIFH_L}r;t`s@hknXm#aoaYA z)`2rdvb9c%kUZ}7)$?|plc%=-O&rN6Ph24K067#PnsEY#^^CVhnxrm~2|9|CJVnrt z4>0!?uXsh3T>?cLO|m#Q)`zSGF)~;K&x#K8jMa>@rsOJ^IeLPEzJTbc5JD3#bQ0MX z!bE<_-}(ZjH9>*kEB>{>dhnsDD{r}3hmP<=9sw7xXeffr^YZ{?GM7wbgjsf38rWVU z0N`Cxz^mefuR7vK@fkmG9(w|P(~0qm06i^Fg*?Gv4?583iLLNLH}sVo2Wb6qS(IH< z=T{o5lbMO|wk(e=U(3!7#1;NVcgqy`EmmFoT!C+hGg=TG@)x?`UwpJJ(p?h=>_IUq z#g8~rCQnA~Ev&-US$=hXnfHQ1wZ-7y5Us7IZSZfm(5{D%9EUBKMjV?i$ywk|kbmZx zr>AdgfXPV)3GPD-7t`|eDC;;%tdeO85#y|zyPN4c)1SdR8|DZCl8$pw+*r#xo@Pi? zK96FIbrdsM4_aAr6ksGwO`t(fL4r303V9R>nX9<4hU>=S$@<~V-JHan^+OXaGUq8p z4Q2&`q$dgPj$Iooe(+C%dK@%BPvUQrw3c(h^@ba7s6_xd*@P^3^OT3p-~RTuSAHda z{QK++-ptQBi=yXtvxvR$gkP`ol*X||_%%lIAt%{~a?Fz}>#+x0DI}A`6_Dt%8QR7w zi0D;;hVDGtE$FKLGk&otyMpkvNxnQC)wuB=< zSku}9s&&wJOh7qx`pnxj^VR@GpaQ|;X0*}3KOTL{%iS571R+I^@h^SpOQ%I0T}qIe zwL=%s6Yz{t070&!1?Zsf&umyrzqQgr!!JI&mO%Q-SH5!E^hxmKNFvtEOM|T}LGuQf#9f!5(EP5QnS$r*kI(A9eH~hM_ z(}e>1un*b4eQPW6$u&1?bkN@Hh#lgvIf)havVLO=;o7$yR#n|hZ7C;gh2-YAe*q9WYQemig&1RH&*x{3t6COCN- zB0#y`u8&`Dcahb6>nfP&ARjyqjLlnMcoF~=YbjF(zA;l1#)0KWUbnfU^!0A-8W?K1QX%m9G zj8-o};i}6UbIGocp2^kfIKcZln6R=D z;F%5-tNe-X+NTNRqzkYt+j+ey7Fz$N?<6+s;wevt^5Jt&h4?jppzFPW?2UDl(&~8? z@HPG{2Bf$@=U9P-qRIZ>g#Tsa$df{Q+06;0_@SSR*gSU2&#V%^7`A%xBGyLLWpkW` zX_OMI1!7Mb1ReoQ@Nu4EC&}1`6rdD40(|6KDdVCaMU?^soEu|28J$}Tuht?D-cpblhdv(2m3fkI^wL6LrE9bV zShm0;-6&+uPeB_v=OgQ3{T=T~0l9#lJY@m=lGSyfXZoq~mqs`IXj6#Y=!#y@jvvr3 z|M4WwhgkUle%OR>;@>_y7sb$+Kb%Ws4=B9ph+by-?QWr1c5*h3YJ2}2C#_Cdf#vvw z{S9PyqqbLzpI*#??B^Nq?1y_>8HR0HWX4%^YMWdXI z5)rHwAo>*u8sP=1wgs~cuUSW8NUMya5&IkneiTMP z4&%|pyCCO?ruFE{cyu-VNDA~IP?9Nc|LMnvd3Z?xC6nYE-35^$Ksy1}cy!P+j&I~C zU0_{nE``CGn}9+(a*=^f6@%n=O#`}0F$DZ1ch{?eZql-6@M2ARm%P~2-r;j}Mz;zz zPww~#KKW+~Ip>}j@?Adc^(N8sypvd$di>EI%FWnL^E|{XJ=K2y+Upx)jSq=4=<)|X zAWmg(u8J`^Rz>8lG;5n&*n-Wiw@D23;5D85an8iqH2W}na5yhWZ}gE?{?{KbV4Uyr zO$#6!&SujjJwaI#xAA77HFn#||LReKmJHgbF6awv*6=osBw#I@TY_?}{I4FY(?Cr^?z zg-K)s#ZBH?6Vy|n*=Y1-qgexez<;~>$d&>UU9txfzwva;p2k|kns}oFX#iXDz)vr9;M>ViIJbLVT5579bQ+axo= z&m2i0MZ%FI{huaKNGLoM0gj$laNw~uYT#uN!|Kzw1&`9GO{Gs>1J}@RJ=ZPHuwx5J?#QPP@!Y2#7$2U zoC4395Iz(u)-s=NfqZEKqojad_`wT)!59hDYwH+8PP7!f=K1X+M?8QrDR}T`J|2w0 z<1GCqQ7;QL@e|)!7Wn07wTNqM5`EyC9cO_J@W7YN$-E$a#?YN2JcWov6`AQP{*i<= zOIO>0P4n3^>ncR?$-k|KANs-rd*g|}L7Z!KryxR1mZm1C+2G6rv0~FuG%r|RTEUc zc8|HbH`{-WpU!Gq;I*!_2GasaVjc_FHl_`#xm!^j*qo99NURS$&=)%#hU3hFfGx>! zvLOU;Yq;wX*s_MZBLx83`MiXt5AY}XE&7N!@}$sd<*}9^mBI=>_`&`yI%CEXG?}ce z0BB(iZ_kk@>j-c*n&Z3P^{)C2Ey3JZ)3YXe}D++)mp~3K{InQ z*3$(~e~i^9*y<-=97iEczi3G?; z1OfreYfq(86qA?kq1_<-)@wR!p-;nqiVV6!J2KG=yYbCM{cjnt16x^>f3hoo(Z@bs zlg;&Ouj{|Sz|V3sav_4e8oP=;e287yquOj3;YLtLP3)Vtz_g8m48Vr`N0Wg0sTjn@ zm9HJdP!G>l*w@4O4fUpCfmpYb*h^Mv{lwwS`FtNLSH}M}^X9cObZgrnwpiCAb>JLI|Qs{U7;$)hQx?s@mSYodY# zbIn?K@fCLkNs5jazxc)VX$_vyoI1q>=HiWP?B?l#zEMp2(H3w8U;0KnPdCWd7O~Mg z{v=xR7?*;j)kj-Y;#FdDG}gK6fWHJByub6E@2qs!L8}w|3u^4bMxkv@uZP7Bw0fm? ze3Jv;+WO?P|-{B?W$8xwuwpKW8S?a=CQuOmLrm)V(5 z+J6FMY&olKI*4up_EGF=4{s7x<_XS)9@_QKC5qIeyod+(*bs8WtOoStqZ4`AP?fBL6?w;vSzt$XgQfzlm_K(DCa6gFepDxee& zTwDU>5KdB~_gyy!>MICRKQ zwqFn^KW6B~|Zb6WdlFMC<#PcpYr@Pv*z34CXv>895t zXltU02aau{drfw_(9gN?1Z+yDadx@~yg1j)cf=Pb%tjgN17`BO0MO&F@slgB?Ei9o zyN-1QF#Ku2R(O;sou@zm^V!?H_^bKn0`ZSlN93hbe32nf|Hw=p{rKiH0AEvpiyiFO`oLZU-o-e3%v;l&C=}34d#)fpu|@W6#5YDP zwKsg*Su(U=>>n}EH;ToC#M?@9mq4DK0^0RoqpM-7%a5=iXNl?8Uw=dOS^F&cy~b5@ z&oi9$2B$>QCW`GKh^A0T@=I|d2vaEM%2S-G-~}KVNklF3SYM-j$9Am;OVOhcsds-% z+JYgIxbbLxi3Dv&$uI?qb$we$uubCKE^x)UB0sv3MZ58aGrAK9>5Pol1WzEWXOjw= zEl)lq1VVgbGF1m^Oz0*aJp%e=x8$uIVMkXY}gR=>T)kKC{(ZtM!yP+8TFe*+z* zRoZLNryF^euEa~e>j-O*-8ibO&2bjaDu95HHs=s3;+m{W&`eU~NR+`@C?juyNaV&# zfO%4|C_HiDfRcIEk)S1CL7c)h&YHEh6EqNHhB9ahG&Cg!g@kGsADZhxMhV}>$zAnW z(2BFQEd^WJHCJC#^+iWjZx8gJ6Uv4p6Zx#4B8V;pOyfLFyZi3DYq27cDGp!$@|Rb+ zyawye1AQhzSc7iKBY~iScJ8X#n9TT9G$=OMp3b8GwhghRXL7xaoF?9N5xqH*A;mK} z@ad>2cGwutZ0Sf3euD9lr@mq2Yb#bmizH6@Se^-nx#$w1Uv^uJKS`cOQUo}w2qF|9IjV*QQcY1HaY~NW024@Tl$Iwy^We99Qf&A*7LW`$T8~<*j!10PORf84&CSnIx^o{ zV7(L-o=)jkP@rKR{#yG7)1HxQE*`mZ>ko{r3cSVF@DtwfmEwnAMQ>!_Qz?QJa_;mL zOYC7DKU=i`3dVF2v;k}twDaOMIZ+H4ZgxsPvmlnp$#h0na*~+Z=C1P*(*lSrk>p?EUbpC0Ii$(A?>dAs_Z^X_EmTDcaDJ z*dr^4w>J8U3+DA8??wlFL*YWKJbk%uhC`?Ja}ylGD3Jx zVPqW%SHQ@Iu!fB?m182yOf0#HL$_^w6;I?MOA2W6JJOkN*U^z=XpZC$bZQ(u&?8wC zmGnd=^EZjY@s#gX16Z9q1F_NZ6US@v=d)}TdE)nxjokdq-tbgWQ%#}cI)AXA`Cn-8 ziOA5l7I|H+Y#p8D|hj#%l1&;up zCrDYF!!w|<5<2IPK^?s|H^I|+TkPN)J;~FiQqYh`0iu~dZ0NRYNIHs#d?o-*^3Y%I zK-xPIGWgt&z64Tq@g|wmLkcZCc#U7zQ@G&O7<|*2`Dp38=9;Uke({zfhz-KC#28sl zo$kLH|4`A7BVCY#3`v%=f<3f)7@m(cNhEeB54q@0fA}H~9VrO;0-5xU!FY6oyyn03 zMD9&IH3~^ZYl{L&AU0yd#~$r(7IKYl^&5kRWA+>yvjtzB z%GhGJr)X@dx7xp9eYIx@`1W`bq>~b&0AaX z6*kh>UZ-bAi3spx&G1dG_Uj6;u(=nF0D?sNhH>m4ojKHbEV?GTyBLr3($FHRTP z#w=@`b%y%h4zUOSqTA>rew+QZ(;#1K-NkdSX-U^s}eC z6UY1C3iEoC{#$i(W_xZ6x~u#ZKRuUdV?KR|sqC3JXx|v)Cf@lv{x$TUb&)+ghR^xb z!Pnr22oH`^#wOrE61X6D{SE!wO*T12Ni3A%4pM&fwV8%M zvu%Q%vEkEGBZ&h4ctw{?_(c~F#wr>@-{0eEH>2w|2;Rx}^izFdr{8?d8VszDe2PF% zeaPTQ&+KK5@Rq_cI^#e<4t;cE1GKO%Ud$y^U?b3-xok%s^EGtwSc6Vk$Gq6%)TzFJ zYn$tSeDH%G=>NJtSv3Adcb**b4ZPrEQ^1q8>7IS)ieHcyuS3`;`p2&AB(i3T9=7Dq zK*z4}0lKUHQhYeRKqfz8W-i@@meztE%%uxD*XW!ND`@$RIcT%7bA>Bj6t3A@JAwhP ziz2atZfg80x|?O&Wq}5r*zeZSE+iBWsWP^$ZkY8|w_~V0Hpd}K8B}8kU+2?e&nl?8 z@o%V`^AKW!z3V7XwDFZ(@|*Z>56vrnhWZ$5RY$w5r`gYcF*G?IIot;?NlZW!WC_bj z9)0A|n#2s&z?SQDj}$CF2C+Jmsm1oPk`i?%|0%XbM!3 zhau4u$P*y(=Xx4QzDeSNbF?{%z^8ewA8mB$NypbR_f>w^=?ot}=V7d0pC+3|7J55Y)H{{VCqKW)Iun89%F?V^L;eS^!~^fbIk}$yU+f z?I*!hkswIe(C!`uPAv&m;FTcIXb}Ynh@nk+KEvW%0Hs{tv{FC`MnJiOq{I{2f^41u zNJLTmETG%Ub8`v2iXQR^y!cKswzeiIBv^Y*p2##cW`SU7EP7}w7RZ%=PEVTTfDT<* z7cT;=g2%b>t{F>4Z&?|q7$IkPr9amNQ#^A@iH&~HPeC*U+L0CNQ?skCthDK#>?xEW ze9$>(_f5bTzTgGj4MjF`vJalD8(joL+k-K9Hm}vCHFFKv3Vj7Gy^wbqpoPYerxx?B zEdsoggAdY|M2^?p0{$Zd8}K80gzxc1{PBa>m5tAW=>s*GYb?3!t30`2|M>Hw;EVAs zzMuVVuktDUr$DN{SoXO+WG%1hbIgx+67kCvLVP>6jm{@(AH|t5{T(sgp{4jAgK>Ke zh5IdXq^*;<>ij(hw&i1yt ztgUB#N6q-46|QX@mt#u^)>V*%KQc(}iYUC2PjI#&T6yq@e>_4+ zfwuF&cu6V=1uta53%QJMH=BeLohx#*Bsc5g8@x_Z*$!k;spG}b-;LtT_@OIuv4y_K zN+tbUOyJk(UnW!|6Uc*ZJHS*3s)2@T7?gbZLEj;Hj)u$5dPRH?c{} z1ODwVy5o;~1uc(5-qR-HUC>}#KF!DZwOA7SrUCo6Hy z3#15Yb+jyobMtzProQ-=Jwhk!p?_@rBFNm#rxQL+Mz#Xi>=ClED}A*^_cEYQw8p@m zY(U@mpliOuUd!4U>}6m-w4K6Z@vwXStz(s>2IZXYr9? zyHMnYRW=->~3Hr@x`*KcSj`0yPOX_&nGB0T5 zm<2SAp+~e%o;+3bakAQozmvhWS=h26C%!>0&H7{pa=OO1*vGM*y9)3KY%mY(L`HTd zBfhMSr!gMr@z}AgKcV3!!t3}MomltDLYFLL<5NEH9vh?WXr6t+XYg#V8Do6xV{CXq zd!EkcVJHuO!ZZI!0T`RwPp;v=m31ZxZTv^}Re21G#QrxI_{Ad|?k3oc?{2q$b`wz* zU*kh;%D!oM-3$EUFEM@{9~s-5%fNhoJ@oDHhc`U#78ddMU|#J0oKO9X`X!;J0D8;h z(isq*fP|Gm39NBy*CZuLIYmH%QXl+|)w{bmlqOgSV#cEz!=mM{c;9ft^|d(CkA@;E z^sXrF(o6bZK1PeuB~pcg;>@b^jI}f_~%38GUQ`;)_YP@%89uQNFeVpWN=LMT-=hTKo;~!{q83JG6n5Ecj

SGVAI60S=cV9nu|~RkIu=! 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

HO4XGE| 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 literal 137855 zcmXt<2RPMl*vFALwjzmRj~ts$lD$LbF|t?4I#%|~E;Dqb?ajHs0V-&g;=)pTCo0gz_D@gG)vk+xcs$d||NYoW^WtLZh99TyzZY&! z!58BdPSVX6w*4RQF}Z>X>@i$jd@pZ3q)76qWMVxpHF2rEnVDHuX@z~3jp5;0fFLb< z>&F>~!?XFr&bSNvW}^k?7Z5i;zjgy&_qH5td-whe?o^GkWHEJ^P0?h=m~HodmCMiF zlil6j^V^AtpnrcX#d5#dK2o15PRS~@X`Bm?l7^B$R(BN1j*tsMEzHl?5yDE4m=>fa zXL52f)%c-pMJNA-~y4+!X%*n%R?oXFa$G?5MzUa9zMtcsqWsUuI z70prO99>61EVFDo7P{NpxoKkBYtlz;mQGF4W9#nP)LZR&W45N~T#Yh^KcxF7C;AZW z3f+IUZ6*#`zc0F1MZvF5AH5ed7}O&Wu618lwF2u`g2>b;v!wm2-es1r#%W3G+>sr> znvm^`}vDQ|d`Km3brn1 zFCl2wHWbTg?>#=}Z9^gRlPi`k?sJ)DzJ{h|3;__fb zoAUhp{HI%vASv!$mI3!RxH^?gduL}8FSaZ{Xk_D1?rnB<_L@r(7jdWsoDRG%zb;1n zKKC{gUYf=^-e}g*2I0)uRngT0T2Tpc@mnuTr(iN>)%p>Xc^fkh&0Nvksl?3OB}akM zq^MzQ))HQtm^KsVp<9x4aWdU%oQ)>@F@vmSRQP=!V%2D@MaEC5_|>xjGw#&$tL~KV zf}|)xuMhXrZ3Jm!hh9#>pO+x073JQlaq85f@5e;oF?wOJ$I}$gOTJqRtB_?>-H%+^ z@42aY&znDrhJ-S^n!bP}j&C3_{OP0G)Q{=nf_lukr~{VvkNt9Xtc5G| zt5k|5($2c`N7v)KF-6&&;g>Iq(haJM9jIV-_7@>z|*J3;uk4(s8TK zt0VX4pjEvxveG^a+wQ=4$u?KeeZSQHr?s$~skbN;e1;ed#

Ipmp4ZBtlLkd(2uG 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 OKY3{tsd5SU=l=r;@S|k_ diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 2bd67c11c..252472e8d 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -27,7 +27,7 @@ QSplashScreen() progress = 0; textX = 5; textY = 20; - pbLeft = 0; + pbLeft = 2; pbTop = 0; pbWidth = 100; pbHeight = 20; @@ -42,14 +42,12 @@ void SplashScreen::setPixmap( const QPixmap &pixmap ) QSplashScreen::setPixmap( pixmap ); if( this->pixmap().width() > 0 ) - pbWidth = this->pixmap().width(); + pbWidth = this->pixmap().width() - 4; if( this->pixmap().height() > 0 ) - pbTop = this->pixmap().height(); + pbTop = this->pixmap().height() - pbHeight - 2; textY = pbTop - pbHeight / 2; - - resize( pbWidth, pbTop + pbHeight ); } void SplashScreen::setText( const QString &text ) @@ -92,7 +90,7 @@ void SplashScreen::drawContents( QPainter *painter ) pbStyle.maximum = 100; pbStyle.progress = progress; pbStyle.invertedAppearance = false; - pbStyle.rect = QRect( 0, pbTop, pbWidth, pbHeight ); + pbStyle.rect = QRect( pbLeft, pbTop, pbWidth, pbHeight ); style()->drawControl( QStyle::CE_ProgressBar, &pbStyle, painter, this ); } From 732b24b9859807ace94e7e3192cf99115ebfaf6a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 20:04:15 +0200 Subject: [PATCH 045/282] Updated qrc location. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/core/plugin_view_dialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/core/plugin_view_dialog.ui b/code/studio/src/plugins/core/plugin_view_dialog.ui index 9d7d395be..53ee0efb8 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.ui +++ b/code/studio/src/plugins/core/plugin_view_dialog.ui @@ -112,7 +112,7 @@ - + From eb41278369e55b5ca8df329ffe697c86adbbae97 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 21:07:46 +0200 Subject: [PATCH 046/282] GUI for plugin loading / unloading in the plugin dialog. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/core/plugin_view_dialog.cpp | 38 +++++++++++++++++ .../src/plugins/core/plugin_view_dialog.h | 4 ++ .../src/plugins/core/plugin_view_dialog.ui | 41 +++++++++++++------ 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index 175902d39..316bb0097 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include // Project includes #include "../../extension_system/iplugin_spec.h" @@ -43,6 +45,10 @@ PluginView::PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget * connect(m_pluginManager, SIGNAL(pluginsChanged()), this, SLOT(updateList())); connect(this, SIGNAL(accepted()), this, SLOT(updateSettings())); + connect( m_ui.pluginTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ), this, SLOT( onItemClicked() ) ); + connect( m_ui.unloadButton, SIGNAL( clicked( bool ) ), this, SLOT( onUnloadClicked() ) ); + connect( m_ui.loadButton, SIGNAL( clicked( bool ) ), this, SLOT( onLoadClicked() ) ); + // WhiteList is list of plugins which can not disable. m_whiteList << Constants::OVQT_CORE_PLUGIN; updateList(); @@ -105,4 +111,36 @@ void PluginView::updateSettings() } } +void PluginView::onItemClicked() +{ + m_ui.unloadButton->setEnabled( true ); +} + +void PluginView::onUnloadClicked() +{ + QTreeWidgetItem *item = m_ui.pluginTreeWidget->currentItem(); + if( item == NULL ) + { + QMessageBox::warning( this, + tr( "Plugin unload" ), + tr( "No plugin selected!" ) ); + return; + } + + +} + +void PluginView::onLoadClicked() +{ + QString f = QFileDialog::getOpenFileName( this, + tr( "Loading a plugin" ), + ".", + "Plugin specifications ( *.xml )" ); + + if( f.isEmpty() ) + { + return; + } +} + } /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.h b/code/studio/src/plugins/core/plugin_view_dialog.h index aae16749d..e11449fdd 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.h +++ b/code/studio/src/plugins/core/plugin_view_dialog.h @@ -44,6 +44,10 @@ private Q_SLOTS: void updateList(); void updateSettings(); + void onItemClicked(); + void onUnloadClicked(); + void onLoadClicked(); + private: const int m_checkStateColumn; diff --git a/code/studio/src/plugins/core/plugin_view_dialog.ui b/code/studio/src/plugins/core/plugin_view_dialog.ui index 53ee0efb8..45c4695e8 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.ui +++ b/code/studio/src/plugins/core/plugin_view_dialog.ui @@ -17,7 +17,7 @@ true - + true @@ -79,7 +79,34 @@ + + + + false + + + All objects list + + + + + + false + + + Unload plugin + + + + + + + Load plugin + + + + Qt::Horizontal @@ -92,23 +119,13 @@ - + Close - - - - false - - - All objects list - - - From d7536332a68ab948953e21363607fd0738fb62b6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:17:24 +0200 Subject: [PATCH 047/282] Implemented plugin unload. --HG-- branch : gsoc2014-dfighter --- .../src/extension_system/iplugin_manager.h | 3 + .../src/extension_system/plugin_manager.cpp | 62 +++++++++++++++++++ .../src/extension_system/plugin_manager.h | 4 ++ .../src/plugins/core/plugin_view_dialog.cpp | 17 ++++- .../src/plugins/core/plugin_view_dialog.h | 1 + 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index 15fa4a336..efbf5ee2f 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -55,6 +55,9 @@ public: virtual void setPluginPaths(const QStringList &paths) = 0; virtual QList plugins() const = 0; + virtual bool loadPlugin( const char *plugin ) = 0; + virtual bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ) = 0; + // Settings virtual void setSettings(QSettings *settings) = 0; virtual QSettings *settings() const = 0; diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 265268896..c9f40e7bd 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -114,6 +114,68 @@ void PluginManager::loadPlugins() Q_EMIT pluginsChanged(); } +bool PluginManager::loadPlugin( const char *plugin ) +{ + return true; +} + +bool PluginManager::unloadPlugin( ExtensionSystem::IPluginSpec *plugin ) +{ + ExtensionSystem::PluginSpec *spec = static_cast< ExtensionSystem::PluginSpec* >( plugin ); + + // Let's see if anything depends on this one + QListIterator< ExtensionSystem::PluginSpec* > itr( m_pluginSpecs ); + while( itr.hasNext() ) + { + ExtensionSystem::PluginSpec *sp = itr.next(); + QList< ExtensionSystem::PluginSpec* > l = sp->dependencySpecs(); + if( l.contains( spec ) ) + return false; + } + + // Stop, delete then remove plugin + spec->stop(); + spec->kill(); + removePlugin( plugin ); + + return true; +} + +void PluginManager::removePlugin( ExtensionSystem::IPluginSpec *plugin ) +{ + QList< ExtensionSystem::IPluginSpec* >::iterator itr1; + QList< ExtensionSystem::PluginSpec* >::iterator itr2; + + QList< ExtensionSystem::IPluginSpec* >::iterator i1 = m_ipluginSpecs.begin(); + while( i1 != m_ipluginSpecs.end() ) + { + if( *i1 == plugin ) + { + itr1 = i1; + break; + } + i1++; + } + + QList< ExtensionSystem::PluginSpec* >::iterator i2 = m_pluginSpecs.begin(); + while( i2 != m_pluginSpecs.end() ) + { + if( *i2 == static_cast< ExtensionSystem::PluginSpec* >( plugin ) ) + { + itr2 = i2; + break; + } + i2++; + } + + m_ipluginSpecs.erase( itr1 ); + m_pluginSpecs.erase( itr2 ); + delete plugin; + + Q_EMIT pluginsChanged(); + +} + QStringList PluginManager::getPluginPaths() const { return m_pluginPaths; diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 9ab1ae135..10130ffc4 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,6 +51,10 @@ public: virtual QList plugins() const; QList loadQueue(); + bool loadPlugin( const char *plugin ); + bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); + void removePlugin( ExtensionSystem::IPluginSpec *plugin ); + // Settings virtual void setSettings(QSettings *settings); virtual QSettings *settings() const; diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index 316bb0097..bf62d4632 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -65,6 +65,7 @@ void PluginView::updateList() static QIcon notLoadedIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton); m_specToItem.clear(); + m_itemToSpec.clear(); QList items; Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) @@ -87,6 +88,7 @@ void PluginView::updateList() items.append(item); m_specToItem.insert(spec, item); + m_itemToSpec.insert(item, spec); } m_ui.pluginTreeWidget->clear(); @@ -127,7 +129,18 @@ void PluginView::onUnloadClicked() return; } - + QMap< QTreeWidgetItem*, ExtensionSystem::IPluginSpec* >::const_iterator itr + = m_itemToSpec.find( item ); + if( itr == m_itemToSpec.end() ) + return; + + bool success = m_pluginManager->unloadPlugin( itr.value() ); + if( !success ) + { + QMessageBox::warning( this, + tr( "Plugin unload" ), + tr( "Failed to unload plugin." ) ); + } } void PluginView::onLoadClicked() @@ -141,6 +154,8 @@ void PluginView::onLoadClicked() { return; } + + this->m_pluginManager->loadPlugin( f.toAscii().data() ); } } /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.h b/code/studio/src/plugins/core/plugin_view_dialog.h index e11449fdd..e7c1123c1 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.h +++ b/code/studio/src/plugins/core/plugin_view_dialog.h @@ -52,6 +52,7 @@ private: const int m_checkStateColumn; QMap m_specToItem; + QMap m_itemToSpec; QStringList m_whiteList; ExtensionSystem::IPluginManager *m_pluginManager; Ui::PluginView m_ui; From fb4dc15fe7abaff49269034340c920a148d6955e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:30:09 +0200 Subject: [PATCH 048/282] Remove GUI Editor menu when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/gui_editor_window.cpp | 11 +++++++++++ .../studio/src/plugins/gui_editor/gui_editor_window.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 24ecc5cfc..e48a37ba6 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -55,6 +55,7 @@ namespace GUIEditor GUIEditorWindow::GUIEditorWindow(QWidget *parent) : QMainWindow(parent) { + menu = NULL; m_ui.setupUi(this); messageProcessor = new CEditorMessageProcessor; m_undoStack = new QUndoStack(this); @@ -112,6 +113,8 @@ namespace GUIEditor { writeSettings(); + removeMenus(); + delete messageProcessor; messageProcessor = NULL; @@ -382,8 +385,16 @@ namespace GUIEditor a = new QAction( "Add Widget", this ); connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); + + menu = m; } } + + void GUIEditorWindow::removeMenus() + { + delete menu; + menu = NULL; + } void GUIEditorWindow::readSettings() { diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index e1a8b8b2d..1362e4671 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -26,6 +26,8 @@ class QtTreePropertyBrowser; +class QMenu; + namespace GUIEditor { @@ -66,6 +68,7 @@ private Q_SLOTS: private: void createMenus(); + void removeMenus(); void readSettings(); @@ -88,6 +91,8 @@ private: CPropBrowserCtrl browserCtrl; QString currentProject; QString currentProjectFile; + + QMenu *menu; }; } From 828f31a2a4383a812acb1e76508736b34f7bd22d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:45:13 +0200 Subject: [PATCH 049/282] Remove translation manager menu when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../translation_manager_main_window.cpp | 37 ++++++++++++++----- .../translation_manager_main_window.h | 6 ++- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index d80ffe3f5..244a5a92c 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -47,6 +47,7 @@ namespace TranslationManager CMainWindow::CMainWindow(QWidget *parent) : QMainWindow(parent) { + menu = NULL; _ui.setupUi(this); _ui.mdiArea->closeAllSubWindows(); @@ -59,10 +60,37 @@ CMainWindow::CMainWindow(QWidget *parent) connect(Core::ICore::instance(), SIGNAL(changeSettings()), this, SLOT(readSettings())); readSettings(); createToolbar(); + createMenus(); m_undoStack = new QUndoStack(this); } +CMainWindow::~CMainWindow() +{ + removeMenus(); +} + +void CMainWindow::removeMenus() +{ + delete menu; + menu = NULL; +} + +void CMainWindow::createMenus() +{ + // Windows menu + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + QMenu *m = menuManager->menuBar()->addMenu( "Translation Manager" ); + if( m != NULL ) + { + windowMenu = m->addMenu("Window"); + menu = m; + } + + updateWindowsList(); + connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); +} + // Functions that will insert the plugin buttons void CMainWindow::createToolbar() { @@ -126,17 +154,8 @@ void CMainWindow::createToolbar() mergeSingleFileAct->setStatusTip(tr("Merge worksheet file from local or remote directory")); connect(mergeSingleFileAct, SIGNAL(triggered()), this, SLOT(mergeSingleFile())); - // Windows menu Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - QMenu *m = menuManager->menuBar()->addMenu( "Translation Manager" ); - if( m != NULL ) - { - windowMenu = m->addMenu("Window"); - } - - updateWindowsList(); - connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); // Undo, Redo actions QAction *undoAction = menuManager->action(Core::Constants::UNDO); diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h index c67f282e0..73bccdd8e 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h @@ -58,7 +58,7 @@ class CMainWindow : public QMainWindow public: CMainWindow(QWidget *parent = 0); - virtual ~CMainWindow() {} + ~CMainWindow(); QUndoStack *m_undoStack; public: @@ -96,6 +96,7 @@ private: void updateToolbar(QMdiSubWindow *window); bool verifySettings(); void readSettings(); + void removeMenus(); void createMenus(); void createToolbar(); void initializeSettings(bool georges); @@ -105,6 +106,9 @@ private: CEditorWorksheet *getEditorByWorksheetType(const QString &type); bool isWorksheetEditor(QString filename); bool isPhraseEditor(QString filename); + + + QMenu *menu; }; class CCoreListener : public Core::ICoreListener From 3fc289e7fa0429b1455c5a94c31e7b67ef75a2d2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:56:40 +0200 Subject: [PATCH 050/282] Remove sheet builder action when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../ovqt_sheet_builder/ovqt_sheet_builder.cpp | 12 ++++++++++++ .../plugins/ovqt_sheet_builder/ovqt_sheet_builder.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp index 4fd7dfb11..8ea90fdc5 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp @@ -35,6 +35,18 @@ using namespace Plugin; +SheetBuilderPlugin::SheetBuilderPlugin() +{ +} + +SheetBuilderPlugin::~SheetBuilderPlugin() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + QAction *a = menuManager->action( "SheetBuilder" ); + menuManager->unregisterAction( "SheetBuilder" ); + delete a; +} + bool SheetBuilderPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) { Q_UNUSED(errorString); diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h index 504d0914d..21e2855c1 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h @@ -36,6 +36,8 @@ class SheetBuilderPlugin : public QObject, public ExtensionSystem::IPlugin Q_OBJECT Q_INTERFACES(ExtensionSystem::IPlugin) public: + SheetBuilderPlugin(); + ~SheetBuilderPlugin(); bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); void extensionsInitialized(); void setNelContext(NLMISC::INelContext *nelContext); From b9bbe802d4e9a54959b79f7c79ee80fe6a874e00 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:27:03 +0200 Subject: [PATCH 051/282] Remove display sheet id action when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../plugins/disp_sheet_id/disp_sheet_id_plugin.cpp | 12 ++++++++++++ .../src/plugins/disp_sheet_id/disp_sheet_id_plugin.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp index 62d2f0430..77e254081 100644 --- a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp +++ b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp @@ -34,6 +34,18 @@ using namespace SheetIdViewPlugin; +DispSheetIdPlugin::DispSheetIdPlugin() +{ +} + +DispSheetIdPlugin::~DispSheetIdPlugin() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + QAction *a = menuManager->action( "SheetIdView" ); + menuManager->unregisterAction( "SheetIdView" ); + delete a; +} + bool DispSheetIdPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) { Q_UNUSED(errorString); diff --git a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h index 8eaf3ead9..7506b84cc 100644 --- a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h +++ b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h @@ -37,6 +37,9 @@ class DispSheetIdPlugin : public QObject, public ExtensionSystem::IPlugin Q_INTERFACES(ExtensionSystem::IPlugin) public: + DispSheetIdPlugin(); + ~DispSheetIdPlugin(); + bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); void extensionsInitialized(); void setNelContext(NLMISC::INelContext *nelContext); From 9ad71881dc26d50fb4f9d6ebf1ee7bb4d02d4e74 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:28:19 +0200 Subject: [PATCH 052/282] Line endings... --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index ae3520465..0effbe087 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -25,8 +25,8 @@ #include #include -namespace Ui { - class TileEditorMainWindow; +namespace Ui { + class TileEditorMainWindow; } class TileModel; @@ -37,7 +37,7 @@ class TileEditorMainWindow : public QMainWindow Q_OBJECT public: - explicit TileEditorMainWindow(QWidget *parent = 0); + explicit TileEditorMainWindow(QWidget *parent = 0); ~TileEditorMainWindow(); QUndoStack *getUndoStack() { return m_undoStack; } From 0096ad1204dd885a9201826c41f1a29471026e9d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:39:58 +0200 Subject: [PATCH 053/282] Remove Object Viewer menus when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/object_viewer/main_window.cpp | 11 +++++++++++ code/studio/src/plugins/object_viewer/main_window.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index 91f832ac0..864896ca1 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -71,6 +71,7 @@ CMainWindow::CMainWindow(QWidget *parent) _lastDir("."), _mouseMode(NL3D::U3dMouseListener::edit3d) { + menu = NULL; nldebug("CMainWindow::CMainWindow:"); setObjectName("CMainWindow"); @@ -134,6 +135,8 @@ CMainWindow::~CMainWindow() settings->endGroup(); settings->sync(); + removeMenus(); + delete _AnimationDialog; delete _AnimationSetDialog; delete _SlotManagerDialog; @@ -323,6 +326,14 @@ void CMainWindow::createMenus() connect(_ParticleControlDialog->toggleViewAction(), SIGNAL(triggered(bool)), _ParticleWorkspaceDialog->_PropertyDialog, SLOT(setVisible(bool))); + menu = ovMenu; + +} + +void CMainWindow::removeMenus() +{ + delete menu; + menu = NULL; } void CMainWindow::createToolBars() diff --git a/code/studio/src/plugins/object_viewer/main_window.h b/code/studio/src/plugins/object_viewer/main_window.h index 5a392c191..dff4d9b4b 100644 --- a/code/studio/src/plugins/object_viewer/main_window.h +++ b/code/studio/src/plugins/object_viewer/main_window.h @@ -95,6 +95,7 @@ protected: private: void createActions(); void createMenus(); + void removeMenus(); void createToolBars(); void createDialogs(); @@ -144,6 +145,8 @@ private: uint _numTri; float _texMem; sint _mouseMode; + + QMenu *menu; };/* class CMainWindow */ } /* namespace NLQT */ From c45b6a17f4c54f9d37af598949180960fc6e83f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 21:56:31 +0200 Subject: [PATCH 054/282] Don't crash when removing the plugin of the first tab. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/core/context_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/core/context_manager.cpp b/code/studio/src/plugins/core/context_manager.cpp index 8355b5cb8..d81f62cf1 100644 --- a/code/studio/src/plugins/core/context_manager.cpp +++ b/code/studio/src/plugins/core/context_manager.cpp @@ -135,8 +135,8 @@ void ContextManager::removeContextObject(IContext *context) const int index = indexOf(context->id()); QWidget *widget = d->m_tabWidget->widget(index); - d->m_tabWidget->removeTab(index); d->m_contexts.remove(index); + d->m_tabWidget->removeTab(index); delete widget; } From f060adbed7eef79980322a89636ae1ce8dd8b1f7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 01:14:13 +0200 Subject: [PATCH 055/282] Plugin loading, with issues.. --HG-- branch : gsoc2014-dfighter --- .../src/extension_system/plugin_manager.cpp | 60 +++++++++++++++++-- .../src/extension_system/plugin_manager.h | 1 + .../src/plugins/core/context_manager.cpp | 10 +--- .../studio/src/plugins/core/context_manager.h | 3 +- .../src/plugins/core/plugin_view_dialog.cpp | 15 ++++- 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index c9f40e7bd..508a4b81b 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -114,8 +114,62 @@ void PluginManager::loadPlugins() Q_EMIT pluginsChanged(); } +bool PluginManager::loadPluginSpec( const char *plugin ) +{ + nlinfo( "Loading plugin spec %s", plugin ); + + PluginSpec *spec = new PluginSpec; + spec->m_pluginManager = this; + if( !spec->setSpecFileName( plugin ) ) + { + nlinfo( "Error loading plugin spec %s", plugin ); + return false; + } + + m_pluginSpecs.append( spec ); + m_ipluginSpecs.append( spec ); + + return true; +} + bool PluginManager::loadPlugin( const char *plugin ) { + if( !loadPluginSpec( plugin ) ) + return false; + + ExtensionSystem::PluginSpec *spec = m_pluginSpecs.last(); + + if( !spec->resolveDependencies( m_pluginSpecs ) ) + { + nlinfo( "Error resolving dependencies for plugin spec %s", plugin ); + return false; + } + + if( !spec->loadLibrary() ) + { + nlinfo( "Error loading plugin %s", spec->fileName().toUtf8().data() ); + return false; + } + + if( !spec->initializePlugin() ) + { + nlinfo( "Error initializing plugin %s", spec->fileName().toUtf8().data() ); + spec->kill(); + return false; + } + + if( !spec->initializeExtensions() ) + { + nlinfo( "Error starting plugin %s", spec->fileName().toUtf8().data() ); + spec->stop(); + spec->kill(); + return false; + } + + nlinfo( "Loaded plugin %s ( %s )", spec->name().data(), spec->fileName().toUtf8().data() ); + + Q_EMIT pluginsChanged(); + return true; } @@ -262,11 +316,7 @@ void PluginManager::readPluginPaths() Q_FOREACH (const QString &pluginFile, pluginsList) { - PluginSpec *spec = new PluginSpec; - spec->m_pluginManager = this; - spec->setSpecFileName(pluginFile); - m_pluginSpecs.append(spec); - m_ipluginSpecs.append(spec); + loadPluginSpec( pluginFile.toUtf8().data() ); } Q_EMIT pluginsChanged(); diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 10130ffc4..9b0d7a0dc 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,6 +51,7 @@ public: virtual QList plugins() const; QList loadQueue(); + bool loadPluginSpec( const char *plugin ); bool loadPlugin( const char *plugin ); bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); void removePlugin( ExtensionSystem::IPluginSpec *plugin ); diff --git a/code/studio/src/plugins/core/context_manager.cpp b/code/studio/src/plugins/core/context_manager.cpp index d81f62cf1..3b02b411c 100644 --- a/code/studio/src/plugins/core/context_manager.cpp +++ b/code/studio/src/plugins/core/context_manager.cpp @@ -36,13 +36,11 @@ struct ContextManagerPrivate Core::MainWindow *m_mainWindow; QTabWidget *m_tabWidget; QVector m_contexts; - int m_oldCurrent; }; ContextManagerPrivate::ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget) : m_mainWindow(mainWindow), - m_tabWidget(tabWidget), - m_oldCurrent(-1) + m_tabWidget(tabWidget) { } @@ -145,11 +143,7 @@ void ContextManager::currentTabChanged(int index) if (index >= 0) { IContext *context = d->m_contexts.at(index); - IContext *oldContext = 0; - if (d->m_oldCurrent >= 0) - oldContext = d->m_contexts.at(d->m_oldCurrent); - d->m_oldCurrent = index; - Q_EMIT currentContextChanged(context, oldContext); + Q_EMIT currentContextChanged(context); } } diff --git a/code/studio/src/plugins/core/context_manager.h b/code/studio/src/plugins/core/context_manager.h index 8151648e7..9b0a62c7e 100644 --- a/code/studio/src/plugins/core/context_manager.h +++ b/code/studio/src/plugins/core/context_manager.h @@ -51,8 +51,7 @@ public: void unregisterUndoStack(QUndoStack *stack); Q_SIGNALS: - // the default argument '=0' is important for connects without the oldContext argument. - void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0); + void currentContextChanged(Core::IContext *context); public Q_SLOTS: void activateContext(const QString &id); diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index bf62d4632..c47a1c75d 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -155,7 +155,18 @@ void PluginView::onLoadClicked() return; } - this->m_pluginManager->loadPlugin( f.toAscii().data() ); + QApplication::setOverrideCursor( Qt::WaitCursor ); + bool success = m_pluginManager->loadPlugin( f.toAscii().data() ); + QApplication::setOverrideCursor( Qt::ArrowCursor ); + + if( !success ) + { + QMessageBox::warning( this, + tr( "Loading plugin" ), + tr( "Error loading plugin!" ) ); + } } -} /* namespace Core */ \ No newline at end of file + +} /* namespace Core */ + From d4ee31ed63dd2ea99886ac10659e87d0ee042ea3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:40:06 +0200 Subject: [PATCH 056/282] Destroy context when unloading plugins. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp | 3 +++ code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp | 3 +++ .../src/plugins/georges_editor/georges_editor_plugin.cpp | 3 +++ code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp | 3 +++ .../src/plugins/landscape_editor/landscape_editor_plugin.cpp | 3 +++ code/studio/src/plugins/log/log_plugin.cpp | 3 +++ .../src/plugins/mission_compiler/mission_compiler_plugin.cpp | 3 +++ code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp | 3 +++ .../src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp | 3 +++ code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp | 3 +++ .../plugins/translation_manager/translation_manager_plugin.cpp | 3 +++ code/studio/src/plugins/world_editor/world_editor_plugin.cpp | 3 +++ 12 files changed, 36 insertions(+) diff --git a/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp index e4bf7f594..509dd2997 100644 --- a/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp +++ b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp @@ -44,6 +44,9 @@ namespace BNPManager } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool BNPManagerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp index 77e254081..46a8ee6bd 100644 --- a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp +++ b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp @@ -44,6 +44,9 @@ DispSheetIdPlugin::~DispSheetIdPlugin() QAction *a = menuManager->action( "SheetIdView" ); menuManager->unregisterAction( "SheetIdView" ); delete a; + + delete m_LibContext; + m_LibContext = NULL; } bool DispSheetIdPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp b/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp index 075ac41b2..f1b419e4e 100644 --- a/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp +++ b/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp @@ -39,6 +39,9 @@ GeorgesEditorPlugin::~GeorgesEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool GeorgesEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp b/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp index d0fea4df3..d5f2403f1 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp @@ -37,6 +37,9 @@ namespace GUIEditor qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool GUIEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp index 73a6f5b25..f97aff691 100644 --- a/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp +++ b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp @@ -39,6 +39,9 @@ LandscapeEditorPlugin::~LandscapeEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool LandscapeEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp index 0f86ab90c..2017ed91a 100644 --- a/code/studio/src/plugins/log/log_plugin.cpp +++ b/code/studio/src/plugins/log/log_plugin.cpp @@ -62,6 +62,9 @@ namespace Plugin NLMISC::AssertLog->removeDisplayer(m_displayer); NLMISC::InfoLog->removeDisplayer(m_displayer); delete m_displayer; + + delete m_libContext; + m_libContext = NULL; } bool CLogPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp index 98b188fd3..46e51f36d 100644 --- a/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp +++ b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp @@ -30,6 +30,9 @@ MissionCompilerPlugin::~MissionCompilerPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_LibContext; + m_LibContext = NULL; } bool MissionCompilerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp index 34fc0f1b4..dce7ad08f 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp +++ b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp @@ -23,6 +23,9 @@ ObjectViewerPlugin::~ObjectViewerPlugin() qDeleteAll(_autoReleaseObjects); _autoReleaseObjects.clear(); Modules::release(); + + delete _LibContext; + _LibContext = NULL; } bool ObjectViewerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp index 8ea90fdc5..21358ec6f 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp @@ -45,6 +45,9 @@ SheetBuilderPlugin::~SheetBuilderPlugin() QAction *a = menuManager->action( "SheetBuilder" ); menuManager->unregisterAction( "SheetBuilder" ); delete a; + + delete m_LibContext; + m_LibContext = NULL; } bool SheetBuilderPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp index ac12766b8..33a617cc1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp @@ -42,6 +42,9 @@ TileEditorPlugin::~TileEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_LibContext; + m_LibContext = NULL; } bool TileEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp b/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp index 20359ccbd..3fafc7510 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp @@ -48,6 +48,9 @@ TranslationManagerPlugin::~TranslationManagerPlugin() } qDeleteAll(_autoReleaseObjects); _autoReleaseObjects.clear(); + + delete _LibContext; + _LibContext = NULL; } bool TranslationManagerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/world_editor/world_editor_plugin.cpp b/code/studio/src/plugins/world_editor/world_editor_plugin.cpp index 301939cb6..3170bce60 100644 --- a/code/studio/src/plugins/world_editor/world_editor_plugin.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_plugin.cpp @@ -43,6 +43,9 @@ WorldEditorPlugin::~WorldEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool WorldEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) From a86605f8d871e292b8cb83d615ca976af3f05f56 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:55:45 +0200 Subject: [PATCH 057/282] Move the log trigger menu item into it's own menu, and remove the menu when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/log/log_plugin.cpp | 8 ++++++-- code/studio/src/plugins/log/log_plugin.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp index 2017ed91a..562b3bb6f 100644 --- a/code/studio/src/plugins/log/log_plugin.cpp +++ b/code/studio/src/plugins/log/log_plugin.cpp @@ -45,6 +45,7 @@ namespace Plugin CLogPlugin::CLogPlugin(QWidget *parent): QDockWidget(parent) { m_ui.setupUi(this); + logMenu = NULL; } CLogPlugin::~CLogPlugin() @@ -63,6 +64,9 @@ namespace Plugin NLMISC::InfoLog->removeDisplayer(m_displayer); delete m_displayer; + delete logMenu; + logMenu = NULL; + delete m_libContext; m_libContext = NULL; } @@ -82,13 +86,13 @@ namespace Plugin Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - QMenu *viewMenu = menuManager->menu(Core::Constants::M_VIEW); QMainWindow *wnd = Core::ICore::instance()->mainWindow(); wnd->addDockWidget(Qt::RightDockWidgetArea, this); hide(); - viewMenu->addAction(this->toggleViewAction()); + logMenu = menuManager->menuBar()->addMenu( "Log" ); + logMenu->addAction(toggleViewAction()); } void CLogPlugin::setNelContext(NLMISC::INelContext *nelContext) diff --git a/code/studio/src/plugins/log/log_plugin.h b/code/studio/src/plugins/log/log_plugin.h index 2221195a8..9e4f64419 100644 --- a/code/studio/src/plugins/log/log_plugin.h +++ b/code/studio/src/plugins/log/log_plugin.h @@ -85,6 +85,8 @@ namespace Plugin NLQT::CQtDisplayer *m_displayer; + QMenu *logMenu; + }; } // namespace Plugin From 92cb5eea3af9c1d9f0c03401e0997716e0f5a7f6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:58:07 +0200 Subject: [PATCH 058/282] Updated qrc location. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/log/log_settings_page.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/log/log_settings_page.ui b/code/studio/src/plugins/log/log_settings_page.ui index 92faef8b6..09ead5c17 100644 --- a/code/studio/src/plugins/log/log_settings_page.ui +++ b/code/studio/src/plugins/log/log_settings_page.ui @@ -89,7 +89,7 @@ - + From fe7c3e4edfa1b750e029e92234355ff60a0e953c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 18:01:14 +0200 Subject: [PATCH 059/282] Rename log menu item. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/log/log_plugin.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp index 562b3bb6f..11da182a0 100644 --- a/code/studio/src/plugins/log/log_plugin.cpp +++ b/code/studio/src/plugins/log/log_plugin.cpp @@ -92,7 +92,9 @@ namespace Plugin hide(); logMenu = menuManager->menuBar()->addMenu( "Log" ); - logMenu->addAction(toggleViewAction()); + QAction *a = toggleViewAction(); + a->setText( tr( "View log" ) ); + logMenu->addAction( a ); } void CLogPlugin::setNelContext(NLMISC::INelContext *nelContext) From 2f023e0bdc24d6f9082d9ae061a988037130293c Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Tue, 10 Jun 2014 12:11:34 +0530 Subject: [PATCH 060/282] Database CREATE TABLE IF NOT EXISTS . ( --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/www/html/installer/libsetup.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index 5aea5c200..43b262b74 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -160,12 +160,16 @@ DROP TABLE IF EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ; CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ( - `PluginId` INT(10) NOT NULL AUTO_INCREMENT, - `PluginName` VARCHAR(11) NOT NULL, - `PluginPermission` VARCHAR(5) NOT NULL, - `PluginVersion` INT(11) NOT NULL, - `IsActive` TINYINT(1) NOT NULL, - PRIMARY KEY (`PluginId`) ) + `Id` INT(10) NOT NULL AUTO_INCREMENT, + `FileName VARCHAR(255) NOT NULL, + `Name` VARCHAR(11) NOT NULL, + `Type` VARCHAR(12) NOT NULL, + `Owner` VARCHAR(25) NOT NULL, + `Permission` VARCHAR(5) NOT NULL, + `Status` INT(11) NOT NULL DEFAULT 0, + `Weight` INT(11) NOT NULL DEFAULT 0, + `Info` BLOB NULL DEFAULT NULL, + PRIMARY KEY (`Id`) ) ENGINE = InnoDB; From c558b92bf57500733c8a46e4a95878b50a9e78d5 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Wed, 11 Jun 2014 11:52:57 +0530 Subject: [PATCH 061/282] plugin interaction files --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 356 ++++++------------ .../server/ryzom_ams/www/html/inc/plugins.php | 62 ++- 2 files changed, 150 insertions(+), 268 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index df3af960c..1b0dc873d 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -1,262 +1,150 @@ - setId($values['PluginId']); - - $this->setPluginName($values['PluginName']); - - $this->setPluginVersion($values['PluginVersion']); - - $this->setPluginPermission($values['PluginPermission']); - - $this->setIsActive($values['IsActive']); - - } - - - + * A constructor. + * Empty constructor + */ + + public function __construct() { + } + + public function set( $values ) { + $this -> setId( $values['Id'] ); + $this -> setPluginName( $values['Name'] ); + $this -> setPluginType( $values['Type'] ); + $this -> setPluginPermission( $values['Permission'] ); + $this -> setPluginStatus( $values['Status'] ); + $this -> setPluginInfo( $values['Info'] ); + } - /** - - * loads the object's attributes. - - */ - - public function load_With_SID( ) { - - $dbl = new DBLayer("lib"); - - $statement = $dbl->executeWithoutParams("SELECT * FROM plugins"); - - $row = $statement->fetch(); - - $this->set($row); - - } - + * loads the object's attributes. + */ + public function load_With_SID() { + $dbl = new DBLayer( "lib" ); + $statement = $dbl -> executeWithoutParams( "SELECT * FROM plugins" ); + $row = $statement -> fetch(); + $this -> set( $row ); + } - + /** + * get plugin id attribute of the object. + * + * @return integer id + */ + public function getId() { + return $this -> Id; + } - /** - - * updates the entry. - - */ - - public function update(){ - - $dbl = new DBLayer("lib"); - - $query = "UPDATE plugins SET PluginPermission= :t, PluginVersion = :q, IsActive = :d WHERE PluginName=:p_n"; - - $values = Array('p_n' => $this->getPluginName(), 't' => $this->getPluginPermission(), 'q' => $this->getPluginVersion(), 'd' => $this->getIsActive()); - - $statement = $dbl->execute($query, $values); - - } - + * get plugin permission attribute of the object. + */ + public function getPluginPermission() { + return $this -> plugin_permission; + } - + /** + * get plugin Type attribute of the object. + */ + public function getPluginType() { + return $this -> plugin_version; + } - - public function getId(){ - - return $this->Id; - - } - - - /** - - * get plugin permission attribute of the object. - - */ - - public function getPluginPermission(){ - - return $this->plugin_permission; - - } - + * get plugin status attribute of the object. + */ + public function getPluginStatus() { + return $this -> plugin_status; + } - /** - - * get plugin version attribute of the object. - - */ - - public function getPluginVersion(){ - - return $this->plugin_version; - - } - + * get plugin name attribute of the object. + */ + public function getPluginName() { + return $this -> plugin_name; + } - /** - - * get plugin is active attribute of the object. - - */ - - public function getIsActive(){ - - return $this->plugin_isactive; - - } - - - + * get plugin info array attribute of the object. + */ + public function getPluginInfo() { + return $this -> plugin_info; + } + /** - - * get plugin name attribute of the object. - - */ - - public function getPluginName(){ - - return $this->plugin_name; - - } - - - + * set plugin id attribute of the object. + * + * @param $s integer id + */ + public function setId( $s ) { + $this -> Id = $s; + } - + /** + * set plugin permission attribute of the object. + * + * @param $t type of the query, set permission + */ + public function setPluginPermission( $t ) { + $this -> plugin_permission = $t; + } - /** - - * set plugin id attribute of the object. - - * @param $s integer id - - */ - - public function setId($s){ - - $this->Id = $s; - - } - - - + * set plugin version attribute of the object. + * + * @param $q string to set plugin version + */ + public function setPluginType( $q ) { + $this -> plugin_version = $q; + } + /** - - * set plugin permission attribute of the object. - - * @param $t type of the query, set permission - - */ - - public function setPluginPermission($t){ - - - - $this->plugin_permission = $t; - - } - + * set plugin status attribute of the object. + * + * @param $d status code type int + */ + public function setPluginStatus( $d ) { + $this -> plugin_status = $d; + } - /** - - * set plugin version attribute of the object. - - * @param $q string to set plugin version - - */ - - public function setPluginVersion($q){ - - $this->plugin_version= $q; - - } - + * get plugin name attribute of the object. + */ + public function getPluginName() { + return $this -> plugin_name; + } - /** - - * set plugin is active attribute of the object. - - * @param $d tinyint to set plugin is active or not . - - */ - - public function setIsActive($d){ - - $this->plugin_isactive= $d; - - } - - - + * set plugin name attribute of the object. + * + * @param $p_n string to set plugin name. + */ + public function setPluginName( $p_n ) { + $this -> plugin_name = $p_n; + } + /** - - * set plugin name attribute of the object. - - * @param $p_n string to set plugin name. - - */ - - public function setPluginName($p_n){ - - $this->plugin_name= $p_n; - - } - + * set plugin info attribute array of the object. + * + * @param $p_n array + */ + public function setPluginInfo( $p_n ) { + $this -> plugin_info = $p_n; + } - -} - - + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php b/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php index 61bdb0278..1118b556f 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins.php @@ -1,45 +1,39 @@ init(); - print_r(plugin::$plugins);**/ - - $pagination = new Pagination("SELECT * FROM plugins","lib",5,"Plugincache"); - $pageResult['plug']= Gui_Elements::make_table($pagination->getElements() , Array ("getId","getPluginName","getPluginVersion","getPluginPermission","getIsActive"), Array("id","plugin_name","plugin_version","plugin_permission","plugin_isactive")); - $pageResult['links'] = $pagination->getLinks(5); - $pageResult['lastPage'] = $pagination->getLast(); - $pageResult['currentPage'] = $pagination->getCurrent(); + { + if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) { + + $pagination = new Pagination( "SELECT * FROM plugins", "lib", 5, "Plugincache" ); + $pageResult['plug'] = Gui_Elements :: make_table( $pagination -> getElements(), Array( "getId", "getPluginName", "getPluginType", "getPluginPermission", "getPluginStatus", "getPluginInfo" ), Array( "id", "plugin_name", "plugin_type", "plugin_permission", "plugin_status", "plugin_info" ) ); + $pageResult['links'] = $pagination -> getLinks( 5 ); + $pageResult['lastPage'] = $pagination -> getLast(); + $pageResult['currentPage'] = $pagination -> getCurrent(); - global $INGAME_WEBPATH; - $pageResult['ingame_webpath'] = $INGAME_WEBPATH; + global $INGAME_WEBPATH; + $pageResult['ingame_webpath'] = $INGAME_WEBPATH; - //check if shard is online - try{ - $dbs = new DBLayer("shard"); - $pageResult['shard'] = "online"; - }catch(PDOException $e){ + // check if shard is online + try { + $dbs = new DBLayer( "shard" ); + $pageResult['shard'] = "online"; + } + catch( PDOException $e ) { $pageResult['shard'] = "offline"; - } - return( $pageResult); - }else{ - //ERROR: No access! + } + return( $pageResult ); + } else { + // ERROR: No access! $_SESSION['error_code'] = "403"; - header("Location: index.php?page=error"); - exit; + header( "Location: index.php?page=error" ); + exit; + } + } - -} - - From a15462c863fb2c761cbf521e46d1c21ac6020f53 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Wed, 11 Jun 2014 15:57:07 +0530 Subject: [PATCH 062/282] plugin installer functionality --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 13 +- .../ryzom_ams/ams_lib/translations/en.ini | 21 +- .../www/html/func/install_plugin.php | 94 ++++++++ .../tools/server/ryzom_ams/www/html/index.php | 208 +++++++++--------- .../ryzom_ams/www/html/installer/libsetup.php | 6 +- .../www/html/templates/install_plugin.tpl | 34 +++ .../ryzom_ams/www/html/templates/plugins.tpl | 67 ++---- 7 files changed, 274 insertions(+), 169 deletions(-) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index 1b0dc873d..bba6e3fb1 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -2,7 +2,7 @@ /** * API for loading and interacting with plugins - * contains getters and setters + * contains getters and setters * * @author shubham meena mentored by Matthew Lagoe */ @@ -29,7 +29,7 @@ class Plugincache { $this -> setPluginType( $values['Type'] ); $this -> setPluginPermission( $values['Permission'] ); $this -> setPluginStatus( $values['Status'] ); - $this -> setPluginInfo( $values['Info'] ); + $this -> setPluginInfo( json_decode( $values['Info'] ) ); } /** @@ -122,13 +122,6 @@ class Plugincache { $this -> plugin_status = $d; } - /** - * get plugin name attribute of the object. - */ - public function getPluginName() { - return $this -> plugin_name; - } - /** * set plugin name attribute of the object. * @@ -147,4 +140,4 @@ class Plugincache { $this -> plugin_info = $p_n; } - } + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini index 0d1b9cfb6..0164abbee 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini @@ -56,12 +56,21 @@ action = "Action" [plugins] plugin_title = "Plugin List" plugin_info = "Here you can see the entire list of plugins . You can easily remove plugins ,activate them and add permissions" -plugins= "Plugins" -plugin_id = "ID" +plugins = "Plugins" plugin_name = "Name" -plugin_version= "Version" -plugin_permission= "Owner/Access Permission" -plugin_is_active= "On/Off" +plugin_version = "Version" +plugin_description = "Description" +plugin_type = "Type" +plugin_permission = "Access Permission" +plugin_status = "Status" +ip_success = "Plugin added succesfully." + +[install_plugin] +ip_title = "Install a new Plugin" +ip_message = "For example: name.zip from your local computer" +ip_support = "Upload the plugin archieve to install.
The following file extension is supported: zip." +ip_error = "Please select the format with zip extension" +ip_info_nfound = "Info file not found in the Plugin.Please recheck" [show_ticket] t_title = "Ticket" @@ -252,4 +261,4 @@ email_body_forgot_password_header = "A request to reset your account's password email_body_forgot_password_footer = " ---------- If you didn't make this request, please ignore this message." -;=========================================================================== \ No newline at end of file +;=========================================================================== diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php new file mode 100644 index 000000000..64cb66a30 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php @@ -0,0 +1,94 @@ + 0 ) && ( $_FILES["file"]["type"] == 'application/zip' ) ) + { + $fileName = $_FILES["file"]["name"]; //the files name takes from the HTML form + $fileTmpLoc = $_FILES["file"]["tmp_name"]; //file in the PHP tmp folder + $dir = trim( $_FILES["file"]["name"], ".zip" ); + $target_path = "../../ams_lib/plugins/$dir"; //path in which the zip extraction is to be done + $destination = "../../ams_lib/plugins/"; + + if ( move_uploaded_file( $fileTmpLoc, $destination . $fileName ) ) { + // zip object to handle zip archieves + $zip = new ZipArchive(); + $x = $zip -> open( $destination . $fileName ); + if ( $x === true ) { + $zip -> extractTo( $destination ); // change this to the correct site path + $zip -> close(); + + // removing the uploaded zip file + unlink( $destination . $fileName ); + + // check for the info file + if ( file_exists( $target_path . "/.info" ) ) + { + // read the details of the plugin through the info file + $file_handle = fopen( $target_path . "/.info", "r" ); + $result = array(); + while ( !feof( $file_handle ) ) { + + $line_of_text = fgets( $file_handle ); + $parts = array_map( 'trim', explode( '=', $line_of_text, 2 ) ); + @$result[$parts[0]] = $parts[1]; + + } + + fclose( $file_handle ); + + // sending all info to the database + $install_result = array(); + $install_result['FileName'] = $target_path; + $install_result['Name'] = $result['PluginName']; + $install_result['Type'] = $result['type']; + + if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) + { + $install_result['Permission'] = 'admin'; + } + else + { + $install_result['Permission'] = 'user'; + } + + $install_result['Info'] = json_encode( $result ); + + // connection with the database + $dbr = new DBLayer( "lib" ); + $dbr -> insert( "plugins", $install_result ); + + header( "Location: index.php?page=plugins&result=1" ); + exit; + + } + else + { + rmdir( $target_path ); + header( "Location: index.php?page=install_plugin&result=2" ); + exit; + + } + + } + } + + header( "Location: index.php?page=plugins" ); + exit; + } + else + { + header( "Location: index.php?page=install_plugin&result=1" ); + exit; + } + } + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/index.php b/code/ryzom/tools/server/ryzom_ams/www/html/index.php index faf3488c6..f01eab3e4 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/index.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/index.php @@ -1,126 +1,130 @@ getPermission(); -}else{ - //default permission - $return['permission'] = 0; -} -//hide sidebar + topbar in case of login/register -if($page == 'login' || $page == 'register' || $page == 'logout' || $page == 'forgot_password' || $page == 'reset_password'){ - $return['no_visible_elements'] = 'TRUE'; -}else{ - $return['no_visible_elements'] = 'FALSE'; -} +// Set permission +if ( isset( $_SESSION['ticket_user'] ) ) { + $return['permission'] = unserialize( $_SESSION['ticket_user'] ) -> getPermission(); + } else { + // default permission + $return['permission'] = 0; + } + + +// hide sidebar + topbar in case of login/register +if ( $page == 'login' || $page == 'register' || $page == 'logout' || $page == 'forgot_password' || $page == 'reset_password' ) { + $return['no_visible_elements'] = 'TRUE'; + } else { + $return['no_visible_elements'] = 'FALSE'; + } -//handle error page -if($page == 'error'){ - $return['permission'] = 0; +// handle error page +if ( $page == 'error' ) { + $return['permission'] = 0; $return['no_visible_elements'] = 'FALSE'; -} + } -//load the template with the variables in the $return array +// load the template with the variables in the $return array helpers :: loadTemplate( $page , $return ); diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index 43b262b74..a590e6d7d 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -160,15 +160,15 @@ DROP TABLE IF EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ; CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ( - `Id` INT(10) NOT NULL AUTO_INCREMENT, - `FileName VARCHAR(255) NOT NULL, + `Id` INT(10) NOT NULL AUTO_INCREMENT, + `FileName VARCHAR(255) NOT NULL, `Name` VARCHAR(11) NOT NULL, `Type` VARCHAR(12) NOT NULL, `Owner` VARCHAR(25) NOT NULL, `Permission` VARCHAR(5) NOT NULL, `Status` INT(11) NOT NULL DEFAULT 0, `Weight` INT(11) NOT NULL DEFAULT 0, - `Info` BLOB NULL DEFAULT NULL, + `Info` TEXT NULL DEFAULT NULL, PRIMARY KEY (`Id`) ) ENGINE = InnoDB; diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl new file mode 100644 index 000000000..52fdb3820 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl @@ -0,0 +1,34 @@ +{block name=content} + +

+
+ +
+
+

{$ip_support}

+
+
+    +
+ {if isset($smarty.get.result) and $smarty.get.result eq "1"}

{$ip_error}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "2"}

{$ip_info_nfound}

{/if} +
+
+ {$ip_message} +
+
+
+
+
+ + + +{/block} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl index 4d4703875..99f382c5c 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl @@ -1,4 +1,3 @@ - {block name=content}
@@ -10,27 +9,35 @@
+ {if isset($smarty.get.result) and $smarty.get.result eq "1"}

{$ip_success}

{/if}

{$plugin_info}

- +
+ + + + +
- - - + + - + + + {foreach from=$plug item=element} - - + - - + + + + {/foreach} @@ -48,42 +55,6 @@ -
-
-

Actions

-
- - -
-
-
-
-
- - -
-
-
-
- -{/block} \ No newline at end of file +{/block} + From ad2ed4dfa4c42d15e614c5fe2c84c7b5edf56ee3 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Fri, 13 Jun 2014 16:40:27 +0530 Subject: [PATCH 063/282] Plugin installation first upload t{block name=content} --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/translations/en.ini | 13 +- .../www/html/func/install_plugin.php | 150 +++++++++++++----- .../www/html/templates/install_plugin.tpl | 9 +- .../ryzom_ams/www/html/templates/layout.tpl | 44 +++++ .../ryzom_ams/www/html/templates/plugins.tpl | 26 +-- 5 files changed, 189 insertions(+), 53 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini index 0164abbee..4c8b545ec 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini @@ -61,16 +61,23 @@ plugin_name = "Name" plugin_version = "Version" plugin_description = "Description" plugin_type = "Type" -plugin_permission = "Access Permission" +plugin_permission = "Access
Permission" plugin_status = "Status" -ip_success = "Plugin added succesfully." +ip_success = "Plugin added succesfuly." +plugin_actions = "Actions" +dp_success = "Plugin deleted successfuly" +dp_error = "Error in deleting plugin.Please try again later" +ac_success = "Plugin Activated successfuly" +ac_error = "Plugin facing some error in activating. Please try again later" +dc_success = "Plugin de-Activated successfuly" +dc_error = "Plugin facing some error in de-activating. Please try again later" [install_plugin] ip_title = "Install a new Plugin" ip_message = "For example: name.zip from your local computer" ip_support = "Upload the plugin archieve to install.
The following file extension is supported: zip." -ip_error = "Please select the format with zip extension" ip_info_nfound = "Info file not found in the Plugin.Please recheck" +ip_file_nfnd="Please upload a plugin before clicking on install button" [show_ticket] t_title = "Ticket" diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php index 64cb66a30..5376dfd02 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php @@ -11,7 +11,18 @@ function install_plugin() { // if logged in if ( WebUsers :: isLoggedIn() ) { - if ( ( isset( $_FILES["file"] ) ) && ( $_FILES["file"]["size"] > 0 ) && ( $_FILES["file"]["type"] == 'application/zip' ) ) + // path of temporary folder for storing files + $temp_path = "../../ams_lib/temp"; + + // create a temp directory if not exist + // temp folder where we first store all uploaded plugins before install + if ( !file_exists( "$temp_path" ) ) + { + mkdir( $temp_path ); + } + + // checking the server if file is uploaded or not + if ( ( isset( $_FILES["file"] ) ) && ( $_FILES["file"]["size"] > 0 ) ) { $fileName = $_FILES["file"]["name"]; //the files name takes from the HTML form $fileTmpLoc = $_FILES["file"]["tmp_name"]; //file in the PHP tmp folder @@ -19,40 +30,44 @@ function install_plugin() { $target_path = "../../ams_lib/plugins/$dir"; //path in which the zip extraction is to be done $destination = "../../ams_lib/plugins/"; - if ( move_uploaded_file( $fileTmpLoc, $destination . $fileName ) ) { - // zip object to handle zip archieves - $zip = new ZipArchive(); - $x = $zip -> open( $destination . $fileName ); - if ( $x === true ) { - $zip -> extractTo( $destination ); // change this to the correct site path - $zip -> close(); - - // removing the uploaded zip file - unlink( $destination . $fileName ); - - // check for the info file + // checking for the command to install plugin is given or not + if ( !isset( $_POST['install_plugin'] ) ) + { + if ( ( $_FILES["file"]["type"] == 'application/zip' ) ) + { + if ( move_uploaded_file( $fileTmpLoc, $temp_path . "/" . $fileName ) ) { + echo "$fileName upload is complete."; + exit(); + } + else + { + echo "Error in uploading file."; + exit(); + } + } + else + { + echo "Please select a file with .zip extension to upload."; + exit(); + } + } + else + { + + // calling function to unzip archives + if ( zipExtraction( $temp_path . "/" . $fileName , $destination ) ) + { if ( file_exists( $target_path . "/.info" ) ) { - // read the details of the plugin through the info file - $file_handle = fopen( $target_path . "/.info", "r" ); - $result = array(); - while ( !feof( $file_handle ) ) { - - $line_of_text = fgets( $file_handle ); - $parts = array_map( 'trim', explode( '=', $line_of_text, 2 ) ); - @$result[$parts[0]] = $parts[1]; - - } - - fclose( $file_handle ); + $result = array(); + $result = readPluginFile( ".info", $target_path ); // sending all info to the database $install_result = array(); $install_result['FileName'] = $target_path; $install_result['Name'] = $result['PluginName']; - $install_result['Type'] = $result['type']; - - if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) + // $install_result['Type'] = $result['type']; + if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) { $install_result['Permission'] = 'admin'; } @@ -67,28 +82,87 @@ function install_plugin() { $dbr = new DBLayer( "lib" ); $dbr -> insert( "plugins", $install_result ); - header( "Location: index.php?page=plugins&result=1" ); + // if everything is successfull redirecting to the plugin template + header( "Location: index.php?page=plugins&result=1" ); exit; - } else { + // file .info not exists rmdir( $target_path ); header( "Location: index.php?page=install_plugin&result=2" ); exit; - } - } + } else + { + // extraction failed + header( "Location: index.php?page=install_plugin&result=0" ); + exit; + } } - - header( "Location: index.php?page=plugins" ); - exit; + } + else + { + echo "Please Browse for a file before clicking the upload button"; + exit(); + } + } + } + +/** + * function to unzip the zipped files + * + * @param $target_path path to the target zipped file + * @param $destination path to the destination + * @return boolean + */ +function zipExtraction( $target_path, $destination ) + { + $zip = new ZipArchive(); + $x = $zip -> open( $target_path ); + if ( $x === true ) { + if ( $zip -> extractTo( $destination ) ) + { + $zip -> close(); + return true; } else { - header( "Location: index.php?page=install_plugin&result=1" ); - exit; + $zip -> close(); + return false; } } - } + } + +/** + * function to read text files and extract + * the information into an array + * + * ----------------------------------------------------------- + * format: + * ----------------------------------------------------------- + * PluginName = Name of the plugin + * Version = version of the plugin + * Type = type of the plugin + * Description = Description of the plugin ,it's functionality + * ----------------------------------------------------------- + * + * reads only files with name .info + * + * @param $fileName file to read + * @param $targetPath path to the folder containing .info file + * @return array containing above information in array(value => key) + */ +function readPluginFile( $fileName, $target_path ) + { + $file_handle = fopen( $target_path . "/" . $fileName, "r" ); + $result = array(); + while ( !feof( $file_handle ) ) { + $line_of_text = fgets( $file_handle ); + $parts = array_map( 'trim', explode( '=', $line_of_text, 2 ) ); + @$result[$parts[0]] = $parts[1]; + } + fclose( $file_handle ); + return $result; + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl index 52fdb3820..27a4cec49 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl @@ -15,12 +15,15 @@

{$ip_support}

- +   
- {if isset($smarty.get.result) and $smarty.get.result eq "1"}

{$ip_error}

{/if} +
+
+

+ {if isset($smarty.get.result) and $smarty.get.result eq "0"}

{$ip_file_nfnd}

{/if} {if isset($smarty.get.result) and $smarty.get.result eq "2"}

{$ip_info_nfound}

{/if} -
+
{$ip_message}
diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl index fa97211d7..e66d952b8 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl @@ -192,6 +192,50 @@ } + + + diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl index 99f382c5c..cac67147a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl @@ -10,23 +10,28 @@ {if isset($smarty.get.result) and $smarty.get.result eq "1"}

{$ip_success}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "0"}

{$dp_error}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "2"}

{$dp_success}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "3"}

{$ac_success}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "4"}

{$ac_error}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "5"}

{$dc_success}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "6"}

{$dc_error}

{/if}
{$plugin_id}{$plugin_permission}{$plugin_name}{$plugin_status}{$plugin_name} {$plugin_version}{$plugin_is_active}{$plugin_description}{$plugin_type}{$plugin_permission}
{$element.id}{$element.plugin_permission} {$element.plugin_name}{$element.plugin_version}{$element.plugin_isactive}{$element.plugin_info->Version}{$element.plugin_info->Description}{$element.plugin_type}{$element.plugin_permission}
- + - - + + + @@ -38,6 +43,9 @@ + {/foreach} From 59a6c6b8c3d868443ba2ad8b4acb849244a29ad0 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Fri, 13 Jun 2014 17:21:49 +0530 Subject: [PATCH 064/282] deleting plugin from ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/www/html/func/delete_plugin.php | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php new file mode 100644 index 000000000..53af36157 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php @@ -0,0 +1,68 @@ + selectWithParameter( "FileName", "plugins", array( 'id' => $id ), "Id=:id" ); + $name = $sth -> fetch(); + + if ( is_dir( "$name[FileName]" ) ) + { + // removing plugin directory from the code base + if ( rrmdir( "$name[FileName]" ) ) + { + $db -> delete( 'plugins', array( 'id' => $id ), "Id=:id" ); + + header( "Location: index.php?page=plugins&result=2" ); + exit; + + } + else + { + header( "Location: index.php?page=plugins&result=0" ); + exit; + } + } + } + else + { + header( "Location: index.php?page=plugins&result=0" ); + exit; + } + } + } + +/** + * function to remove a non empty directory + * + * @param $dir directory address + * @return boolean + */ +function rrmdir( $dir ) { + if ( is_dir( $dir ) ) { + $objects = scandir( $dir ); + foreach ( $objects as $object ) { + if ( $object != "." && $object != ".." ) { + if ( filetype( $dir . "/" . $object ) == "dir" ) rmdir( $dir . "/" . $object ); + else unlink( $dir . "/" . $object ); + } + } + reset( $objects ); + return rmdir( $dir ); + } + } + From c692b168d70fb362ad4877d6102ddb49cb5fc808 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 17:28:33 +0200 Subject: [PATCH 065/282] Split Nel3DWidget and NelGUIWidget. --HG-- branch : gsoc2014-dfighter --- .../plugins/gui_editor/gui_editor_window.cpp | 2 +- .../src/plugins/gui_editor/nelgui_widget.cpp | 32 ++++++++++++------- .../src/plugins/gui_editor/nelgui_widget.h | 10 ++++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index e48a37ba6..923db1016 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -66,7 +66,7 @@ namespace GUIEditor addWidgetWidget = new AddWidgetWidget; connect( projectWindow, SIGNAL( projectFilesChanged() ), this, SLOT( onProjectFilesChanged() ) ); viewPort = new NelGUIWidget; - setCentralWidget( viewPort ); + setCentralWidget( viewPort->getViewPort() ); widgetInfoTree = new CWidgetInfoTree; diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index d86d31269..f8e34da3b 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -29,16 +29,19 @@ #include #include "editor_selection_watcher.h" +#include "nel3d_widget.h" + namespace GUIEditor { std::set< std::string > hwCursors; NelGUIWidget::NelGUIWidget( QWidget *parent ) : - Nel3DWidget( parent ) + QWidget( parent ) { timerID = 0; guiLoaded = false; watcher = NULL; + w = new Nel3DWidget(); } NelGUIWidget::~NelGUIWidget() @@ -49,7 +52,9 @@ namespace GUIEditor NLGUI::CViewRenderer::release(); NLMISC::CI18N::setNoResolution( false ); - + + delete w; + w = NULL; } void NelGUIWidget::init() @@ -59,15 +64,15 @@ namespace GUIEditor NLMISC::CPath::remapExtension( "dds", "png", true ); NLMISC::CPath::remapExtension( "png", "tga", true ); - Nel3DWidget::init(); - createTextContext( "Ryzom.ttf" ); + w->init(); + w->createTextContext( "Ryzom.ttf" ); NLGUI::CAHManager::setEditorMode( true ); NLGUI::CLuaManager::setEditorMode( true ); NLGUI::CInterfaceElement::setEditorMode( true ); - NLGUI::CViewRenderer::setDriver( getDriver() ); - NLGUI::CViewRenderer::setTextContext( getTextContext() ); + NLGUI::CViewRenderer::setDriver( w->getDriver() ); + NLGUI::CViewRenderer::setTextContext( w->getTextContext() ); NLGUI::CViewRenderer::hwCursors = &hwCursors; NLGUI::CViewRenderer::getInstance()->init(); @@ -125,21 +130,21 @@ namespace GUIEditor CWidgetManager::getInstance()->reset(); CWidgetManager::getInstance()->getParser()->removeAll(); CViewRenderer::getInstance()->reset(); - clear(); + w->clear(); } void NelGUIWidget::draw() { - getDriver()->clearBuffers( NLMISC::CRGBA::Black ); + w->getDriver()->clearBuffers( NLMISC::CRGBA::Black ); CWidgetManager::getInstance()->checkCoords(); CWidgetManager::getInstance()->drawViews( 0 ); - getDriver()->swapBuffers(); + w->getDriver()->swapBuffers(); } void NelGUIWidget::paintEvent( QPaintEvent *evnt ) { if( !guiLoaded ) - clear(); + w->clear(); } void NelGUIWidget::timerEvent( QTimerEvent *evnt ) @@ -148,7 +153,7 @@ namespace GUIEditor { if( guiLoaded ) { - getDriver()->EventServer.pump(); + w->getDriver()->EventServer.pump(); draw(); } } @@ -165,5 +170,10 @@ namespace GUIEditor if( timerID != 0 ) killTimer( timerID ); } + + QWidget* NelGUIWidget::getViewPort() + { + return w; + } } diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h index 34c510507..a1412257c 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.h +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.h @@ -18,15 +18,16 @@ #ifndef NELGUI_WIDGET_H #define NELGUI_WIDGET_H -#include "nel3d_widget.h" +#include #include "project_files.h" namespace GUIEditor { class CEditorSelectionWatcher; + class Nel3DWidget; /// Qt viewport for the Nel GUI library - class NelGUIWidget : public Nel3DWidget + class NelGUIWidget : public QWidget { Q_OBJECT public: @@ -39,6 +40,8 @@ namespace GUIEditor void reset(); CEditorSelectionWatcher* getWatcher(){ return watcher; } + QWidget* getViewPort(); + Q_SIGNALS: void guiLoadComplete(); @@ -53,6 +56,9 @@ Q_SIGNALS: int timerID; bool guiLoaded; CEditorSelectionWatcher *watcher; + + + Nel3DWidget *w; }; } From 9d9cd463b08a2fc40f8ba0dd34a81385c81374ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:31:50 +0200 Subject: [PATCH 066/282] GUI Editor main window will now send the show/hide events to NelGUIWidget. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/gui_editor_window.cpp | 14 ++++++++++++++ .../src/plugins/gui_editor/gui_editor_window.h | 4 ++++ .../src/plugins/gui_editor/nelgui_widget.cpp | 4 ++-- code/studio/src/plugins/gui_editor/nelgui_widget.h | 6 +++--- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 923db1016..1d4050412 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -340,6 +340,20 @@ namespace GUIEditor addWidgetWidget->setupWidgetInfo( widgetInfoTree ); } + + + void GUIEditorWindow::hideEvent( QHideEvent *evnt ) + { + QWidget::hideEvent( evnt ); + viewPort->hide(); + } + + void GUIEditorWindow::showEvent( QShowEvent *evnt ) + { + QWidget::showEvent( evnt ); + viewPort->show(); + } + void GUIEditorWindow::createMenus() { Core::MenuManager *mm = Core::ICore::instance()->menuManager(); diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 1362e4671..6434b07d6 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -66,6 +66,10 @@ private Q_SLOTS: void onAddWidgetClicked(); void onTreeChanged(); +protected: + void hideEvent( QHideEvent *evnt ); + void showEvent( QShowEvent *evnt ); + private: void createMenus(); void removeMenus(); diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index f8e34da3b..e6a056390 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -159,13 +159,13 @@ namespace GUIEditor } } - void NelGUIWidget::showEvent( QShowEvent *evnt ) + void NelGUIWidget::show() { if( timerID == 0 ) timerID = startTimer( 200 ); } - void NelGUIWidget::hideEvent( QHideEvent *evnt ) + void NelGUIWidget::hide() { if( timerID != 0 ) killTimer( timerID ); diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h index a1412257c..dacee1668 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.h +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.h @@ -42,15 +42,15 @@ namespace GUIEditor QWidget* getViewPort(); + void show(); + void hide(); + Q_SIGNALS: void guiLoadComplete(); protected: void paintEvent( QPaintEvent *evnt ); void timerEvent( QTimerEvent *evnt ); - void showEvent( QShowEvent *evnt ); - void hideEvent( QHideEvent *evnt ); - private: int timerID; From 1457469dfe5f196d794cbb128bdb883451fbf70d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:32:27 +0200 Subject: [PATCH 067/282] TimerId should be set to 0 when hiding. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/nelgui_widget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index e6a056390..812e002df 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -168,7 +168,10 @@ namespace GUIEditor void NelGUIWidget::hide() { if( timerID != 0 ) + { killTimer( timerID ); + timerID = 0; + } } QWidget* NelGUIWidget::getViewPort() From 676587559b5c33f6fb68111119734eae3ab399f4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:44:57 +0200 Subject: [PATCH 068/282] Renamed NelGUIWidget to NelGUICtrl, and changed it's base class from QWidget to QObject. --HG-- branch : gsoc2014-dfighter --- .../plugins/gui_editor/gui_editor_window.cpp | 26 ++++++++--------- .../plugins/gui_editor/gui_editor_window.h | 4 +-- .../src/plugins/gui_editor/nelgui_widget.cpp | 28 ++++++++----------- .../src/plugins/gui_editor/nelgui_widget.h | 13 +++++---- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 1d4050412..236ff93a2 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -65,8 +65,8 @@ namespace GUIEditor projectWindow = new ProjectWindow; addWidgetWidget = new AddWidgetWidget; connect( projectWindow, SIGNAL( projectFilesChanged() ), this, SLOT( onProjectFilesChanged() ) ); - viewPort = new NelGUIWidget; - setCentralWidget( viewPort->getViewPort() ); + GUICtrl = new NelGUICtrl(); + setCentralWidget( GUICtrl->getViewPort() ); widgetInfoTree = new CWidgetInfoTree; @@ -97,9 +97,9 @@ namespace GUIEditor dock->setWidget( propBrowser ); addDockWidget( Qt::RightDockWidgetArea, dock ); - viewPort->init(); + GUICtrl->init(); - connect( viewPort, SIGNAL( guiLoadComplete() ), this, SLOT( onGUILoaded() ) ); + connect( GUICtrl, SIGNAL( guiLoadComplete() ), this, SLOT( onGUILoaded() ) ); connect( widgetProps, SIGNAL( treeChanged() ), this, SLOT( onTreeChanged() ) ); connect( addWidgetWidget, @@ -130,8 +130,8 @@ namespace GUIEditor delete projectWindow; projectWindow = NULL; - delete viewPort; - viewPort = NULL; + delete GUICtrl; + GUICtrl = NULL; delete addWidgetWidget; addWidgetWidget = NULL; @@ -181,7 +181,7 @@ namespace GUIEditor currentProject = projectFiles.projectName.c_str(); currentProjectFile = fileName; projectWindow->setupFiles( projectFiles ); - if( viewPort->parse( projectFiles ) ) + if( GUICtrl->parse( projectFiles ) ) { hierarchyView->buildHierarchy( projectFiles.masterGroup ); } @@ -282,14 +282,14 @@ namespace GUIEditor return false; - CEditorSelectionWatcher *w = viewPort->getWatcher(); + CEditorSelectionWatcher *w = GUICtrl->getWatcher(); disconnect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), hierarchyView, SLOT( onSelectionChanged( std::string& ) ) ); disconnect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), &browserCtrl, SLOT( onSelectionChanged( std::string& ) ) ); projectFiles.clearAll(); projectWindow->clear(); hierarchyView->clearHierarchy(); - viewPort->reset(); + GUICtrl->reset(); browserCtrl.clear(); linkList->clear(); procList->clear(); @@ -305,7 +305,7 @@ namespace GUIEditor setCursor( Qt::WaitCursor ); projectWindow->updateFiles( projectFiles ); - if( !viewPort->parse( projectFiles ) ) + if( !GUICtrl->parse( projectFiles ) ) { QMessageBox::critical( this, tr( "Error parsing GUI XML files" ), @@ -321,7 +321,7 @@ namespace GUIEditor procList->onGUILoaded(); linkList->onGUILoaded(); - CEditorSelectionWatcher *w = viewPort->getWatcher(); + CEditorSelectionWatcher *w = GUICtrl->getWatcher(); connect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), hierarchyView, SLOT( onSelectionChanged( std::string& ) ) ); connect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), &browserCtrl, SLOT( onSelectionChanged( std::string& ) ) ); } @@ -345,13 +345,13 @@ namespace GUIEditor void GUIEditorWindow::hideEvent( QHideEvent *evnt ) { QWidget::hideEvent( evnt ); - viewPort->hide(); + GUICtrl->hide(); } void GUIEditorWindow::showEvent( QShowEvent *evnt ) { QWidget::showEvent( evnt ); - viewPort->show(); + GUICtrl->show(); } void GUIEditorWindow::createMenus() diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 6434b07d6..517186739 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -36,7 +36,7 @@ namespace GUIEditor class LinkList; class ProcList; class ProjectWindow; - class NelGUIWidget; + class NelGUICtrl; class CWidgetInfoTree; class CEditorMessageProcessor; class AddWidgetWidget; @@ -87,7 +87,7 @@ private: LinkList *linkList; ProcList *procList; ProjectWindow *projectWindow; - NelGUIWidget *viewPort; + NelGUICtrl *GUICtrl; CWidgetInfoTree *widgetInfoTree; CEditorMessageProcessor *messageProcessor; AddWidgetWidget *addWidgetWidget; diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index 812e002df..6fc9db7e3 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -35,8 +35,8 @@ namespace GUIEditor { std::set< std::string > hwCursors; - NelGUIWidget::NelGUIWidget( QWidget *parent ) : - QWidget( parent ) + NelGUICtrl::NelGUICtrl( QObject *parent ) : + QObject( parent ) { timerID = 0; guiLoaded = false; @@ -44,7 +44,7 @@ namespace GUIEditor w = new Nel3DWidget(); } - NelGUIWidget::~NelGUIWidget() + NelGUICtrl::~NelGUICtrl() { guiLoaded = false; if( timerID != 0 ) @@ -57,7 +57,7 @@ namespace GUIEditor w = NULL; } - void NelGUIWidget::init() + void NelGUICtrl::init() { NLMISC::CI18N::setNoResolution( true ); NLMISC::CPath::remapExtension( "dds", "tga", true ); @@ -81,7 +81,7 @@ namespace GUIEditor watcher = new CEditorSelectionWatcher(); } - bool NelGUIWidget::parse( SProjectFiles &files ) + bool NelGUICtrl::parse( SProjectFiles &files ) { reset(); IParser *parser = CWidgetManager::getInstance()->getParser(); @@ -120,7 +120,7 @@ namespace GUIEditor return true; } - void NelGUIWidget::reset() + void NelGUICtrl::reset() { guiLoaded = false; if( timerID != 0 ) @@ -133,7 +133,7 @@ namespace GUIEditor w->clear(); } - void NelGUIWidget::draw() + void NelGUICtrl::draw() { w->getDriver()->clearBuffers( NLMISC::CRGBA::Black ); CWidgetManager::getInstance()->checkCoords(); @@ -141,13 +141,7 @@ namespace GUIEditor w->getDriver()->swapBuffers(); } - void NelGUIWidget::paintEvent( QPaintEvent *evnt ) - { - if( !guiLoaded ) - w->clear(); - } - - void NelGUIWidget::timerEvent( QTimerEvent *evnt ) + void NelGUICtrl::timerEvent( QTimerEvent *evnt ) { if( evnt->timerId() == timerID ) { @@ -159,13 +153,13 @@ namespace GUIEditor } } - void NelGUIWidget::show() + void NelGUICtrl::show() { if( timerID == 0 ) timerID = startTimer( 200 ); } - void NelGUIWidget::hide() + void NelGUICtrl::hide() { if( timerID != 0 ) { @@ -174,7 +168,7 @@ namespace GUIEditor } } - QWidget* NelGUIWidget::getViewPort() + QWidget* NelGUICtrl::getViewPort() { return w; } diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h index dacee1668..38da599e4 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.h +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.h @@ -18,21 +18,23 @@ #ifndef NELGUI_WIDGET_H #define NELGUI_WIDGET_H -#include +#include #include "project_files.h" +class QWidget; + namespace GUIEditor { class CEditorSelectionWatcher; class Nel3DWidget; - /// Qt viewport for the Nel GUI library - class NelGUIWidget : public QWidget + /// Qt viewport controller for the Nel GUI library + class NelGUICtrl : public QObject { Q_OBJECT public: - NelGUIWidget( QWidget *parent = NULL ); - ~NelGUIWidget(); + NelGUICtrl( QObject *parent = NULL ); + ~NelGUICtrl(); void init(); bool parse( SProjectFiles &files ); @@ -49,7 +51,6 @@ Q_SIGNALS: void guiLoadComplete(); protected: - void paintEvent( QPaintEvent *evnt ); void timerEvent( QTimerEvent *evnt ); private: From 59b4735d96e4cdab5e5f533403a56824d28fd33d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 19:37:42 +0200 Subject: [PATCH 069/282] Renamed nelgui_widget.* to nelgui_ctrl.* --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/CMakeLists.txt | 2 +- code/studio/src/plugins/gui_editor/gui_editor_window.cpp | 2 +- .../plugins/gui_editor/{nelgui_widget.cpp => nelgui_ctrl.cpp} | 2 +- .../src/plugins/gui_editor/{nelgui_widget.h => nelgui_ctrl.h} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename code/studio/src/plugins/gui_editor/{nelgui_widget.cpp => nelgui_ctrl.cpp} (99%) rename code/studio/src/plugins/gui_editor/{nelgui_widget.h => nelgui_ctrl.h} (100%) diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index ff248a261..2ea82a6e4 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -25,7 +25,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR property_browser_ctrl.h project_window.h nel3d_widget.h - nelgui_widget.h + nelgui_ctrl.h new_property_widget.h new_widget_widget.h add_widget_widget.h diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 236ff93a2..4f66b61fc 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -40,7 +40,7 @@ #include "project_file_parser.h" #include "project_file_serializer.h" #include "project_window.h" -#include "nelgui_widget.h" +#include "nelgui_ctrl.h" #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp similarity index 99% rename from code/studio/src/plugins/gui_editor/nelgui_widget.cpp rename to code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 6fc9db7e3..2a9a433ee 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . -#include "nelgui_widget.h" +#include "nelgui_ctrl.h" #include "nel/misc/path.h" #include "nel/gui/view_renderer.h" #include "nel/gui/interface_group.h" diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h similarity index 100% rename from code/studio/src/plugins/gui_editor/nelgui_widget.h rename to code/studio/src/plugins/gui_editor/nelgui_ctrl.h From 2f81e3c1b94d0068aa65cab075bd3244f5be280b Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Sun, 15 Jun 2014 09:42:09 +0530 Subject: [PATCH 070/282] activating a plugin in ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../www/html/func/activate_plugin.php | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/func/activate_plugin.php diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/activate_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/activate_plugin.php new file mode 100644 index 000000000..930ed15f1 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/activate_plugin.php @@ -0,0 +1,35 @@ + update( "plugins", array( 'Status' => '1' ), "Id = $id" ); + if ( $result ) + { + header( "Location: index.php?page=plugins&result=3" ); + exit; + } + else + { + header( "Location: index.php?page=plugins&result=4" ); + exit; + } + } + else + { + header( "Location: index.php?page=plugins&result=4" ); + exit; + } + } + } From cebfde66f7f73245cb1cdd16d2e1d283478d873a Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Sun, 15 Jun 2014 09:45:00 +0530 Subject: [PATCH 071/282] deactivating a plugin in ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../www/html/func/deactivate_plugin.php | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/func/deactivate_plugin.php diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/deactivate_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/deactivate_plugin.php new file mode 100644 index 000000000..a4b6120b1 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/deactivate_plugin.php @@ -0,0 +1,37 @@ + update( "plugins", array( 'Status' => '0' ), "Id = $id" ); + if ( $result ) + { + header( "Location: index.php?page=plugins&result=5" ); + exit; + } + else + { + header( "Location: index.php?page=plugins&result=6" ); + exit; + + } + } + else + { + header( "Location: index.php?page=plugins&result=6" ); + exit; + } + } + } From 3cbe37d700c6d71c90dd0da378d130f28003b738 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 18:41:54 +0200 Subject: [PATCH 072/282] Fixed build error that was caused by two widgets having the same filenames. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/core/settings_dialog.cpp | 2 +- code/studio/src/plugins/core/settings_dialog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/core/settings_dialog.cpp b/code/studio/src/plugins/core/settings_dialog.cpp index 4b7bbac3a..0b38e4e80 100644 --- a/code/studio/src/plugins/core/settings_dialog.cpp +++ b/code/studio/src/plugins/core/settings_dialog.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . // Project includes -#include "settings_dialog.h" +#include "../core/settings_dialog.h" #include "ioptions_page.h" // Qt includes diff --git a/code/studio/src/plugins/core/settings_dialog.h b/code/studio/src/plugins/core/settings_dialog.h index 9e1c86444..a90f88b18 100644 --- a/code/studio/src/plugins/core/settings_dialog.h +++ b/code/studio/src/plugins/core/settings_dialog.h @@ -19,7 +19,7 @@ #ifndef SETTINGS_DIALOG_H #define SETTINGS_DIALOG_H -#include "ui_settings_dialog.h" +#include "../core/ui_settings_dialog.h" // Qt includes #include From f8505429ee44e5ee189d66f2d5fc4631c65cc1b8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:16:52 +0200 Subject: [PATCH 073/282] Moved the event listener from the 3d widget to the gui control class. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/nel3d_widget.cpp | 7 +------ code/studio/src/plugins/gui_editor/nel3d_widget.h | 6 ------ .../studio/src/plugins/gui_editor/nelgui_ctrl.cpp | 15 +++++++++++++++ code/studio/src/plugins/gui_editor/nelgui_ctrl.h | 10 +++++++++- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 3fd7abb7b..5be8bacb8 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -21,8 +21,7 @@ #include "nel/3d/driver_user.h" #include "nel/misc/rgba.h" #include "nel/misc/path.h" -#include "nel/misc/event_listener.h" -#include "nel/gui/event_listener.h" +//#include "nel/misc/event_listener.h" #ifdef NL_OS_WINDOWS #include @@ -42,7 +41,6 @@ namespace GUIEditor // so that we can render the widget normally ourselves, without the image // disappearing when a widget is resized or shown on top of us setAttribute( Qt::WA_PaintOnScreen, true ); - eventListener = NULL; } Nel3DWidget::~Nel3DWidget() @@ -59,7 +57,6 @@ namespace GUIEditor delete driver; driver = NULL; } - delete eventListener; } void Nel3DWidget::init() @@ -69,8 +66,6 @@ namespace GUIEditor driver = NL3D::UDriver::createDriver( 0, false, 0 ); driver->setMatrixMode2D11(); driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); - eventListener = new NLGUI::CEventListener(); - eventListener->addToServer( &driver->EventServer ); } void Nel3DWidget::createTextContext( std::string fontFile ) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h index fb4321d49..07a74b8c3 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.h @@ -22,11 +22,6 @@ #include "nel/misc/types_nl.h" #include -namespace NLGUI -{ - class CEventListener; -} - namespace NL3D { class UDriver; @@ -71,7 +66,6 @@ namespace GUIEditor private: NL3D::UDriver *driver; NL3D::UTextContext *textContext; - NLGUI::CEventListener *eventListener; }; } diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 2a9a433ee..4e72ba614 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -22,6 +22,7 @@ #include "nel/gui/widget_manager.h" #include "nel/gui/action_handler.h" #include "nel/gui/lua_manager.h" +#include "nel/gui/event_listener.h" #include "nel/misc/path.h" #include "nel/misc/i18n.h" #include @@ -42,6 +43,8 @@ namespace GUIEditor guiLoaded = false; watcher = NULL; w = new Nel3DWidget(); + eventListener = new NLGUI::CEventListener(); + listening = false; } NelGUICtrl::~NelGUICtrl() @@ -157,6 +160,12 @@ namespace GUIEditor { if( timerID == 0 ) timerID = startTimer( 200 ); + + if( !listening ) + { + eventListener->addToServer( &w->getDriver()->EventServer ); + listening = true; + } } void NelGUICtrl::hide() @@ -166,6 +175,12 @@ namespace GUIEditor killTimer( timerID ); timerID = 0; } + + if( listening ) + { + eventListener->removeFromServer(); + listening = false; + } } QWidget* NelGUICtrl::getViewPort() diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h index 38da599e4..f13a57b9b 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h @@ -23,6 +23,11 @@ class QWidget; +namespace NLGUI +{ + class CEventListener; +} + namespace GUIEditor { class CEditorSelectionWatcher; @@ -58,8 +63,11 @@ Q_SIGNALS: bool guiLoaded; CEditorSelectionWatcher *watcher; + NLGUI::CEventListener *eventListener; + + Nel3DWidget *w; - Nel3DWidget *w; + bool listening; }; } From e5921ffd64d45ee89371c0f14f0ce14b1cfa16f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:28:57 +0200 Subject: [PATCH 074/282] Activate the driver when getting a show event, and clear the GUI Editor display widget when there's no GUI loaded. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/nel3d_widget.cpp | 7 +++++++ code/studio/src/plugins/gui_editor/nel3d_widget.h | 2 ++ code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 5be8bacb8..1e030db25 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -102,6 +102,13 @@ namespace GUIEditor driver->swapBuffers(); } + void Nel3DWidget::showEvent( QShowEvent *evnt ) + { + QWidget::showEvent( evnt ); + + if( driver != NULL ) + driver->activate(); + } #if defined ( NL_OS_WINDOWS ) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h index 07a74b8c3..e2d5f00b6 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.h @@ -55,6 +55,8 @@ namespace GUIEditor protected: + void showEvent( QShowEvent *evnt ); + #if defined(NL_OS_WINDOWS) virtual bool winEvent( MSG *message, long *result ); #elif defined(NL_OS_MAC) diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 4e72ba614..72bb9524f 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -153,6 +153,10 @@ namespace GUIEditor w->getDriver()->EventServer.pump(); draw(); } + else + { + w->clear(); + } } } From 81908eea0122a47a3ef0b1cc9d4ce294d9b6f75f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:42:41 +0200 Subject: [PATCH 075/282] Set some windows attributes. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/nel3d_widget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 1e030db25..682645421 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -41,6 +41,8 @@ namespace GUIEditor // so that we can render the widget normally ourselves, without the image // disappearing when a widget is resized or shown on top of us setAttribute( Qt::WA_PaintOnScreen, true ); + setAttribute( Qt::WA_OpaquePaintEvent, true ); + setAttribute( Qt::WA_NoSystemBackground, true ); } Nel3DWidget::~Nel3DWidget() From dde63ceb319ec76aa1f821383ab879de2c08b8c8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:52:04 +0200 Subject: [PATCH 076/282] Nel3DWidget is no longer in the GUI Editor namespace. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/nel3d_widget.cpp | 201 +++++++++--------- .../src/plugins/gui_editor/nel3d_widget.h | 54 +++-- .../src/plugins/gui_editor/nelgui_ctrl.h | 2 +- 3 files changed, 124 insertions(+), 133 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 682645421..8ebc393ba 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -27,152 +27,145 @@ #include #endif - - -namespace GUIEditor +Nel3DWidget::Nel3DWidget( QWidget *parent ) : +QWidget( parent ) { - Nel3DWidget::Nel3DWidget( QWidget *parent ) : - QWidget( parent ) - { - driver = NULL; - textContext = NULL; - - // Need to set this attribute with a NULL paintengine returned to Qt - // so that we can render the widget normally ourselves, without the image - // disappearing when a widget is resized or shown on top of us - setAttribute( Qt::WA_PaintOnScreen, true ); - setAttribute( Qt::WA_OpaquePaintEvent, true ); - setAttribute( Qt::WA_NoSystemBackground, true ); - } + driver = NULL; + textContext = NULL; + + // Need to set this attribute with a NULL paintengine returned to Qt + // so that we can render the widget normally ourselves, without the image + // disappearing when a widget is resized or shown on top of us + setAttribute( Qt::WA_PaintOnScreen, true ); + setAttribute( Qt::WA_OpaquePaintEvent, true ); + setAttribute( Qt::WA_NoSystemBackground, true ); +} - Nel3DWidget::~Nel3DWidget() +Nel3DWidget::~Nel3DWidget() +{ + if( driver != NULL ) { - if( driver != NULL ) + if( textContext != NULL ) { - if( textContext != NULL ) - { - driver->deleteTextContext( textContext ); - textContext = NULL; - } - - driver->release(); - delete driver; - driver = NULL; + driver->deleteTextContext( textContext ); + textContext = NULL; } - } - - void Nel3DWidget::init() - { - nlassert( driver == NULL ); - driver = NL3D::UDriver::createDriver( 0, false, 0 ); - driver->setMatrixMode2D11(); - driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); + driver->release(); + delete driver; + driver = NULL; } +} - void Nel3DWidget::createTextContext( std::string fontFile ) - { - if( driver == NULL ) - return; - - std::string font; +void Nel3DWidget::init() +{ + nlassert( driver == NULL ); - try - { - font = NLMISC::CPath::lookup( fontFile ); - } - catch( ... ) - { - nlinfo( "Font %s cannot be found, cannot create textcontext!", fontFile.c_str() ); - exit( EXIT_FAILURE ); - } + driver = NL3D::UDriver::createDriver( 0, false, 0 ); + driver->setMatrixMode2D11(); + driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); +} - if( textContext != NULL ) - { - driver->deleteTextContext( textContext ); - textContext = NULL; - } +void Nel3DWidget::createTextContext( std::string fontFile ) +{ + if( driver == NULL ) + return; + + std::string font; - textContext = driver->createTextContext( font ); + try + { + font = NLMISC::CPath::lookup( fontFile ); } - - void Nel3DWidget::clear() + catch( ... ) { - if( driver == NULL ) - return; - driver->clearBuffers( NLMISC::CRGBA::Black ); - driver->swapBuffers(); + nlinfo( "Font %s cannot be found, cannot create textcontext!", fontFile.c_str() ); + exit( EXIT_FAILURE ); } - void Nel3DWidget::showEvent( QShowEvent *evnt ) + if( textContext != NULL ) { - QWidget::showEvent( evnt ); - - if( driver != NULL ) - driver->activate(); + driver->deleteTextContext( textContext ); + textContext = NULL; } + textContext = driver->createTextContext( font ); +} + +void Nel3DWidget::clear() +{ + if( driver == NULL ) + return; + driver->clearBuffers( NLMISC::CRGBA::Black ); + driver->swapBuffers(); +} + +void Nel3DWidget::showEvent( QShowEvent *evnt ) +{ + QWidget::showEvent( evnt ); + + if( driver != NULL ) + driver->activate(); +} + #if defined ( NL_OS_WINDOWS ) - typedef bool ( *winProc )( NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); +typedef bool ( *winProc )( NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); - bool Nel3DWidget::winEvent( MSG *message, long *result ) +bool Nel3DWidget::winEvent( MSG *message, long *result ) +{ + if( driver != NULL ) { - if( driver != NULL ) + NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); + if( iDriver != NULL ) { - NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); - if( iDriver != NULL ) - { - winProc proc = (winProc)iDriver->getWindowProc(); - return proc( iDriver, message->hwnd, message->message, message->wParam, message->lParam ); - } + winProc proc = (winProc)iDriver->getWindowProc(); + return proc( iDriver, message->hwnd, message->message, message->wParam, message->lParam ); } - - return false; } + return false; +} + #elif defined( NL_OS_MAC ) - typedef bool ( *cocoaProc )( NL3D::IDriver *, const void *e ); +typedef bool ( *cocoaProc )( NL3D::IDriver *, const void *e ); - bool Nel3DWidget::macEvent( EventHandlerCallRef caller, EventRef event ) - { - if( caller ) - nlerror( "You are using QtCarbon! Only QtCocoa supported, please upgrade Qt" ); +bool Nel3DWidget::macEvent( EventHandlerCallRef caller, EventRef event ) +{ + if( caller ) + nlerror( "You are using QtCarbon! Only QtCocoa supported, please upgrade Qt" ); - if( driver != NULL ) + if( driver != NULL ) + { + NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); + if( iDriver != NULL ) { - NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); - if( iDriver != NULL ) - { - cocoaProc proc = ( cocoaProc )iDriver->getWindowProc(); - return proc( iDriver, event ); - } + cocoaProc proc = ( cocoaProc )iDriver->getWindowProc(); + return proc( iDriver, event ); } - - return false; } + return false; +} + #elif defined( NL_OS_UNIX ) - typedef bool ( *x11Proc )( NL3D::IDriver *drv, XEvent *e ); +typedef bool ( *x11Proc )( NL3D::IDriver *drv, XEvent *e ); - bool Nel3DWidget::x11Event( XEvent *event ) +bool Nel3DWidget::x11Event( XEvent *event ) +{ + if( driver != NULL ) { + NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); if( driver != NULL ) { - NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); - if( driver != NULL ) - { - x11Proc proc = ( x11Proc )iDriver->getWindowProc(); - return proc( iDriver, event ); - } + x11Proc proc = ( x11Proc )iDriver->getWindowProc(); + return proc( iDriver, event ); } - - return false; } -#endif + return false; } - +#endif diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h index e2d5f00b6..672fc3fde 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.h @@ -28,48 +28,46 @@ namespace NL3D class UTextContext; } -namespace GUIEditor +/// Nel 3D interface to Qt +class Nel3DWidget : public QWidget { - /// Nel 3D interface to Qt - class Nel3DWidget : public QWidget - { - Q_OBJECT - public: - Nel3DWidget( QWidget *parent = NULL ); - virtual ~Nel3DWidget(); + Q_OBJECT +public: + Nel3DWidget( QWidget *parent = NULL ); + virtual ~Nel3DWidget(); - virtual void init(); - void createTextContext( std::string fontFile ); + void init(); + void createTextContext( std::string fontFile ); - NL3D::UDriver* getDriver() const{ return driver; } - NL3D::UTextContext* getTextContext() const{ return textContext; } + NL3D::UDriver* getDriver() const{ return driver; } + NL3D::UTextContext* getTextContext() const{ return textContext; } - // Need to return NULL paintengine to Qt so that we can - // render the widget normally ourselves, without the image - // disappearing when a widget is resized or shown on top of us - QPaintEngine* paintEngine() const{ return NULL; } + // Need to return NULL paintengine to Qt so that we can + // render the widget normally ourselves, without the image + // disappearing when a widget is resized or shown on top of us + QPaintEngine* paintEngine() const{ return NULL; } - public Q_SLOTS: - void clear(); +public Q_SLOTS: + void clear(); - protected: +protected: - void showEvent( QShowEvent *evnt ); + void showEvent( QShowEvent *evnt ); #if defined(NL_OS_WINDOWS) - virtual bool winEvent( MSG *message, long *result ); + bool winEvent( MSG *message, long *result ); #elif defined(NL_OS_MAC) - virtual bool macEvent( EventHandlerCallRef caller, EventRef event ); + bool macEvent( EventHandlerCallRef caller, EventRef event ); #elif defined(NL_OS_UNIX) - virtual bool x11Event( XEvent *event ); + bool x11Event( XEvent *event ); #endif - private: - NL3D::UDriver *driver; - NL3D::UTextContext *textContext; - }; -} +private: + NL3D::UDriver *driver; + NL3D::UTextContext *textContext; + +}; #endif diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h index f13a57b9b..b3c68ff32 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h @@ -22,6 +22,7 @@ #include "project_files.h" class QWidget; +class Nel3DWidget; namespace NLGUI { @@ -31,7 +32,6 @@ namespace NLGUI namespace GUIEditor { class CEditorSelectionWatcher; - class Nel3DWidget; /// Qt viewport controller for the Nel GUI library class NelGUICtrl : public QObject From b4eac44a9d8d76c37a96bdaae5a9bb762c75c095 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 22:22:01 +0200 Subject: [PATCH 077/282] Moved the Nel 3d widget into it's own library. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 1 + code/studio/src/Nel3DWidget/CMakeLists.txt | 36 +++++++++++++++++++ .../nel3d_widget.cpp | 0 .../gui_editor => Nel3DWidget}/nel3d_widget.h | 8 ++++- .../src/plugins/gui_editor/CMakeLists.txt | 2 +- .../src/plugins/gui_editor/nelgui_ctrl.cpp | 2 +- 6 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/Nel3DWidget/CMakeLists.txt rename code/studio/src/{plugins/gui_editor => Nel3DWidget}/nel3d_widget.cpp (100%) rename code/studio/src/{plugins/gui_editor => Nel3DWidget}/nel3d_widget.h (92%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 9bc071bf2..8670f516f 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY(3rdparty) +ADD_SUBDIRECTORY(Nel3DWidget) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${QT_INCLUDES}) INCLUDE( ${QT_USE_FILE} ) diff --git a/code/studio/src/Nel3DWidget/CMakeLists.txt b/code/studio/src/Nel3DWidget/CMakeLists.txt new file mode 100644 index 000000000..55b4b2a80 --- /dev/null +++ b/code/studio/src/Nel3DWidget/CMakeLists.txt @@ -0,0 +1,36 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${QT_INCLUDES} + ) + +INCLUDE( ${QT_USE_FILE} ) + +FILE(GLOB SRC *.cpp *.h) + +SET(NEL3DWIDGET_HDR + nel3d_widget.h + ) + +SET(QT_USE_QTGUI TRUE) + +QT4_WRAP_CPP( NEL3DWIDGET_MOC_SRC ${NEL3DWIDGET_HDR} ) + +SOURCE_GROUP(QtGeneratedMocSrc FILES ${NEL3DWIDGET_MOC_SRC} ) +SOURCE_GROUP("Nel 3D Widget files" FILES ${SRC}) + +ADD_LIBRARY(nel3dwidget SHARED + ${SRC} + ${NEL3DWIDGET_MOC_SRC} + ) + +TARGET_LINK_LIBRARIES( nel3dwidget + nelmisc + nel3d + ${QT_LIBRARIES} + ) + +NL_DEFAULT_PROPS(nel3dwidget "Nel3D Qt Widget") +NL_ADD_RUNTIME_FLAGS(nel3dwidget) +NL_ADD_LIB_SUFFIX(nel3dwidget) + +ADD_DEFINITIONS( -DN3DW_LIB -DQT_DLL -DQT_SHARED ${QT_DEFINITIONS} ) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/Nel3DWidget/nel3d_widget.cpp similarity index 100% rename from code/studio/src/plugins/gui_editor/nel3d_widget.cpp rename to code/studio/src/Nel3DWidget/nel3d_widget.cpp diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/Nel3DWidget/nel3d_widget.h similarity index 92% rename from code/studio/src/plugins/gui_editor/nel3d_widget.h rename to code/studio/src/Nel3DWidget/nel3d_widget.h index 672fc3fde..d3e6c3ae1 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/Nel3DWidget/nel3d_widget.h @@ -22,6 +22,12 @@ #include "nel/misc/types_nl.h" #include +#if defined( N3DW_LIB ) +#define N3DW_EXPORT Q_DECL_EXPORT +#else +#define N3DW_EXPORT Q_DECL_IMPORT +#endif + namespace NL3D { class UDriver; @@ -29,7 +35,7 @@ namespace NL3D } /// Nel 3D interface to Qt -class Nel3DWidget : public QWidget +class N3DW_EXPORT Nel3DWidget : public QWidget { Q_OBJECT public: diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 2ea82a6e4..5adf618d0 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -24,7 +24,6 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR action_editor.h property_browser_ctrl.h project_window.h - nel3d_widget.h nelgui_ctrl.h new_property_widget.h new_widget_widget.h @@ -78,6 +77,7 @@ TARGET_LINK_LIBRARIES( ${QT_QTOPENGL_LIBRARY} ${LIBXML2_LIBRARIES} qt_property_browser + nel3dwidget ) NL_DEFAULT_PROPS(studio_plugin_gui_editor "Tools: Studio Plugin: GUI Editor") diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 72bb9524f..b2cf67ea2 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -30,7 +30,7 @@ #include #include "editor_selection_watcher.h" -#include "nel3d_widget.h" +#include "../../Nel3DWidget/nel3d_widget.h" namespace GUIEditor { From d74d1d1663d4ebe7dca543a3e58642ee009b6c41 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 16 Jun 2014 15:30:35 +0200 Subject: [PATCH 078/282] Had to move the Nel3DWidget library to the core plugin, because Nel can only be used statically at this point. Which makes using the separate Nel3DWidget library inparctical. --HG-- branch : gsoc2014-dfighter --- code/studio/src/CMakeLists.txt | 1 - code/studio/src/Nel3DWidget/CMakeLists.txt | 36 ------------------- code/studio/src/plugins/core/CMakeLists.txt | 8 ++++- .../core}/Nel3DWidget/nel3d_widget.cpp | 0 .../core}/Nel3DWidget/nel3d_widget.h | 8 ++--- .../src/plugins/gui_editor/CMakeLists.txt | 1 - .../src/plugins/gui_editor/nelgui_ctrl.cpp | 2 +- 7 files changed, 10 insertions(+), 46 deletions(-) delete mode 100644 code/studio/src/Nel3DWidget/CMakeLists.txt rename code/studio/src/{ => plugins/core}/Nel3DWidget/nel3d_widget.cpp (100%) rename code/studio/src/{ => plugins/core}/Nel3DWidget/nel3d_widget.h (92%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 8670f516f..9bc071bf2 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -1,5 +1,4 @@ ADD_SUBDIRECTORY(3rdparty) -ADD_SUBDIRECTORY(Nel3DWidget) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${QT_INCLUDES}) INCLUDE( ${QT_USE_FILE} ) diff --git a/code/studio/src/Nel3DWidget/CMakeLists.txt b/code/studio/src/Nel3DWidget/CMakeLists.txt deleted file mode 100644 index 55b4b2a80..000000000 --- a/code/studio/src/Nel3DWidget/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${QT_INCLUDES} - ) - -INCLUDE( ${QT_USE_FILE} ) - -FILE(GLOB SRC *.cpp *.h) - -SET(NEL3DWIDGET_HDR - nel3d_widget.h - ) - -SET(QT_USE_QTGUI TRUE) - -QT4_WRAP_CPP( NEL3DWIDGET_MOC_SRC ${NEL3DWIDGET_HDR} ) - -SOURCE_GROUP(QtGeneratedMocSrc FILES ${NEL3DWIDGET_MOC_SRC} ) -SOURCE_GROUP("Nel 3D Widget files" FILES ${SRC}) - -ADD_LIBRARY(nel3dwidget SHARED - ${SRC} - ${NEL3DWIDGET_MOC_SRC} - ) - -TARGET_LINK_LIBRARIES( nel3dwidget - nelmisc - nel3d - ${QT_LIBRARIES} - ) - -NL_DEFAULT_PROPS(nel3dwidget "Nel3D Qt Widget") -NL_ADD_RUNTIME_FLAGS(nel3dwidget) -NL_ADD_LIB_SUFFIX(nel3dwidget) - -ADD_DEFINITIONS( -DN3DW_LIB -DQT_DLL -DQT_SHARED ${QT_DEFINITIONS} ) diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index 964f95b11..2c21c9b58 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -4,6 +4,11 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${QT_INCLUDES}) FILE(GLOB SRC *.cpp *.h) +SET( SRC ${SRC} + ${CMAKE_CURRENT_SOURCE_DIR}/Nel3DWidget/nel3d_widget.h + ${CMAKE_CURRENT_SOURCE_DIR}/Nel3DWidget/nel3d_widget.cpp + ) + SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) @@ -22,6 +27,7 @@ SET(OVQT_CORE_PLUGIN_HDR search_paths_settings_page.h general_settings_page.h plugin_view_dialog.h + ${CMAKE_CURRENT_SOURCE_DIR}/Nel3DWidget/nel3d_widget.h ) SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui @@ -47,7 +53,7 @@ SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) ADD_LIBRARY(studio_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(studio_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_core nelmisc nel3d ${QT_LIBRARIES}) NL_DEFAULT_PROPS(studio_plugin_core "Tools: Studio Plugin: Core") NL_ADD_RUNTIME_FLAGS(studio_plugin_core) diff --git a/code/studio/src/Nel3DWidget/nel3d_widget.cpp b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp similarity index 100% rename from code/studio/src/Nel3DWidget/nel3d_widget.cpp rename to code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp diff --git a/code/studio/src/Nel3DWidget/nel3d_widget.h b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h similarity index 92% rename from code/studio/src/Nel3DWidget/nel3d_widget.h rename to code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h index d3e6c3ae1..9cbf474bc 100644 --- a/code/studio/src/Nel3DWidget/nel3d_widget.h +++ b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h @@ -22,11 +22,7 @@ #include "nel/misc/types_nl.h" #include -#if defined( N3DW_LIB ) -#define N3DW_EXPORT Q_DECL_EXPORT -#else -#define N3DW_EXPORT Q_DECL_IMPORT -#endif +#include "../core_global.h" namespace NL3D { @@ -35,7 +31,7 @@ namespace NL3D } /// Nel 3D interface to Qt -class N3DW_EXPORT Nel3DWidget : public QWidget +class CORE_EXPORT Nel3DWidget : public QWidget { Q_OBJECT public: diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 5adf618d0..0c13c4cd6 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -77,7 +77,6 @@ TARGET_LINK_LIBRARIES( ${QT_QTOPENGL_LIBRARY} ${LIBXML2_LIBRARIES} qt_property_browser - nel3dwidget ) NL_DEFAULT_PROPS(studio_plugin_gui_editor "Tools: Studio Plugin: GUI Editor") diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index b2cf67ea2..03f784944 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -30,7 +30,7 @@ #include #include "editor_selection_watcher.h" -#include "../../Nel3DWidget/nel3d_widget.h" +#include "../core/Nel3DWidget/nel3d_widget.h" namespace GUIEditor { From ca78ce10a0e0c76d2203963378011328e7d41c4f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 16 Jun 2014 16:22:52 +0200 Subject: [PATCH 079/282] Object Viewer plugin will now use the Nel3DWidget in the Core plugin. --HG-- branch : gsoc2014-dfighter --- .../plugins/core/Nel3DWidget/nel3d_widget.cpp | 13 ++- .../plugins/core/Nel3DWidget/nel3d_widget.h | 6 +- .../object_viewer/graphics_viewport.cpp | 100 ++++-------------- .../plugins/object_viewer/graphics_viewport.h | 40 ++----- .../src/plugins/object_viewer/main_window.cpp | 2 +- .../plugins/object_viewer/object_viewer.cpp | 17 +-- .../src/plugins/object_viewer/object_viewer.h | 2 +- 7 files changed, 52 insertions(+), 128 deletions(-) diff --git a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp index 8ebc393ba..dc0bb858b 100644 --- a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp +++ b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp @@ -1,4 +1,4 @@ -// Object Viewer Qt GUI Editor plugin +// Ryzom Core MMORPG framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify @@ -21,12 +21,13 @@ #include "nel/3d/driver_user.h" #include "nel/misc/rgba.h" #include "nel/misc/path.h" -//#include "nel/misc/event_listener.h" #ifdef NL_OS_WINDOWS #include #endif +#include + Nel3DWidget::Nel3DWidget( QWidget *parent ) : QWidget( parent ) { @@ -62,7 +63,6 @@ void Nel3DWidget::init() nlassert( driver == NULL ); driver = NL3D::UDriver::createDriver( 0, false, 0 ); - driver->setMatrixMode2D11(); driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); } @@ -108,6 +108,13 @@ void Nel3DWidget::showEvent( QShowEvent *evnt ) driver->activate(); } +void Nel3DWidget::resizeEvent( QResizeEvent *evnt ) +{ + QWidget::resizeEvent( evnt ); + + Q_EMIT( evnt->size().width(), evnt->size().height() ); +} + #if defined ( NL_OS_WINDOWS ) typedef bool ( *winProc )( NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); diff --git a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h index 9cbf474bc..059e1b738 100644 --- a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h +++ b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h @@ -1,4 +1,4 @@ -// Object Viewer Qt GUI Editor plugin +// Ryzom Core MMORPG framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify @@ -50,12 +50,16 @@ public: // disappearing when a widget is resized or shown on top of us QPaintEngine* paintEngine() const{ return NULL; } +Q_SIGNALS: + void resize( int width, int height ); + public Q_SLOTS: void clear(); protected: void showEvent( QShowEvent *evnt ); + void resizeEvent( QResizeEvent *evnt ); #if defined(NL_OS_WINDOWS) bool winEvent( MSG *message, long *result ); diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp index d8e36e785..8cf6f3f60 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp @@ -19,6 +19,7 @@ #include "stdpch.h" #include "graphics_viewport.h" +#include "../core/Nel3DWidget/nel3d_widget.h" // STL includes @@ -46,17 +47,18 @@ using namespace NL3D; namespace NLQT { -CGraphicsViewport::CGraphicsViewport(QWidget *parent) - : QNLWidget(parent) +CGraphicsViewport::CGraphicsViewport(QObject *parent) + : QObject(parent) { - setAttribute(Qt::WA_OpaquePaintEvent); - setAttribute(Qt::WA_NoSystemBackground); - setAttribute(Qt::WA_PaintOnScreen); + w = new Nel3DWidget(); + connect( w, SIGNAL( resize( int, int ) ), this, SLOT( onResize( int, int ) ) ); } CGraphicsViewport::~CGraphicsViewport() { - + disconnect( w, SIGNAL( resize( int, int ) ), this, SLOT( onResize( int, int ) ) ); + delete w; + w = NULL; } void CGraphicsViewport::init() @@ -68,12 +70,13 @@ void CGraphicsViewport::init() makeCurrent(); #endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC) - Modules::objView().init((nlWindow)winId(), width(), height()); + w->init(); + Modules::objView().init( w->getDriver() ); Modules::psEdit().init(); Modules::veget().init(); - setMouseTracking(true); - setFocusPolicy(Qt::StrongFocus); + w->setMouseTracking(true); + w->setFocusPolicy(Qt::StrongFocus); } void CGraphicsViewport::release() @@ -101,6 +104,11 @@ QAction *CGraphicsViewport::createSetBackgroundColor(QObject *parent) return action; } +QWidget* CGraphicsViewport::widget() +{ + return w; +} + void CGraphicsViewport::saveScreenshot() { Modules::objView().saveScreenshot("screenshot", false, true, false); @@ -115,81 +123,11 @@ void CGraphicsViewport::setBackgroundColor() Modules::objView().setBackgroundColor(NLMISC::CRGBA(color.red(), color.green(), color.blue())); } -void CGraphicsViewport::resizeEvent(QResizeEvent *resizeEvent) +void CGraphicsViewport::onResize( int width, int height ) { - QWidget::resizeEvent(resizeEvent); if (Modules::objView().getDriver()) - Modules::objView().setSizeViewport(resizeEvent->size().width(), resizeEvent->size().height()); -} - -#if defined(NL_OS_WINDOWS) - -typedef bool (*winProc)(NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -bool CGraphicsViewport::winEvent(MSG *message, long *result) -{ - if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive()) - { - NL3D::IDriver *driver = dynamic_cast(Modules::objView().getDriver())->getDriver(); - if (driver) - { - winProc proc = (winProc)driver->getWindowProc(); - - // TODO: shouldn't it return false like the others? - // see macEvent() and x11Event() below - return proc(driver, message->hwnd, message->message, message->wParam, message->lParam); - } - } - - return false; -} - -#elif defined(NL_OS_MAC) - -typedef bool (*cocoaProc)(NL3D::IDriver *, const void *e); - -bool CGraphicsViewport::macEvent(EventHandlerCallRef caller, EventRef event) -{ - if(caller) - nlerror("You are using QtCarbon! Only QtCocoa supported, please upgrade Qt"); - - if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive()) - { - NL3D::IDriver *driver = dynamic_cast(Modules::objView().getDriver())->getDriver(); - if (driver) - { - cocoaProc proc = (cocoaProc)driver->getWindowProc(); - proc(driver, event); - } - } - - // return false to let Qt handle the event as well, - // else the widget would never get focus - return false; -} - -#elif defined(NL_OS_UNIX) - -typedef bool (*x11Proc)(NL3D::IDriver *drv, XEvent *e); - -bool CGraphicsViewport::x11Event(XEvent *event) -{ - if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive()) - { - NL3D::IDriver *driver = dynamic_cast(Modules::objView().getDriver())->getDriver(); - if (driver) - { - x11Proc proc = (x11Proc)driver->getWindowProc(); - proc(driver, event); - } - } - - // return false to let Qt handle the event as well, - // else the widget would never get focus - // TODO: test me please, i have no linux at hand (rti) - return false; + Modules::objView().setSizeViewport( width, height ); } -#endif } /* namespace NLQT */ diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.h b/code/studio/src/plugins/object_viewer/graphics_viewport.h index 0c01fa1ad..9bbad9806 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.h +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.h @@ -26,23 +26,14 @@ // STL includes // Qt includes -#include -#include +#include // NeL includes // Project includes - -/* TODO every platform should use QWidget */ -#if defined(NL_OS_WINDOWS) -typedef QWidget QNLWidget; -#elif defined(NL_OS_MAC) -typedef QWidget QNLWidget; -#elif defined(NL_OS_UNIX) -typedef QGLWidget QNLWidget; -#endif // NL_OS_UNIX - +class QWidget; class QAction; +class Nel3DWidget; namespace NLQT { @@ -51,25 +42,22 @@ namespace NLQT @class CGraphicsViewport @brief Responsible for interaction between Qt and NeL. Initializes CObjectViewer, CParticleEditor and CVegetableEditor subsystem. */ -class CGraphicsViewport : public QNLWidget, public NLMISC::IEventEmitter +class CGraphicsViewport : public QObject, public NLMISC::IEventEmitter { Q_OBJECT public: - CGraphicsViewport(QWidget *parent); + CGraphicsViewport(QObject *parent); virtual ~CGraphicsViewport(); - virtual QPaintEngine *paintEngine() const - { - return NULL; - } - void init(); void release(); QAction *createSaveScreenshotAction(QObject *parent); QAction *createSetBackgroundColor(QObject *parent); + QWidget* widget(); + private Q_SLOTS: void saveScreenshot(); void setBackgroundColor(); @@ -77,21 +65,15 @@ private Q_SLOTS: void submitEvents(NLMISC::CEventServer &server, bool allWindows) { } void emulateMouseRawMode(bool) { } -protected: - virtual void resizeEvent(QResizeEvent *resizeEvent); - -#if defined(NL_OS_WINDOWS) - virtual bool winEvent(MSG *message, long *result); -#elif defined(NL_OS_MAC) - virtual bool macEvent(EventHandlerCallRef caller, EventRef event); -#elif defined(NL_OS_UNIX) - virtual bool x11Event(XEvent *event); -#endif + void onResize( int width, int height ); private: CGraphicsViewport(const CGraphicsViewport &); CGraphicsViewport &operator=(const CGraphicsViewport &); + + Nel3DWidget *w; + }; /* class CGraphicsViewport */ } /* namespace NLQT */ diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index 864896ca1..10da56ffa 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -77,7 +77,7 @@ CMainWindow::CMainWindow(QWidget *parent) // create NeL viewport _GraphicsViewport = new CGraphicsViewport(this); - setCentralWidget(_GraphicsViewport); + setCentralWidget(_GraphicsViewport->widget()); setDockNestingEnabled(true); diff --git a/code/studio/src/plugins/object_viewer/object_viewer.cpp b/code/studio/src/plugins/object_viewer/object_viewer.cpp index 48c679455..2cf803d3d 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer.cpp +++ b/code/studio/src/plugins/object_viewer/object_viewer.cpp @@ -70,20 +70,16 @@ CObjectViewer::~CObjectViewer() saveConfig(); } -void CObjectViewer::init(nlWindow wnd, uint16 w, uint16 h) +void CObjectViewer::init( NL3D::UDriver *driver ) { //H_AUTO2 nldebug("CObjectViewert::init"); // create the driver nlassert(!_Driver); - - _Driver = NL3D::UDriver::createDriver(0, _Direct3D, 0); + _Driver = driver; nlassert(_Driver); - // initialize the window with config file values - _Driver->setDisplay(wnd, NL3D::UDriver::CMode(w, h, 32)); - // Create a scene _Scene = _Driver->createScene(false); _Scene->setPolygonBalancingMode(NL3D::UScene::PolygonBalancingClamp); @@ -128,8 +124,8 @@ void CObjectViewer::init(nlWindow wnd, uint16 w, uint16 h) NL3D::CBloomEffect::instance().setDensityBloom(uint8(_BloomDensity)); NL3D::CBloomEffect::instance().setSquareBloom(_BloomSquare); - NL3D::CDriverUser *driver = dynamic_cast(Modules::objView().getDriver()); - _IDriver = driver->getDriver(); + NL3D::CDriverUser *udriver = dynamic_cast(Modules::objView().getDriver()); + _IDriver = udriver->getDriver(); NL3D::CSceneUser *scene = dynamic_cast(Modules::objView().getScene()); _CScene = &scene->getScene(); @@ -158,11 +154,8 @@ void CObjectViewer::release() // delete the light delete _Light; - // release driver - nlassert(_Driver); - _Driver->release(); - delete _Driver; _Driver = 0; + _IDriver = NULL; } void CObjectViewer::updateInput() diff --git a/code/studio/src/plugins/object_viewer/object_viewer.h b/code/studio/src/plugins/object_viewer/object_viewer.h index 5e978d7e0..e8cc7304e 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer.h +++ b/code/studio/src/plugins/object_viewer/object_viewer.h @@ -78,7 +78,7 @@ public: /// @param wnd - handle window. /// @param w - width window. /// @param h - height window. - void init(nlWindow wnd, uint16 w, uint16 h); + void init( NL3D::UDriver *driver ); /// Release class. void release(); From 4341ac31390cb5599b20d7b4a2d8259704017b89 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 01:15:39 +0200 Subject: [PATCH 080/282] Unload plugins when killing them. --HG-- branch : gsoc2014-dfighter --- .../src/extension_system/plugin_spec.cpp | 34 +++++++++++++++---- .../studio/src/extension_system/plugin_spec.h | 7 +++- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/code/studio/src/extension_system/plugin_spec.cpp b/code/studio/src/extension_system/plugin_spec.cpp index 89f8046bb..97a08ea64 100644 --- a/code/studio/src/extension_system/plugin_spec.cpp +++ b/code/studio/src/extension_system/plugin_spec.cpp @@ -84,6 +84,13 @@ PluginSpec::PluginSpec() #else # error "You must define the lib suffix for your platform" #endif + loader = NULL; +} + +PluginSpec::~PluginSpec() +{ + delete loader; + loader = NULL; } QString PluginSpec::name() const @@ -292,6 +299,8 @@ bool PluginSpec::isEnabled() const bool PluginSpec::loadLibrary() { + nlassert( loader == NULL ); + if (m_hasError) return false; if (m_state != State::Resolved) @@ -301,14 +310,16 @@ bool PluginSpec::loadLibrary() return reportError(QCoreApplication::translate("PluginSpec", "Loading the library failed because state != Resolved")); } - QPluginLoader loader(m_filePath); - if (!loader.load()) - return reportError(loader.errorString()); + loader = new QPluginLoader( m_filePath ); + if (!loader->load()) + return reportError(loader->errorString()); - IPlugin *pluginObject = qobject_cast(loader.instance()); + IPlugin *pluginObject = qobject_cast(loader->instance()); if (!pluginObject) { - loader.unload(); + loader->unload(); + delete loader; + loader = NULL; return reportError(QCoreApplication::translate("PluginSpec", "Plugin is not valid (does not derive from IPlugin)")); } @@ -412,8 +423,17 @@ void PluginSpec::kill() { if (!m_plugin) return; - delete m_plugin; - m_plugin = 0; + + bool b = loader->unload(); + if( !b ) + { + nlinfo( "Plugin %s couldn't be unloaded.", this->m_name.toAscii().data() ); + } + + //delete m_plugin; + m_plugin = NULL; + delete loader; + loader = NULL; m_state = State::Deleted; } diff --git a/code/studio/src/extension_system/plugin_spec.h b/code/studio/src/extension_system/plugin_spec.h index 0ce74d004..d2abe1ef8 100644 --- a/code/studio/src/extension_system/plugin_spec.h +++ b/code/studio/src/extension_system/plugin_spec.h @@ -25,12 +25,15 @@ #include #include +class QPluginLoader; + namespace ExtensionSystem { class PluginSpec: public IPluginSpec { public: + ~PluginSpec(); virtual QString name() const; virtual QString version() const; virtual QString vendor() const; @@ -54,7 +57,7 @@ public: private: PluginSpec(); - + bool setFileName(const QString &fileName); bool setSpecFileName(const QString &specFileName); bool readSpec(); @@ -96,6 +99,8 @@ private: IPluginManager *m_pluginManager; QList m_dependencySpecs; + QPluginLoader *loader; + friend class PluginManager; }; From a80053083d13faf7604b0109307c443342cdaa1f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 01:20:37 +0200 Subject: [PATCH 081/282] Crashfix: If the status info widget isn't removed it miraclously crashes the app on shutdown. TODO: investigate why. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/object_viewer/main_window.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index 10da56ffa..dc0c221cc 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -117,7 +117,7 @@ CMainWindow::CMainWindow(QWidget *parent) _statusBarTimer = new QTimer(this); connect(_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar())); - _statusInfo = new QLabel(this); + _statusInfo = new QLabel(); _statusInfo->hide(); Core::ICore::instance()->mainWindow()->statusBar()->addPermanentWidget(_statusInfo); } @@ -137,6 +137,12 @@ CMainWindow::~CMainWindow() removeMenus(); + // If the status info widget isn't removed it miraclously crashes the application on shutdown... + // Somehow it's deleted while being owned by the status bar, then the status bar also tries to delete is... + Core::ICore::instance()->mainWindow()->statusBar()->removeWidget( _statusInfo ); + delete _statusInfo; + _statusInfo = NULL; + delete _AnimationDialog; delete _AnimationSetDialog; delete _SlotManagerDialog; From 3d48a01170652f68c420dbe714a18c31329240c0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:41:58 +0200 Subject: [PATCH 082/282] Wrong slash... --HG-- branch : gsoc2014-dfighter --- code/studio/src/pm_watcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp index 85c6d267b..0bbd28ca1 100644 --- a/code/studio/src/pm_watcher.cpp +++ b/code/studio/src/pm_watcher.cpp @@ -16,7 +16,7 @@ #include "pm_watcher.h" -#include "extension_system\iplugin_manager.h" +#include "extension_system/iplugin_manager.h" #include "splash_screen.h" namespace From d64b499284ee0dcd735fb53fa1dddaa83820d072 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:51:53 +0200 Subject: [PATCH 083/282] Making master Dnk happy. --HG-- branch : gsoc2014-dfighter --- code/studio/src/extension_system/iplugin_manager.h | 2 +- code/studio/src/extension_system/plugin_manager.cpp | 10 +++++----- code/studio/src/extension_system/plugin_manager.h | 4 ++-- code/studio/src/plugins/core/plugin_view_dialog.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index efbf5ee2f..f60f45890 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -55,7 +55,7 @@ public: virtual void setPluginPaths(const QStringList &paths) = 0; virtual QList plugins() const = 0; - virtual bool loadPlugin( const char *plugin ) = 0; + virtual bool loadPlugin( const QString &plugin ) = 0; virtual bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ) = 0; // Settings diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 508a4b81b..37cd85237 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -114,15 +114,15 @@ void PluginManager::loadPlugins() Q_EMIT pluginsChanged(); } -bool PluginManager::loadPluginSpec( const char *plugin ) +bool PluginManager::loadPluginSpec( const QString &plugin ) { - nlinfo( "Loading plugin spec %s", plugin ); + nlinfo( "Loading plugin spec %s", plugin.toUtf8().data() ); PluginSpec *spec = new PluginSpec; spec->m_pluginManager = this; if( !spec->setSpecFileName( plugin ) ) { - nlinfo( "Error loading plugin spec %s", plugin ); + nlinfo( "Error loading plugin spec %s", plugin.toUtf8().data() ); return false; } @@ -132,7 +132,7 @@ bool PluginManager::loadPluginSpec( const char *plugin ) return true; } -bool PluginManager::loadPlugin( const char *plugin ) +bool PluginManager::loadPlugin( const QString &plugin ) { if( !loadPluginSpec( plugin ) ) return false; @@ -141,7 +141,7 @@ bool PluginManager::loadPlugin( const char *plugin ) if( !spec->resolveDependencies( m_pluginSpecs ) ) { - nlinfo( "Error resolving dependencies for plugin spec %s", plugin ); + nlinfo( "Error resolving dependencies for plugin spec %s", plugin.toUtf8().data() ); return false; } diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 9b0d7a0dc..654c48c18 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,8 +51,8 @@ public: virtual QList plugins() const; QList loadQueue(); - bool loadPluginSpec( const char *plugin ); - bool loadPlugin( const char *plugin ); + bool loadPluginSpec( const QString &plugin ); + bool loadPlugin( const QString &plugin ); bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); void removePlugin( ExtensionSystem::IPluginSpec *plugin ); diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index c47a1c75d..cccc98509 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -156,7 +156,7 @@ void PluginView::onLoadClicked() } QApplication::setOverrideCursor( Qt::WaitCursor ); - bool success = m_pluginManager->loadPlugin( f.toAscii().data() ); + bool success = m_pluginManager->loadPlugin( f ); QApplication::setOverrideCursor( Qt::ArrowCursor ); if( !success ) From 0a26a5a1c6788f7af42b48148c94d171180103c0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:53:39 +0200 Subject: [PATCH 084/282] Why did I make these public in the first place? --HG-- branch : gsoc2014-dfighter --- code/studio/src/extension_system/plugin_manager.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 654c48c18..ca31e1552 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,10 +51,9 @@ public: virtual QList plugins() const; QList loadQueue(); - bool loadPluginSpec( const QString &plugin ); bool loadPlugin( const QString &plugin ); bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); - void removePlugin( ExtensionSystem::IPluginSpec *plugin ); + // Settings virtual void setSettings(QSettings *settings); @@ -63,6 +62,8 @@ public: void writeSettings(); private: + bool loadPluginSpec( const QString &plugin ); + void removePlugin( ExtensionSystem::IPluginSpec *plugin ); void setPluginState(PluginSpec *spec, int destState); void readPluginPaths(); bool loadQueue(PluginSpec *spec, QList &queue, QList &circularityCheckQueue); From 678cc254ee29b2a7a80e5843f900d495be06b5de Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Wed, 18 Jun 2014 15:10:31 +0530 Subject: [PATCH 085/282] updating functionality with some error fixes --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/dblayer.php | 383 +++++++++--------- .../ams_lib/autoload/plugincache.php | 34 +- .../ryzom_ams/ams_lib/translations/en.ini | 27 +- .../www/html/func/install_plugin.php | 118 +++++- .../www/html/templates/install_plugin.tpl | 3 +- .../ryzom_ams/www/html/templates/plugins.tpl | 2 +- 6 files changed, 360 insertions(+), 207 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php index b82e7ea8f..63b6bfc81 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php @@ -1,232 +1,245 @@ PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC - ); - $this->PDO = new PDO($dsn,$cfg['db'][$db]['user'],$cfg['db'][$db]['pass'], $opt); - } else { + $dsn = "mysql:"; + $dsn .= "host=" . $cfg['db'][$db]['host'] . ";"; + $dsn .= "dbname=" . $cfg['db'][$db]['name'] . ";"; + $dsn .= "port=" . $cfg['db'][$db]['port'] . ";"; + + $opt = array( + PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION, + PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC + ); + $this -> PDO = new PDO( $dsn, $cfg['db'][$db]['user'], $cfg['db'][$db]['pass'], $opt ); + } else { global $cfg; - $dsn = "mysql:"; - $dsn .= "host=". $cfg['db'][$dbn]['host'].";"; - $dsn .= "port=". $cfg['db'][$dbn]['port'].";"; + $dsn = "mysql:"; + $dsn .= "host=" . $cfg['db'][$dbn]['host'] . ";"; + $dsn .= "port=" . $cfg['db'][$dbn]['port'] . ";"; + + $opt = array( + PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION, + PDO :: ATTR_DEFAULT_FETCH_MODE => PDO :: FETCH_ASSOC + ); + $this -> PDO = new PDO( $dsn, $_POST['Username'], $_POST['Password'], $opt ); + } - $opt = array( - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC - ); - $this->PDO = new PDO($dsn,$_POST['Username'],$_POST['Password'], $opt); - } - - } + } /** - * execute a query that doesn't have any parameters - * @param $query the mysql query - * @return returns a PDOStatement object - */ - public function executeWithoutParams($query){ - $statement = $this->PDO->prepare($query); - $statement->execute(); - return $statement; - } + * execute a query that doesn't have any parameters + * + * @param $query the mysql query + * @return returns a PDOStatement object + */ + public function executeWithoutParams( $query ) { + $statement = $this -> PDO -> prepare( $query ); + $statement -> execute(); + return $statement; + } /** - * execute a query that has parameters - * @param $query the mysql query - * @param $params the parameters that are being used by the query - * @return returns a PDOStatement object - */ - public function execute($query,$params){ - $statement = $this->PDO->prepare($query); - $statement->execute($params); - return $statement; - } + * execute a query that has parameters + * + * @param $query the mysql query + * @param $params the parameters that are being used by the query + * @return returns a PDOStatement object + */ + public function execute( $query, $params ) { + $statement = $this -> PDO -> prepare( $query ); + $statement -> execute( $params ); + return $statement; + } - /** - * execute a query (an insertion query) that has parameters and return the id of it's insertion - * @param $query the mysql query - * @param $params the parameters that are being used by the query - * @return returns the id of the last inserted element. - */ - public function executeReturnId($tb_name,$data){ - $field_values =':'. implode(',:', array_keys($data)); - $field_options = implode(',', array_keys($data)); - try{ - $sth = $this->PDO->prepare("INSERT INTO $tb_name ($field_options) VALUE ($field_values)"); - foreach ($data as $key => $value ) - { - $sth->bindValue(":$key", $value); - } - $this->PDO->beginTransaction(); - //execution - $sth->execute(); - $lastId =$this->PDO->lastInsertId(); - $this->PDO->commit(); - }catch (Exception $e) - { - //for rolling back the changes during transaction - $this->PDO->rollBack(); - throw new Exception("error in inseting"); - } - return $lastId; - } - - /** + * execute a query (an insertion query) that has parameters and return the id of it's insertion * + * @param $query the mysql query + * @param $params the parameters that are being used by the query + * @return returns the id of the last inserted element. + */ + public function executeReturnId( $tb_name, $data ) { + $field_values = ':' . implode( ',:', array_keys( $data ) ); + $field_options = implode( ',', array_keys( $data ) ); + try { + $sth = $this -> PDO -> prepare( "INSERT INTO $tb_name ($field_options) VALUE ($field_values)" ); + foreach ( $data as $key => $value ) + { + $sth -> bindValue( ":$key", $value ); + } + $this -> PDO -> beginTransaction(); + $sth -> execute(); + $lastId = $this -> PDO -> lastInsertId(); + $this -> PDO -> commit(); + } + catch ( Exception $e ) + { + // for rolling back the changes during transaction + $this -> PDO -> rollBack(); + throw new Exception( "error in inseting" ); + } + return $lastId; + } + + /** * Select function using prepared statement + * * @param string $tb_name Table Name to Select * @param array $data Associative array * @param string $where where to select * @return statement object */ - public function selectWithParameter($param, $tb_name, $data, $where) - { - try{ - $sth = $this->PDO->prepare("SELECT $param FROM $tb_name WHERE $where"); - $this->PDO->beginTransaction(); - $sth->execute($data); - $this->PDO->commit(); - }catch(Exception $e) - { - $this->PDO->rollBack(); - throw new Exception("error selection"); - return false; - } + public function selectWithParameter( $param, $tb_name, $data, $where ) + { + try { + $sth = $this -> PDO -> prepare( "SELECT $param FROM $tb_name WHERE $where" ); + $this -> PDO -> beginTransaction(); + $sth -> execute( $data ); + $this -> PDO -> commit(); + } + catch( Exception $e ) + { + $this -> PDO -> rollBack(); + throw new Exception( "error selection" ); + return false; + } return $sth; - } - + } + /** - * * Select function using prepared statement + * * @param string $tb_name Table Name to Select * @param array $data Associative array * @param string $where where to select * @return statement object */ - public function select($tb_name, $data ,$where) - { - try{ - $sth = $this->PDO->prepare("SELECT * FROM $tb_name WHERE $where"); - $this->PDO->beginTransaction(); - $sth->execute($data); - $this->PDO->commit(); - }catch(Exception $e) - { - $this->PDO->rollBack(); - throw new Exception("error selection"); - return false; - } + public function select( $tb_name, $data , $where ) + { + try { + $sth = $this -> PDO -> prepare( "SELECT * FROM $tb_name WHERE $where" ); + $this -> PDO -> beginTransaction(); + $sth -> execute( $data ); + $this -> PDO -> commit(); + } + catch( Exception $e ) + { + $this -> PDO -> rollBack(); + throw new Exception( "error selection" ); + return false; + } return $sth; - } - + } + /** - * * Update function with prepared statement + * * @param string $tb_name name of the table * @param array $data associative array with values * @param string $where where part * @throws Exception error in updating */ - public function update($tb_name, $data, $where) - { - $field_option_values=null; - foreach ($data as $key => $value) - { - $field_option_values.=",$key".'=:'.$value; - } - $field_option_values = ltrim($field_option_values,','); - try { - $sth = $this->PDO->prepare("UPDATE $tb_name SET $field_option_values WHERE $where "); - - foreach ($data as $key => $value) - { - $sth->bindValue(":$key", $value); - } - $this->PDO->beginTransaction(); - $sth->execute(); - $this->PDO->commit(); - }catch (Exception $e) - { - $this->PDO->rollBack(); - throw new Exception('error in updating'); - } - } + public function update( $tb_name, $data, $where ) + { + $field_option_values = null; + foreach ( $data as $key => $value ) + { + $field_option_values .= ",$key" . '=:' . $key; + } + $field_option_values = ltrim( $field_option_values, ',' ); + try { + $sth = $this -> PDO -> prepare( "UPDATE $tb_name SET $field_option_values WHERE $where " ); + + foreach ( $data as $key => $value ) + { + $sth -> bindValue( ":$key", $value ); + } + $this -> PDO -> beginTransaction(); + $sth -> execute(); + $this -> PDO -> commit(); + } + catch ( Exception $e ) + { + $this -> PDO -> rollBack(); + throw new Exception( 'error in updating' ); + return false; + } + return true; + } + /** - * * insert function using prepared statements + * * @param string $tb_name Name of the table to insert in * @param array $data Associative array of data to insert */ - - public function insert($tb_name, $data) - { - $field_values =':'. implode(',:', array_keys($data)); - $field_options = implode(',', array_keys($data)); - try{ - $sth = $this->PDO->prepare("INSERT INTO $tb_name ($field_options) VALUE ($field_values)"); - foreach ($data as $key => $value ) - { - $sth->bindValue(":$key", $value); - } - $this->PDO->beginTransaction(); - //execution - $sth->execute(); - $this->PDO->commit(); - - }catch (Exception $e) - { - //for rolling back the changes during transaction - $this->PDO->rollBack(); - throw new Exception("error in inseting"); - } - } - + public function insert( $tb_name, $data ) + { + $field_values = ':' . implode( ',:', array_keys( $data ) ); + $field_options = implode( ',', array_keys( $data ) ); + try { + $sth = $this -> PDO -> prepare( "INSERT INTO $tb_name ($field_options) VALUE ($field_values)" ); + foreach ( $data as $key => $value ) + { + + $sth -> bindValue( ":$key", $value ); + } + $this -> PDO -> beginTransaction(); + // execution + $sth -> execute(); + $this -> PDO -> commit(); + + } + catch ( Exception $e ) + { + // for rolling back the changes during transaction + $this -> PDO -> rollBack(); + throw new Exception( "error in inseting" ); + } + } + /** - * * Delete database entery using prepared statement - * @param string $tb_name - * @param string $where + * + * @param string $tb_name + * @param string $where * @throws error in deleting */ - public function delete($tb_name, $where) - { + public function delete( $tb_name, $data, $where ) + { try { - $sth = $this->prepare("DELETE FROM $tb_name WHERE $where"); - $this->PDO->beginTransaction(); - $sth->execute(); - $this->PDO->commit(); - } - catch (Exception $e) - { - $this->rollBack(); - throw new Exception("error in deleting"); - } - - } -} + $sth = $this -> PDO -> prepare( "DELETE FROM $tb_name WHERE $where" ); + $this -> PDO -> beginTransaction(); + $sth -> execute( $data ); + $this -> PDO -> commit(); + } + catch ( Exception $e ) + { + $this -> rollBack(); + throw new Exception( "error in deleting" ); + } + + } + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index bba6e3fb1..1f0ef9bf6 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -26,10 +26,10 @@ class Plugincache { public function set( $values ) { $this -> setId( $values['Id'] ); $this -> setPluginName( $values['Name'] ); - $this -> setPluginType( $values['Type'] ); - $this -> setPluginPermission( $values['Permission'] ); - $this -> setPluginStatus( $values['Status'] ); - $this -> setPluginInfo( json_decode( $values['Info'] ) ); + $this -> setPluginType( $values['Type'] ); + $this -> setPluginPermission( $values['Permission'] ); + $this -> setPluginStatus( $values['Status'] ); + $this -> setPluginInfo( json_decode( $values['Info'] ) ); } /** @@ -140,4 +140,30 @@ class Plugincache { $this -> plugin_info = $p_n; } + + /** + * some more plugin function that requires during plugin operations + * + * / + * + * + * /** + * function to remove a non empty directory + * + * @param $dir directory address + * @return boolean + */ + public static function rrmdir( $dir ) { + if ( is_dir( $dir ) ) { + $objects = scandir( $dir ); + foreach ( $objects as $object ) { + if ( $object != "." && $object != ".." ) { + if ( filetype( $dir . "/" . $object ) == "dir" ) rmdir( $dir . "/" . $object ); + else unlink( $dir . "/" . $object ); + } + } + reset( $objects ); + return rmdir( $dir ); + } + } } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini index 4c8b545ec..548b2ea06 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini @@ -5,6 +5,9 @@ login_info = "Please enter your MySQL Username and Password to install the database.
This is being loaded because the is_installed file is missing.
This process will take about 30 seconds." login_here = "here" +[ams_content] +ams_title="Ryzom Account Mangement System" + [dashboard] home_title = "Introduction" home_info = "Welcome to the Ryzom Core - Account Management System" @@ -66,11 +69,12 @@ plugin_status = "Status" ip_success = "Plugin added succesfuly." plugin_actions = "Actions" dp_success = "Plugin deleted successfuly" -dp_error = "Error in deleting plugin.Please try again later" -ac_success = "Plugin Activated successfuly" -ac_error = "Plugin facing some error in activating. Please try again later" -dc_success = "Plugin de-Activated successfuly" -dc_error = "Plugin facing some error in de-activating. Please try again later" +dp_error = "Error in deleting plugin.Please try again later." +ac_success = "Plugin Activated successfuly." +ac_error = "Plugin facing some error in activating. Please try again later." +dc_success = "Plugin de-Activated successfuly." +dc_error = "Plugin facing some error in de-activating. Please try again later." +up_success = "Update added successfully. Go to Updates page for installing updates." [install_plugin] ip_title = "Install a new Plugin" @@ -79,6 +83,15 @@ ip_support = "Upload the plugin archieve to install.
The following file exte ip_info_nfound = "Info file not found in the Plugin.Please recheck" ip_file_nfnd="Please upload a plugin before clicking on install button" +[plugins_update] +up_title = "Updates for Plugins" +up_info = "Here you can see the entire list of available updates for plugins." +up_serial = "Serial No." +plugin_name = "Name" +plugin_version = "Version" +up_updated_version = "New Version" +up_action = "Actions" + [show_ticket] t_title = "Ticket" title = "Title" @@ -152,8 +165,8 @@ go_home = "Go Home" userlist_info = "welcome to the userlist" [login] -login_info = "Please login with your Username and Password." -login_error_message = "The username/password were not correct!" +login_info = "Please login with your Email/Username and Password." +login_error_message = "The Email/username/password were not correct!" login_register_message ="Register If you don't have an account yet, create one" login_here = "here" login_forgot_password_message = "In case you forgot your password, click" diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php index 5376dfd02..1383dea8a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php @@ -8,7 +8,9 @@ */ function install_plugin() { - // if logged in + $result = array(); + + // if logged in if ( WebUsers :: isLoggedIn() ) { // path of temporary folder for storing files @@ -30,13 +32,32 @@ function install_plugin() { $target_path = "../../ams_lib/plugins/$dir"; //path in which the zip extraction is to be done $destination = "../../ams_lib/plugins/"; - // checking for the command to install plugin is given or not + // scanning plugin folder if plugin with same name is already exists or not + $x = checkForUpdate( $dir, $destination, $fileTmpLoc, $temp_path ); + if ( $x == '1' ) + { + echo "update found"; + exit(); + } + else if ( $x == '2' ) + { + echo "Plugin already exists with same name ."; + exit(); + } + else if ( $x == '3' ) + { + echo "Update info is not present in the update"; + exit(); + } + + + // checking for the command to install plugin is given or not if ( !isset( $_POST['install_plugin'] ) ) { if ( ( $_FILES["file"]["type"] == 'application/zip' ) ) { if ( move_uploaded_file( $fileTmpLoc, $temp_path . "/" . $fileName ) ) { - echo "$fileName upload is complete."; + echo "$fileName upload is complete.
" . "
"; exit(); } else @@ -59,15 +80,14 @@ function install_plugin() { { if ( file_exists( $target_path . "/.info" ) ) { - $result = array(); - $result = readPluginFile( ".info", $target_path ); + $result = readPluginFile( ".info", $target_path ); // sending all info to the database $install_result = array(); $install_result['FileName'] = $target_path; $install_result['Name'] = $result['PluginName']; - // $install_result['Type'] = $result['type']; - if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) + $install_result['Type'] = $result['Type']; + if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) { $install_result['Permission'] = 'admin'; } @@ -165,4 +185,86 @@ function readPluginFile( $fileName, $target_path ) } fclose( $file_handle ); return $result; - } + } + +/** + * function to check for updates or + * if the same plugin already exists + * also, if the update founds ,check for the update info in the .info file. + * Update is saved in the temp direcotry with pluginName_version.zip + * + * @param $fileName file which is uploaded in .zip extension + * @param $findPath where we have to look for the installed plugins + * @param $tempFile path for the temporary file + * @param $tempPath path where we have to store the update + * @return 2 if plugin already exists and update not found + * @return 3 if update info tag not found in .info file + */ +function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) + { + // check for plugin if exists + $file = scandir( $findPath ); + foreach( $file as $key => $value ) + { + if ( strcmp( $value, $fileName ) == 0 ) + { + if ( !file_exists( $tempPath . "/test" ) ) + { + mkdir( $tempPath . "/test" ); + } + if ( zipExtraction( $tempFile, $tempPath . "/test/" ) ) + { + $result = readPluginFile( ".info", $tempPath . "/test/" . $fileName ); + + // check for the version for the plugin + $db = new DBLayer( "lib" ); + $sth = $db -> select( "plugins", array( ':name' => $result['PluginName'] ), "Name = :name" ); + $info = $sth -> fetch(); + $info['Info'] = json_decode( $info['Info'] ); + + // the two versions from main plugin and the updated part + $new_version = explode( '.', $result['Version'] ); + $pre_version = explode( '.', $info['Info'] -> Version ); + + // For all plugins we have used semantic versioning + // Format: X.Y.Z ,X->Major, Y->Minor, Z->Patch + // change in the X Y & Z values refer the type of change in the plugin. + // for initial development only Minor an Patch MUST be 0. + // if there is bug fix then there MUST be an increment in the Z value. + // if there is change in the functionality or addition of new functionality + // then there MUST be an increment in the Y value. + // When there is increment in the X value , Y and Z MUST be 0. + // comparing if there is some change + if ( !array_intersect( $new_version , $pre_version ) ) + { + // removing the uploaded file + Plugincache :: rrmdir( $tempPath . "/test/" . $fileName ); + return '2'; + } + else + { + // check for update info if exists + if ( !array_key_exists( 'UpdateInfo', $result ) ) + { + return '3'; //update info tag not found + } + else + { + // storing update in the temp directory + // format of update save + if ( move_uploaded_file( $tempFile, $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) ) { + // setting update information in the database + $dbr = new DBLayer( "lib" ); + $update['PluginId'] = $info['Id']; + $update['UpdatePath'] = $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip"; + $update['UpdateInfo'] = json_encode( $result ); + $dbr -> insert( "updates", $update ); + header( "Location: index.php?page=plugins&result=7" ); + exit; + } + } + } + } + } + } + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl index 27a4cec49..968d6cec4 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/install_plugin.tpl @@ -22,8 +22,7 @@

{if isset($smarty.get.result) and $smarty.get.result eq "0"}

{$ip_file_nfnd}

{/if} - {if isset($smarty.get.result) and $smarty.get.result eq "2"}

{$ip_info_nfound}

{/if} -
+ {if isset($smarty.get.result) and $smarty.get.result eq "2"}

{$ip_info_nfound}

{/if} {$ip_message} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl index cac67147a..4aa6e7e3b 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl @@ -16,6 +16,7 @@ {if isset($smarty.get.result) and $smarty.get.result eq "4"}

{$ac_error}

{/if} {if isset($smarty.get.result) and $smarty.get.result eq "5"}

{$dc_success}

{/if} {if isset($smarty.get.result) and $smarty.get.result eq "6"}

{$dc_error}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "7"}

{$up_success}

{/if}

{$plugin_info}

@@ -65,4 +66,3 @@
{/block} - From f1ff5e7d2c058f9b57b114f0cac553afb7d44351 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 16:48:33 +0200 Subject: [PATCH 086/282] Added color picking support to the GUI Editor. TODO: change all the widget definitions. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 59 ++++++++++++++++--- .../gui_editor/property_browser_ctrl.h | 3 +- .../gui_editor/widgets/CtrlTextButton.xml | 29 +++++---- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 82330bfaf..da4ff1499 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -22,6 +22,7 @@ #include "nel/gui/widget_manager.h" #include #include "widget_info_tree.h" +#include namespace GUIEditor { @@ -62,8 +63,8 @@ namespace GUIEditor void CPropBrowserCtrl::clear() { browser->clear(); - disconnect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); } void CPropBrowserCtrl::onSelectionChanged( std::string &id ) @@ -71,16 +72,16 @@ namespace GUIEditor if( browser == NULL ) return; - disconnect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); browser->clear(); CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( id ); if( e == NULL ) { - connect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); return; } @@ -90,11 +91,11 @@ namespace GUIEditor std::string n = e->getClassName(); setupProperties( n, e ); - connect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); } - void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop ) + void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop, const QVariant &v ) { QString propName = prop->propertyName(); QString propValue = prop->valueText(); @@ -107,6 +108,14 @@ namespace GUIEditor propValue = p->value().toString(); } + if( v.type() == QVariant::Color ) + { + QColor c = v.value< QColor >(); + QString val = "%1 %2 %3 %4"; + val = val.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() ); + propValue = val; + } + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) return; @@ -163,6 +172,38 @@ namespace GUIEditor NLMISC::fromString( element->getProperty( prop.propName ), value ); v = value; } + else + if( prop.propType == "color" ) + { + p = propertyMgr->addProperty( QVariant::Color, prop.propName.c_str() ); + + std::string s = element->getProperty( prop.propName ); + // Parse string into a QColor + QString qs = s.c_str(); + QStringList l = qs.split( " " ); + int r = l[ 0 ].toInt(); + int g = l[ 1 ].toInt(); + int b = l[ 2 ].toInt(); + int a = l[ 3 ].toInt(); + + QColor value; + value.setRed( r ); + value.setGreen( g ); + value.setBlue( b ); + value.setAlpha( a ); + v = value; + + + // Remove the subproperties + QList< QtProperty* > pl = p->subProperties(); + QListIterator< QtProperty* > itr( pl ); + while( itr.hasNext() ) + { + delete itr.next(); + } + pl.clear(); + + } if( p == NULL ) return; diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index 4c5ebce63..e126b86ea 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -26,6 +26,7 @@ class QtTreePropertyBrowser; class QtVariantPropertyManager; class QtProperty; +class QVariant; namespace NLGUI { @@ -53,7 +54,7 @@ namespace GUIEditor void onSelectionChanged( std::string &id ); private Q_SLOTS: - void onPropertyChanged( QtProperty *prop ); + void onPropertyChanged( QtProperty *prop, const QVariant &v ); private: void setupProperties( const std::string &type, const NLGUI::CInterfaceElement *element ); diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml index cacc45ccb..32541cc1f 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml @@ -2,7 +2,6 @@
CtrlTextButton CCtrlTextButton - text_button CtrlBaseButton false @@ -12,27 +11,27 @@ tx_normal string - but + tx_pushed string - but + tx_over string - but_over + hardtext string - text + wmargin int - 20 + 0 wmin @@ -61,32 +60,32 @@ text_color_normal - string + color 255 255 255 255 text_color_pushed - string + color 255 255 255 255 text_color_over - string + color 255 255 255 255 text_shadow_color_normal - string + color 0 0 0 255 text_shadow_color_pushed - string + color 0 0 0 255 text_shadow_color_over - string + color 0 0 0 255 @@ -116,7 +115,7 @@ color - string + color 255 255 255 255 @@ -136,7 +135,7 @@ shadow_color - string + color 0 0 0 255 @@ -152,7 +151,7 @@ line_maxw int - 200 + 0 multi_line_space From 4d1d52fc73a0488dac22d95fc9dd76ff52dedcf6 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Thu, 19 Jun 2014 14:53:49 +0530 Subject: [PATCH 087/282] check functionality for existing updates --HG-- branch : Gsoc14-ryzomAppImprovements --- .../www/html/func/install_plugin.php | 60 +++++++++++++++---- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php index 1383dea8a..1ea950d38 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php @@ -212,6 +212,8 @@ function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) { mkdir( $tempPath . "/test" ); } + + // extracting the update if ( zipExtraction( $tempFile, $tempPath . "/test/" ) ) { $result = readPluginFile( ".info", $tempPath . "/test/" . $fileName ); @@ -246,25 +248,59 @@ function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) // check for update info if exists if ( !array_key_exists( 'UpdateInfo', $result ) ) { - return '3'; //update info tag not found + return '3'; //update info tag not found } else { - // storing update in the temp directory - // format of update save - if ( move_uploaded_file( $tempFile, $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) ) { - // setting update information in the database - $dbr = new DBLayer( "lib" ); - $update['PluginId'] = $info['Id']; - $update['UpdatePath'] = $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip"; - $update['UpdateInfo'] = json_encode( $result ); - $dbr -> insert( "updates", $update ); - header( "Location: index.php?page=plugins&result=7" ); - exit; + // check if update already exists + if ( pluginUpdateExists( $info['Id'], $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) ) + { + echo "Update already exists"; + exit; } + else { + // removing the preivous update + $dbr = new DBLayer( "lib" ); + $dbr -> delete( "updates", array( 'id' => $info['Id'] ), "PluginId=:id" ); + // storing update in the temp directory + // format of update save + if ( move_uploaded_file( $tempFile, $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip" ) ) { + // setting update information in the database + $update['PluginId'] = $info['Id']; + $update['UpdatePath'] = $tempPath . "/" . trim( $fileName, ".zip" ) . "_" . $result['Version'] . ".zip"; + $update['UpdateInfo'] = json_encode( $result ); + $dbr -> insert( "updates", $update ); + header( "Location: index.php?page=plugins&result=7" ); + exit; + } + } } } } } } + } + +/** + * Function to check for the update of a plugin already exists + * + * @param $pluginId id of the plugin for which update is available + * @param $updatePath path of the new update + * @return boolean if update for a plugin already exists or + * if update of same version is uploading + */ +function PluginUpdateExists( $pluginId, $updatePath ) + { + $db = new DBLayer( 'lib' ); + $sth = $db -> selectWithParameter( "UpdatePath", "updates", array( 'pluginid' => $pluginId ), "PluginId=:pluginid" ); + $row = $sth -> fetch(); + if ( $updatePath == $row['UpdatePath'] ) + { + return true; + } + else + { + rmdir( $row['UpdatePath'] ); + return false; + } } From f09e4e48a542ce42a09940a422b497c19234ef49 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Thu, 19 Jun 2014 17:11:10 +0530 Subject: [PATCH 088/282] template for updates of plugins --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 41 ++++++++++++++----- .../ryzom_ams/ams_lib/translations/en.ini | 4 +- .../ryzom_ams/www/html/inc/plugins_update.php | 36 ++++++++++++++++ 3 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins_update.php diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index 1f0ef9bf6..09bd942b3 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -14,7 +14,7 @@ class Plugincache { private $plugin_permission; private $plugin_status; private $plugin_info = array(); - + private $update_info = array(); /** * A constructor. * Empty constructor @@ -26,15 +26,17 @@ class Plugincache { public function set( $values ) { $this -> setId( $values['Id'] ); $this -> setPluginName( $values['Name'] ); - $this -> setPluginType( $values['Type'] ); - $this -> setPluginPermission( $values['Permission'] ); - $this -> setPluginStatus( $values['Status'] ); - $this -> setPluginInfo( json_decode( $values['Info'] ) ); + $this -> setPluginType( $values['Type'] ); + $this -> setPluginPermission( $values['Permission'] ); + $this -> setPluginStatus( $values['Status'] ); + $this -> setPluginInfo( json_decode( $values['Info'] ) ); + @$this -> setUpdateInfo( json_decode( $values['UpdateInfo'] ) ); } /** * loads the object's attributes. */ + public function load_With_SID() { $dbl = new DBLayer( "lib" ); $statement = $dbl -> executeWithoutParams( "SELECT * FROM plugins" ); @@ -140,14 +142,33 @@ class Plugincache { $this -> plugin_info = $p_n; } + /** + * functionalities for plugin updates + */ /** - * some more plugin function that requires during plugin operations - * - * / + * set update info attribute array of the object. * + * @param $p_n array + */ + public function setUpdateInfo( $p_n ) { + $this -> update_info = $p_n; + } + + /** + * get update info array attribute of the object. + */ + public function getUpdateInfo() { + return $this -> update_info; + } + + + /** + * some more plugin function that requires during plugin operations * - * /** + */ + + /** * function to remove a non empty directory * * @param $dir directory address @@ -166,4 +187,4 @@ class Plugincache { return rmdir( $dir ); } } - } + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini index 548b2ea06..d324acb3a 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini @@ -86,11 +86,11 @@ ip_file_nfnd="Please upload a plugin before clicking on install button" [plugins_update] up_title = "Updates for Plugins" up_info = "Here you can see the entire list of available updates for plugins." -up_serial = "Serial No." +up_description = "Updates Info" plugin_name = "Name" plugin_version = "Version" up_updated_version = "New Version" -up_action = "Actions" +up_actions = "Actions" [show_ticket] t_title = "Ticket" diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins_update.php b/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins_update.php new file mode 100644 index 000000000..89d547860 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/inc/plugins_update.php @@ -0,0 +1,36 @@ + getElements(), Array( "getId", "getPluginName", "getPluginInfo", "getUpdateInfo" ), Array( "id", "plugin_name", "plugin_info", "update_info" ) ); + $pageResult['links'] = $pagination -> getLinks( 5 ); + $pageResult['lastPage'] = $pagination -> getLast(); + $pageResult['currentPage'] = $pagination -> getCurrent(); + + global $INGAME_WEBPATH; + $pageResult['ingame_webpath'] = $INGAME_WEBPATH; + + // check if shard is online + try { + $dbs = new DBLayer( "shard" ); + $pageResult['shard'] = "online"; + } + catch( PDOException $e ) { + $pageResult['shard'] = "offline"; + } + return( $pageResult ); + } else { + // ERROR: No access! + $_SESSION['error_code'] = "403"; + header( "Location: index.php?page=error" ); + exit; + } + } From ae7503df36ca01e076b80b7ff385dbd21824f643 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Thu, 19 Jun 2014 17:16:24 +0530 Subject: [PATCH 089/282] template with list of updates --HG-- branch : Gsoc14-ryzomAppImprovements --- .../www/html/templates/plugins_update.tpl | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins_update.tpl diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins_update.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins_update.tpl new file mode 100644 index 000000000..afa93d80f --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins_update.tpl @@ -0,0 +1,50 @@ +{block name=content} +
+
+
+

{$up_title}

+
+ + + +
+
+
+

{$up_info}

+
{$plugin_status}{$plugin_name}{$plugin_name} {$plugin_version}{$plugin_description}{$plugin_type}{$plugin_description}{$plugin_type} {$plugin_permission}{$plugin_actions}
{$element.plugin_info->Description} {$element.plugin_type} {$element.plugin_permission} + {if ($element.plugin_status) eq "0"}{/if} + {if ($element.plugin_status) eq "1"}{/if}
+ + + + + + + + + + + {foreach from=$plug item=element} + + + + + + + {/foreach} + + +
{$plugin_name}{$plugin_version}{$up_updated_version}{$up_description}{$up_actions}
{$element.plugin_name}{$element.plugin_info->Version}{$element.update_info->Version}{$element.update_info->UpdateInfo} +
+
+
    +
  • «
  • + {foreach from=$links item=link} +
  • {$link}
  • + {/foreach} +
  • »
  • +
+
+
+ + + +{/block} From bb7fa7987b59cc8cb5f9cb2d252c4df7309cf957 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Jun 2014 17:21:11 +0200 Subject: [PATCH 090/282] More widgets can use the color picker now. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/widgets/CtrlBaseButton.xml | 8 ++++---- .../plugins/gui_editor/widgets/CtrlButton.xml | 7 +++---- .../gui_editor/widgets/CtrlColPick.xml | 1 - .../plugins/gui_editor/widgets/CtrlScroll.xml | 1 - .../widgets/DBGroupSelectNumber.xml | 1 - .../plugins/gui_editor/widgets/DBViewBar.xml | 3 +-- .../plugins/gui_editor/widgets/DBViewBar3.xml | 13 ++++++------- .../gui_editor/widgets/DBViewDigit.xml | 5 ++--- .../gui_editor/widgets/DBViewNumber.xml | 3 +-- .../gui_editor/widgets/DBViewQuantity.xml | 7 +++---- .../plugins/gui_editor/widgets/GroupCell.xml | 2 +- .../gui_editor/widgets/GroupContainer.xml | 3 +-- .../gui_editor/widgets/GroupEditBox.xml | 1 - .../plugins/gui_editor/widgets/GroupFrame.xml | 2 +- .../plugins/gui_editor/widgets/GroupHTML.xml | 19 +++++++++---------- .../gui_editor/widgets/GroupHeader.xml | 1 - .../plugins/gui_editor/widgets/GroupList.xml | 3 +-- .../plugins/gui_editor/widgets/GroupMenu.xml | 15 +++++++-------- .../plugins/gui_editor/widgets/GroupModal.xml | 1 - .../gui_editor/widgets/GroupParagraph.xml | 2 +- .../gui_editor/widgets/GroupScrollText.xml | 1 - .../plugins/gui_editor/widgets/GroupTab.xml | 1 - .../plugins/gui_editor/widgets/GroupTable.xml | 3 +-- .../plugins/gui_editor/widgets/GroupTree.xml | 7 +++---- .../gui_editor/widgets/InterfaceGroup.xml | 1 - .../widgets/InterfaceGroupWheel.xml | 1 - .../plugins/gui_editor/widgets/ViewBitmap.xml | 1 - .../gui_editor/widgets/ViewBitmapCombo.xml | 1 - .../plugins/gui_editor/widgets/ViewText.xml | 9 ++++----- .../gui_editor/widgets/ViewTextFormated.xml | 1 - .../plugins/gui_editor/widgets/ViewTextID.xml | 1 - .../gui_editor/widgets/ViewTextIDFormated.xml | 1 - 32 files changed, 49 insertions(+), 77 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml index 42e2bdef1..4c7d915be 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml @@ -11,7 +11,7 @@ button_type string - push_button + toggle_button pushed @@ -30,17 +30,17 @@ color - string + color 255 255 255 255 col_pushed - string + color 255 255 255 255 col_over - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml index fb2514e7c..12b82e7f6 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml @@ -2,7 +2,6 @@
CtrlButton CCtrlButton - button CtrlBaseButton false @@ -12,17 +11,17 @@ tx_normal string - log_but_r.tga + tx_pushed string - log_but_r.tga + tx_over string - log_but_over_r.tga + scale diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml index 6ac05fbcc..ea2ba6171 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml @@ -2,7 +2,6 @@
CtrlColPick CCtrlColPick - colpick CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml index a5c8dae1e..1ad970f31 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml @@ -2,7 +2,6 @@
CtrlScroll CCtrlScroll - scroll CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml index 63be51b5e..624ded887 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml @@ -2,7 +2,6 @@
DBGroupSelectNumber CDBGroupSelectNumber - select_number InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml index c7f2e488c..c7f644fa4 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml @@ -2,7 +2,6 @@
DBViewBar CDBViewBar - bar ViewBitmap false @@ -26,7 +25,7 @@ color_negative - string + color 0 0 0 0 diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml index 9b12a637a..8295c5f30 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml @@ -2,7 +2,6 @@
DBViewBar3 CDBViewBar3 - bar3 ViewBitmap false @@ -41,32 +40,32 @@ color1 - string + color 255 255 255 255 color2 - string + color 255 255 255 255 color3 - string + color 255 255 255 255 color1_negative - string + color 0 0 0 0 color2_negative - string + color 0 0 0 0 color3_negative - string + color 0 0 0 0 diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml index 8a2a28831..0c12445f9 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml @@ -2,7 +2,6 @@
DBViewDigit CDBViewDigit - digit CtrlBase false @@ -12,7 +11,7 @@ value string - 0 + numdigit @@ -26,7 +25,7 @@ color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml index 95a43025e..c1861df61 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml @@ -2,7 +2,6 @@
DBViewNumber CDBViewNumber - text_number ViewText false @@ -12,7 +11,7 @@ value string - 0 + positive diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml index 1b812bccf..c24379c96 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml @@ -2,7 +2,6 @@
DBViewQuantity CDBViewQuantity - text_quantity ViewText false @@ -12,17 +11,17 @@ value string - 0 + valuemax string - 100 + emptytext string - empty text + diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml b/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml index 8f8592771..ad0ae6e02 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml @@ -30,7 +30,7 @@ bgcolor - string + color 0 0 0 0 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml index bdbf9931a..b374bca19 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml @@ -2,7 +2,6 @@
GroupContainer CGroupContainer - container InterfaceGroup false @@ -46,7 +45,7 @@ header_color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml b/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml index 603af6c04..31ca205c7 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml @@ -2,7 +2,6 @@
GroupEditBox CGroupEditBox - edit_box InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml b/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml index f414e67e7..c7ac89fa2 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml @@ -15,7 +15,7 @@ color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml index b76fe4cd4..5f0521be8 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml @@ -2,7 +2,6 @@
GroupHTML CGroupHTML - html GroupScrollText false @@ -21,47 +20,47 @@ background_color - string + color 0 0 0 255 error_color - string + color 255 0 0 255 link_color - string + color 0 0 255 255 h1_color - string + color 255 255 255 255 h2_color - string + color 255 255 255 255 h3_color - string + color 255 255 255 255 h4_color - string + color 255 255 255 255 h5_color - string + color 255 255 255 255 h6_color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml index bcb517c66..cc96fd742 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml @@ -2,7 +2,6 @@
GroupHeader CGroupHeader - header GroupList false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupList.xml b/code/studio/src/plugins/gui_editor/widgets/GroupList.xml index 1858cd5b3..3ca2db95c 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupList.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupList.xml @@ -2,7 +2,6 @@
GroupList CGroupList - list InterfaceGroup false @@ -41,7 +40,7 @@ col_over - string + color 255 255 255 32 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml b/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml index 4739f0352..cdd42ba95 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml @@ -2,7 +2,6 @@
GroupMenu CGroupMenu - menu GroupModal false @@ -16,7 +15,7 @@ color - string + color 255 255 255 255 @@ -26,32 +25,32 @@ shadow_color - string + color 0 0 0 255 color_over - string + color 255 255 255 255 shadow_color_over - string + color 0 0 0 255 highlight_over - string + color 128 0 0 255 color_grayed - string + color 128 128 128 255 shadow_color_grayed - string + color 0 0 0 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml b/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml index afc5005c8..034e3025e 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml @@ -2,7 +2,6 @@
GroupModal CGroupModal - modal GroupFrame false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml b/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml index f05806757..e561e8c5f 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml @@ -30,7 +30,7 @@ col_over - string + color 255 255 255 32 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml b/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml index 8cefb8df2..95719398d 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml @@ -2,7 +2,6 @@
GroupScrollText CGroupScrollText - scroll_text InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml index 69db79466..df148a0a3 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml @@ -2,7 +2,6 @@
GroupTab CGroupTab - tab InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml index 9c2240adc..9fa957741 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml @@ -2,7 +2,6 @@
GroupTable CGroupTable - table InterfaceGroup false @@ -26,7 +25,7 @@ bgcolor - string + color 0 0 0 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml index 6bd10ad9f..73b1dea3b 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml @@ -2,7 +2,6 @@
GroupTree CGroupTree - tree InterfaceGroup false @@ -11,17 +10,17 @@ col_over - string + color 255 255 255 128 col_select - string + color 255 128 128 128 col_over_back - string + color 64 64 64 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml index c9a8c1546..b9e99d336 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml @@ -2,7 +2,6 @@
InterfaceGroup CInterfaceGroup - interface_group CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml index 51590ee33..62d67cc0a 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml @@ -2,7 +2,6 @@
InterfaceGroupWheel CInterfaceGroupWheel - group_wheel InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index 8b931f78b..9da967b5a 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -2,7 +2,6 @@
ViewBitmap CViewBitmap - bitmap CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml index 190143be5..0b55f6932 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml @@ -2,7 +2,6 @@
ViewBitmapCombo CViewBitmapCombo - bitmap_combo CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml index 9490a1eee..fc4d30688 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml @@ -2,7 +2,6 @@
ViewText CViewText - text InterfaceElement false @@ -11,7 +10,7 @@ color - string + color 255 255 255 255 @@ -31,7 +30,7 @@ shadow_color - string + color 0 0 0 255 @@ -47,7 +46,7 @@ line_maxw int - 100 + 0 multi_line_space @@ -102,7 +101,7 @@ hardtext string - some text + hardtext_format diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml index c5749ca9c..cabd081f0 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml @@ -2,7 +2,6 @@
ViewTextFormated CViewTextFormated - text_formated ViewText false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml index b3edc86ab..52e010ec6 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml @@ -2,7 +2,6 @@
ViewTextID CViewTextID - text_id ViewText false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml index 3ac6c7962..af8dd54eb 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml @@ -2,7 +2,6 @@
ViewTextIDFormated CViewTextIDFormated - text_id_formated ViewTextID false From 1ce333bb00bfd55e06890403808b31288b88c8cd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Jun 2014 18:40:50 +0200 Subject: [PATCH 091/282] As Object Viewer no longer uses the QtOpenGL widget this is not needed. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/object_viewer/graphics_viewport.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp index 8cf6f3f60..0cec0be10 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp @@ -66,10 +66,6 @@ void CGraphicsViewport::init() //H_AUTO2 nldebug("CGraphicsViewport::init"); -#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) - makeCurrent(); -#endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC) - w->init(); Modules::objView().init( w->getDriver() ); Modules::psEdit().init(); From 49002d0250255498c261cf8ef1756629328f6893 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 15:09:13 +0200 Subject: [PATCH 092/282] Line endings... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index da4ff1499..1118a86bc 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -110,7 +110,7 @@ namespace GUIEditor if( v.type() == QVariant::Color ) { - QColor c = v.value< QColor >(); + QColor c = v.value< QColor >(); QString val = "%1 %2 %3 %4"; val = val.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() ); propValue = val; From 25df3c8afe18c5e1788e971cc8c7a4546cb53911 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 16:22:07 +0200 Subject: [PATCH 093/282] Button types can now be set using an enum property editor. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 87 ++++++++++++++++++- .../gui_editor/property_browser_ctrl.h | 4 + .../gui_editor/widgets/CtrlBaseButton.xml | 2 +- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 1118a86bc..77872d8b3 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -17,7 +17,9 @@ #include "property_browser_ctrl.h" #include "../../3rdparty/qtpropertybrowser/QtVariantPropertyManager" +#include "../../3rdparty/qtpropertybrowser/QtEnumPropertyManager" #include "../../3rdparty/qtpropertybrowser/QtTreePropertyBrowser" +#include "../../3rdparty/qtpropertybrowser/QtEnumEditorFactory" #include "nel/gui/interface_group.h" #include "nel/gui/widget_manager.h" #include @@ -26,16 +28,27 @@ namespace GUIEditor { + enum NELButtonTypes + { + BUTTON_TYPE_PUSH = 0, + BUTTON_TYPE_TOGGLE = 1, + BUTTON_TYPE_RADIO = 2 + }; + CPropBrowserCtrl::CPropBrowserCtrl() { browser = NULL; propertyMgr = new QtVariantPropertyManager; + enumMgr = new QtEnumPropertyManager; } CPropBrowserCtrl::~CPropBrowserCtrl() { + delete enumMgr; + enumMgr = NULL; delete propertyMgr; propertyMgr = NULL; + browser = NULL; } @@ -65,6 +78,9 @@ namespace GUIEditor browser->clear(); disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + + disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); } void CPropBrowserCtrl::onSelectionChanged( std::string &id ) @@ -74,6 +90,8 @@ namespace GUIEditor disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); browser->clear(); @@ -82,6 +100,8 @@ namespace GUIEditor { connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); return; } @@ -93,6 +113,8 @@ namespace GUIEditor setupProperties( n, e ); connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); } void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop, const QVariant &v ) @@ -107,7 +129,7 @@ namespace GUIEditor if( p != NULL ) propValue = p->value().toString(); } - + if( v.type() == QVariant::Color ) { QColor c = v.value< QColor >(); @@ -128,6 +150,32 @@ namespace GUIEditor e->setActive( active ); } + void CPropBrowserCtrl::onEnumPropertyChanged( QtProperty *prop, int value ) + { + QString propName = prop->propertyName(); + + if( propName == "button_type" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + if( ( value < 0 ) || ( value > 2 ) ) + return; + + std::string v; + + switch( value ) + { + case BUTTON_TYPE_PUSH: v = "push_button"; break; + case BUTTON_TYPE_TOGGLE: v = "toggle_button"; break; + case BUTTON_TYPE_RADIO: v = "radio_button"; break; + } + + e->setProperty( propName.toUtf8().constData(), v ); + } + } + void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) { std::map< std::string, SWidgetInfo >::iterator itr = widgetInfo.find( type ); @@ -144,6 +192,9 @@ namespace GUIEditor QtVariantEditorFactory *factory = new QtVariantEditorFactory; browser->setFactoryForManager( propertyMgr, factory ); + + QtEnumEditorFactory *efactory = new QtEnumEditorFactory; + browser->setFactoryForManager( enumMgr, efactory ); } void CPropBrowserCtrl::setupProperty( const SPropEntry &prop, const CInterfaceElement *element ) @@ -151,6 +202,40 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "button_type" ) + { + std::string btype = element->getProperty( prop.propName ); + if( btype.empty() ) + return; + + QStringList enums; + enums.push_back( "push_button" ); + enums.push_back( "toggle_button" ); + enums.push_back( "radio_button" ); + + int e = -1; + if( btype == "push_button" ) + e = BUTTON_TYPE_PUSH; + else + if( btype == "toggle_button" ) + e = BUTTON_TYPE_TOGGLE; + else + if( btype == "radio_button" ) + e = BUTTON_TYPE_RADIO; + + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index e126b86ea..648463bc6 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -25,6 +25,7 @@ class QtTreePropertyBrowser; class QtVariantPropertyManager; +class QtEnumPropertyManager; class QtProperty; class QVariant; @@ -55,6 +56,7 @@ namespace GUIEditor private Q_SLOTS: void onPropertyChanged( QtProperty *prop, const QVariant &v ); + void onEnumPropertyChanged( QtProperty *prop, int value ); private: void setupProperties( const std::string &type, const NLGUI::CInterfaceElement *element ); @@ -62,6 +64,8 @@ namespace GUIEditor QtTreePropertyBrowser *browser; QtVariantPropertyManager *propertyMgr; + QtEnumPropertyManager *enumMgr; + std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; }; diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml index 4c7d915be..72e362556 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml @@ -10,7 +10,7 @@ button_type - string + button_type toggle_button From 9e36082ff0f403139f405a3a04813e6893711e9d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 16:26:10 +0200 Subject: [PATCH 094/282] A little refactoring --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 39 ++++++++++--------- .../gui_editor/property_browser_ctrl.h | 3 ++ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 77872d8b3..c27d3ca6c 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -75,12 +75,8 @@ namespace GUIEditor void CPropBrowserCtrl::clear() { + disablePropertyWatchers(); browser->clear(); - disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - - disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); } void CPropBrowserCtrl::onSelectionChanged( std::string &id ) @@ -88,21 +84,13 @@ namespace GUIEditor if( browser == NULL ) return; - disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); - + disablePropertyWatchers(); browser->clear(); CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( id ); if( e == NULL ) { - connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); - + enablePropertyWatchers(); return; } @@ -111,10 +99,7 @@ namespace GUIEditor std::string n = e->getClassName(); setupProperties( n, e ); - connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + enablePropertyWatchers(); } void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop, const QVariant &v ) @@ -176,6 +161,22 @@ namespace GUIEditor } } + void CPropBrowserCtrl::enablePropertyWatchers() + { + connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + } + + void CPropBrowserCtrl::disablePropertyWatchers() + { + disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + } + void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) { std::map< std::string, SWidgetInfo >::iterator itr = widgetInfo.find( type ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index 648463bc6..f8d839bd6 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -59,6 +59,9 @@ namespace GUIEditor void onEnumPropertyChanged( QtProperty *prop, int value ); private: + void enablePropertyWatchers(); + void disablePropertyWatchers(); + void setupProperties( const std::string &type, const NLGUI::CInterfaceElement *element ); void setupProperty( const SPropEntry &prop, const NLGUI::CInterfaceElement *element ); From 1afe2d4a17cd7b3b36dd70c2bee072c6252f5fe5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 17:07:27 +0200 Subject: [PATCH 095/282] Text justification can now be set using an enum property editor. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 74 +++++++++++++++++-- .../gui_editor/widgets/CtrlTextButton.xml | 2 +- .../plugins/gui_editor/widgets/ViewText.xml | 2 +- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index c27d3ca6c..6408703f4 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -35,6 +35,13 @@ namespace GUIEditor BUTTON_TYPE_RADIO = 2 }; + enum NELTxtJustification + { + TEXT_CLIPWORD, + TEXT_DONTCLIPWORD, + TEXT_JUSTIFIED + }; + CPropBrowserCtrl::CPropBrowserCtrl() { browser = NULL; @@ -145,7 +152,7 @@ namespace GUIEditor if( e == NULL ) return; - if( ( value < 0 ) || ( value > 2 ) ) + if( ( value < BUTTON_TYPE_PUSH ) || ( value > BUTTON_TYPE_RADIO ) ) return; std::string v; @@ -157,6 +164,26 @@ namespace GUIEditor case BUTTON_TYPE_RADIO: v = "radio_button"; break; } + e->setProperty( propName.toUtf8().constData(), v ); + } + else + if( propName == "justification" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + if( ( value < TEXT_CLIPWORD ) || ( value > TEXT_JUSTIFIED ) ) + return; + + std::string v; + switch( value ) + { + case TEXT_CLIPWORD: v = "clip_word"; break; + case TEXT_DONTCLIPWORD: v = "dont_clip_word"; break; + case TEXT_JUSTIFIED: v = "justified"; break; + } + e->setProperty( propName.toUtf8().constData(), v ); } } @@ -209,11 +236,6 @@ namespace GUIEditor if( btype.empty() ) return; - QStringList enums; - enums.push_back( "push_button" ); - enums.push_back( "toggle_button" ); - enums.push_back( "radio_button" ); - int e = -1; if( btype == "push_button" ) e = BUTTON_TYPE_PUSH; @@ -231,12 +253,52 @@ namespace GUIEditor if( pp == NULL ) return; + QStringList enums; + enums.push_back( "push_button" ); + enums.push_back( "toggle_button" ); + enums.push_back( "radio_button" ); + enumMgr->setEnumNames( pp, enums ); enumMgr->setValue( pp, e ); browser->addProperty( pp ); return; } else + if( prop.propType == "text_justification" ) + { + std::string j = element->getProperty( prop.propName ); + if( j.empty() ) + return; + + int e = -1; + if( j == "clip_word" ) + e = TEXT_CLIPWORD; + else + if( j == "dont_clip_word" ) + e = TEXT_DONTCLIPWORD; + else + if( j == "justified" ) + e = TEXT_JUSTIFIED; + + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "clip_word" ); + enums.push_back( "dont_clip_word" ); + enums.push_back( "justified" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml index 32541cc1f..4553af272 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml @@ -145,7 +145,7 @@ justification - string + text_justification dont_clip_word diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml index fc4d30688..415c3167e 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml @@ -40,7 +40,7 @@ justification - string + text_justification dont_clip_word From 250cd6efc159c0d8f79c7ffbfc96d1036b2b87c8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Jun 2014 18:25:14 +0200 Subject: [PATCH 096/282] Posref can now be set as an enum, instead of a string in the property editor. --HG-- branch : gsoc2014-dfighter --- code/nel/src/gui/interface_element.cpp | 16 ++- .../gui_editor/property_browser_ctrl.cpp | 123 ++++++++++++++++++ .../gui_editor/widgets/InterfaceElement.xml | 13 +- 3 files changed, 145 insertions(+), 7 deletions(-) diff --git a/code/nel/src/gui/interface_element.cpp b/code/nel/src/gui/interface_element.cpp index 15f9cf812..0225d2797 100644 --- a/code/nel/src/gui/interface_element.cpp +++ b/code/nel/src/gui/interface_element.cpp @@ -130,12 +130,17 @@ namespace NLGUI if( name == "posref" ) { std::string posref; - posref = HotSpotToString( getParentPosRef() ); - posref += " "; posref += HotSpotToString( getPosRef() ); return posref; } else + if( name == "parentposref" ) + { + std::string parentPosRef; + parentPosRef = HotSpotToString( getParentPosRef() ); + return parentPosRef; + } + else if( name == "sizeref" ) { return getSizeRefAsString( _SizeRef, _SizeDivW, _SizeDivH ); @@ -221,10 +226,15 @@ namespace NLGUI else if( name == "posref" ) { - convertHotSpotCouple( value.c_str(), _ParentPosRef, _PosRef ); + convertHotSpot( value.c_str() ); return; } else + if( name == "parentposref" ) + { + convertHotSpot( value.c_str() ); + } + else if( name == "sizeref" ) { parseSizeRef( value.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 6408703f4..d5feba8f7 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -26,6 +26,83 @@ #include "widget_info_tree.h" #include +namespace +{ + + class NelPosRef + { + public: + + enum NELPosRef + { + POSREF_BL = 0, + POSREF_BM = 1, + POSREF_BR = 2, + POSREF_ML = 3, + POSREF_MM = 4, + POSREF_MR = 5, + POSREF_TL = 6, + POSREF_TM = 7, + POSREF_TR = 8 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "BL" ) + r = POSREF_BL; + else + if( s == "BM" ) + r = POSREF_BM; + else + if( s == "BR" ) + r = POSREF_BR; + else + if( s == "ML" ) + r = POSREF_ML; + else + if( s == "MM" ) + r = POSREF_MM; + else + if( s == "MR" ) + r = POSREF_MR; + else + if( s == "TL" ) + r = POSREF_TL; + else + if( s == "TM" ) + r = POSREF_TM; + else + if( s == "TR" ) + r = POSREF_TR; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case POSREF_BL: v = "BL"; break; + case POSREF_BM: v = "BM"; break; + case POSREF_BR: v = "BR"; break; + case POSREF_ML: v = "ML"; break; + case POSREF_MM: v = "MM"; break; + case POSREF_MR: v = "MR"; break; + case POSREF_TL: v = "TL"; break; + case POSREF_TM: v = "TM"; break; + case POSREF_TR: v = "TR"; break; + } + + return v; + } + }; + +} + namespace GUIEditor { enum NELButtonTypes @@ -184,6 +261,19 @@ namespace GUIEditor case TEXT_JUSTIFIED: v = "justified"; break; } + e->setProperty( propName.toUtf8().constData(), v ); + } + else + if( ( propName == "posref" ) || ( propName == "parentposref" ) ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelPosRef::toString( value ); + if( v.empty() ) + return; + e->setProperty( propName.toUtf8().constData(), v ); } } @@ -299,6 +389,39 @@ namespace GUIEditor return; } else + if( prop.propType == "posref" ) + { + std::string j = element->getProperty( prop.propName ); + if( j.empty() ) + return; + + int e = -1; + e = NelPosRef::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "BL" ); + enums.push_back( "BM" ); + enums.push_back( "BR" ); + enums.push_back( "ML" ); + enums.push_back( "MM" ); + enums.push_back( "MR" ); + enums.push_back( "TL" ); + enums.push_back( "TM" ); + enums.push_back( "TR" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml index 856480dc7..b16de9ed0 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml @@ -36,12 +36,17 @@ h int 0 - + posref - string - BL BL - + posref + BL + + + parentposref + posref + BL + sizeref string From ec86d0381be90009cbd129e28e3a74b82593f435 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Jun 2014 22:55:10 +0200 Subject: [PATCH 097/282] Some refactoring. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 141 ++++++++++++------ 1 file changed, 93 insertions(+), 48 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index d5feba8f7..6eef4e2f6 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -101,24 +101,98 @@ namespace } }; -} -namespace GUIEditor -{ - enum NELButtonTypes + class NelButtonType { - BUTTON_TYPE_PUSH = 0, - BUTTON_TYPE_TOGGLE = 1, - BUTTON_TYPE_RADIO = 2 + public: + + enum NELButtonTypes + { + BUTTON_TYPE_PUSH = 0, + BUTTON_TYPE_TOGGLE = 1, + BUTTON_TYPE_RADIO = 2 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "push_button" ) + r = BUTTON_TYPE_PUSH; + else + if( s == "toggle_button" ) + r = BUTTON_TYPE_TOGGLE; + else + if( s == "radio_button" ) + r = BUTTON_TYPE_RADIO; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case BUTTON_TYPE_PUSH: v = "push_button"; break; + case BUTTON_TYPE_TOGGLE: v = "toggle_button"; break; + case BUTTON_TYPE_RADIO: v = "radio_button"; break; + } + + return v; + } + }; - enum NELTxtJustification + class NelTxtJustification { - TEXT_CLIPWORD, - TEXT_DONTCLIPWORD, - TEXT_JUSTIFIED + public: + + enum NELTxtJustification + { + TEXT_CLIPWORD, + TEXT_DONTCLIPWORD, + TEXT_JUSTIFIED + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "clip_word" ) + r = TEXT_CLIPWORD; + else + if( s == "dont_clip_word" ) + r = TEXT_DONTCLIPWORD; + else + if( s == "justified" ) + r = TEXT_JUSTIFIED; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case TEXT_CLIPWORD: v = "clip_word"; break; + case TEXT_DONTCLIPWORD: v = "dont_clip_word"; break; + case TEXT_JUSTIFIED: v = "justified"; break; + } + + return v; + } + }; +} + +namespace GUIEditor +{ + CPropBrowserCtrl::CPropBrowserCtrl() { browser = NULL; @@ -229,17 +303,10 @@ namespace GUIEditor if( e == NULL ) return; - if( ( value < BUTTON_TYPE_PUSH ) || ( value > BUTTON_TYPE_RADIO ) ) - return; - std::string v; - - switch( value ) - { - case BUTTON_TYPE_PUSH: v = "push_button"; break; - case BUTTON_TYPE_TOGGLE: v = "toggle_button"; break; - case BUTTON_TYPE_RADIO: v = "radio_button"; break; - } + v = NelButtonType::toString( value ); + if( v.empty() ) + return; e->setProperty( propName.toUtf8().constData(), v ); } @@ -250,16 +317,10 @@ namespace GUIEditor if( e == NULL ) return; - if( ( value < TEXT_CLIPWORD ) || ( value > TEXT_JUSTIFIED ) ) - return; - std::string v; - switch( value ) - { - case TEXT_CLIPWORD: v = "clip_word"; break; - case TEXT_DONTCLIPWORD: v = "dont_clip_word"; break; - case TEXT_JUSTIFIED: v = "justified"; break; - } + v = NelTxtJustification::toString( value ); + if( v.empty() ) + return; e->setProperty( propName.toUtf8().constData(), v ); } @@ -327,15 +388,7 @@ namespace GUIEditor return; int e = -1; - if( btype == "push_button" ) - e = BUTTON_TYPE_PUSH; - else - if( btype == "toggle_button" ) - e = BUTTON_TYPE_TOGGLE; - else - if( btype == "radio_button" ) - e = BUTTON_TYPE_RADIO; - + e = NelButtonType::fromString( btype ); if( e == -1 ) return; @@ -361,15 +414,7 @@ namespace GUIEditor return; int e = -1; - if( j == "clip_word" ) - e = TEXT_CLIPWORD; - else - if( j == "dont_clip_word" ) - e = TEXT_DONTCLIPWORD; - else - if( j == "justified" ) - e = TEXT_JUSTIFIED; - + e = NelTxtJustification::fromString( j ); if( e == -1 ) return; From e7e4b8874710319eb366f56992328ee713baf5b6 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 23 Jun 2014 14:36:29 +0530 Subject: [PATCH 098/282] function to install update in the plugin --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/translations/en.ini | 1 + .../ryzom_ams/www/html/func/update_plugin.php | 35 +++++++++++++++++++ .../ryzom_ams/www/html/templates/plugins.tpl | 1 + 3 files changed, 37 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini index d324acb3a..f2a21d2ab 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/translations/en.ini @@ -75,6 +75,7 @@ ac_error = "Plugin facing some error in activating. Please try again later." dc_success = "Plugin de-Activated successfuly." dc_error = "Plugin facing some error in de-activating. Please try again later." up_success = "Update added successfully. Go to Updates page for installing updates." +up_install_success = "Update installed successfully." [install_plugin] ip_title = "Install a new Plugin" diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php new file mode 100644 index 000000000..ddf4b0abf --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php @@ -0,0 +1,35 @@ + executeWithoutParams( "SELECT * FROM plugins INNER JOIN updates ON plugins.Id=updates.PluginId Where plugins.Id=$id" ); + $row = $sth -> fetch(); + print_r( $row ); + + // replacing update in the database + Plugincache :: rrmdir( $row['FileName'] ); + Plugincache :: zipExtraction( $row['UpdatePath'], rtrim( $row['FileName'], strtolower( $row['Name'] ) ) ); + + $db -> update( "plugins", array( 'Info' => $row['UpdateInfo'] ), "Id=$row[Id]" ); + + // deleting the previous update + $db -> delete( "updates", array( 'id' => $row['s.no'] ), "s.no=:id" ); + + header( "Location: index.php?page=plugins&result=8" ); + exit; + + } + } + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl index 4aa6e7e3b..73f88d1a2 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl @@ -17,6 +17,7 @@ {if isset($smarty.get.result) and $smarty.get.result eq "5"}

{$dc_success}

{/if} {if isset($smarty.get.result) and $smarty.get.result eq "6"}

{$dc_error}

{/if} {if isset($smarty.get.result) and $smarty.get.result eq "7"}

{$up_success}

{/if} + {if isset($smarty.get.result) and $smarty.get.result eq "8"}

{$up_install_success}

{/if}

{$plugin_info}

From e182e25e078e00329940fd053bf94a5aa40230eb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:07:44 +0200 Subject: [PATCH 099/282] text posref is now an enum too. --HG-- branch : gsoc2014-dfighter --- code/nel/src/gui/ctrl_text_button.cpp | 20 +++++++++++++------ .../gui_editor/property_browser_ctrl.cpp | 6 +++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/code/nel/src/gui/ctrl_text_button.cpp b/code/nel/src/gui/ctrl_text_button.cpp index cdf006a51..d3a0f6765 100644 --- a/code/nel/src/gui/ctrl_text_button.cpp +++ b/code/nel/src/gui/ctrl_text_button.cpp @@ -149,11 +149,16 @@ namespace NLGUI } else if( name == "text_posref" ) + { + std::string pr; + pr = CInterfaceElement::HotSpotToString( _TextPosRef ); + return pr; + } + else + if( name == "text_parent_posref" ) { std::string pr; pr = CInterfaceElement::HotSpotToString( _TextParentPosRef ); - pr += " "; - pr += CInterfaceElement::HotSpotToString( _TextPosRef ); return pr; } else @@ -324,10 +329,13 @@ namespace NLGUI else if( name == "text_posref" ) { - THotSpot parent, posref; - CInterfaceElement::convertHotSpotCouple( value.c_str(), parent, posref ); - _TextPosRef = posref; - _TextParentPosRef = parent; + _TextPosRef = convertHotSpot( value.c_str() ); + return; + } + else + if( name == "text_parent_posref" ) + { + _TextParentPosRef = convertHotSpot( value.c_str() ); return; } else diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 6eef4e2f6..3e25cbab8 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -325,7 +325,11 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } else - if( ( propName == "posref" ) || ( propName == "parentposref" ) ) + if( ( propName == "posref" ) || + ( propName == "parentposref" ) || + ( propName == "text_posref" ) || + ( propName == "text_parent_posref" ) + ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) From 0c4e0e63cc65bfdd28efa70c1de4fae6bb37b26f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:24:31 +0200 Subject: [PATCH 100/282] The proper enum type is now determined by type not name. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 23 +++++++++++++------ .../gui_editor/property_browser_ctrl.h | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 3e25cbab8..7effe6765 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -296,8 +296,18 @@ namespace GUIEditor void CPropBrowserCtrl::onEnumPropertyChanged( QtProperty *prop, int value ) { QString propName = prop->propertyName(); + std::string n = propName.toUtf8().constData(); - if( propName == "button_type" ) + // Try to find the type for this property + std::map< std::string, std::string >::const_iterator itr = + nameToType.find( n ); + // Not found :( + if( itr == nameToType.end() ) + return; + std::string type = itr->second; + + + if( type == "button_type" ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) @@ -311,7 +321,7 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } else - if( propName == "justification" ) + if( type == "text_justification" ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) @@ -325,11 +335,7 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } else - if( ( propName == "posref" ) || - ( propName == "parentposref" ) || - ( propName == "text_posref" ) || - ( propName == "text_parent_posref" ) - ) + if( type == "posref" ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) @@ -366,10 +372,13 @@ namespace GUIEditor return; SWidgetInfo &w = itr->second; + nameToType.clear(); + std::vector< SPropEntry >::const_iterator pItr; for( pItr = w.props.begin(); pItr != w.props.end(); ++pItr ) { const SPropEntry &prop = *pItr; + nameToType[ prop.propName ] = prop.propType; setupProperty( prop, element ); } diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index f8d839bd6..f53648f79 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -71,6 +71,7 @@ namespace GUIEditor std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; + std::map< std::string, std::string > nameToType; }; } From b88e53c685c3b4388e6ee4eb885d7e84d4c1d398 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:47:29 +0200 Subject: [PATCH 101/282] Got rid of a memleak. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 22 ++++++++++++++----- .../gui_editor/property_browser_ctrl.h | 5 +++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 7effe6765..4a839cbee 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -198,6 +198,9 @@ namespace GUIEditor browser = NULL; propertyMgr = new QtVariantPropertyManager; enumMgr = new QtEnumPropertyManager; + + variantFactory = new QtVariantEditorFactory; + enumFactory = new QtEnumEditorFactory; } CPropBrowserCtrl::~CPropBrowserCtrl() @@ -207,6 +210,11 @@ namespace GUIEditor delete propertyMgr; propertyMgr = NULL; + delete variantFactory; + variantFactory = NULL; + delete enumFactory; + enumFactory = NULL; + browser = NULL; } @@ -257,6 +265,14 @@ namespace GUIEditor std::string n = e->getClassName(); setupProperties( n, e ); + + + // Need to set these up every time, otherwise the editors won't work + // probably the clear() method clears them too... + browser->setFactoryForManager( propertyMgr, variantFactory ); + browser->setFactoryForManager( enumMgr, enumFactory ); + + enablePropertyWatchers(); } @@ -381,12 +397,6 @@ namespace GUIEditor nameToType[ prop.propName ] = prop.propType; setupProperty( prop, element ); } - - QtVariantEditorFactory *factory = new QtVariantEditorFactory; - browser->setFactoryForManager( propertyMgr, factory ); - - QtEnumEditorFactory *efactory = new QtEnumEditorFactory; - browser->setFactoryForManager( enumMgr, efactory ); } void CPropBrowserCtrl::setupProperty( const SPropEntry &prop, const CInterfaceElement *element ) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index f53648f79..efb785d9b 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -26,6 +26,8 @@ class QtTreePropertyBrowser; class QtVariantPropertyManager; class QtEnumPropertyManager; +class QtVariantEditorFactory; +class QtEnumEditorFactory; class QtProperty; class QVariant; @@ -69,6 +71,9 @@ namespace GUIEditor QtVariantPropertyManager *propertyMgr; QtEnumPropertyManager *enumMgr; + QtVariantEditorFactory *variantFactory; + QtEnumEditorFactory *enumFactory; + std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; std::map< std::string, std::string > nameToType; From 809fcab9e21e7ad3e572ef9eaf18c5887a2a6a02 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:49:31 +0200 Subject: [PATCH 102/282] Forgot the widget settings... --HG-- branch : gsoc2014-dfighter --- .../plugins/gui_editor/widgets/CtrlTextButton.xml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml index 4553af272..ca66dbd62 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml @@ -52,12 +52,17 @@ text_underlined bool false - - + + text_posref - string - MM MM - + posref + MM + + + text_parent_posref + posref + MM + text_color_normal color From 842ca366ded53e77b291e1c922afbcfc64887145 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 01:44:06 +0200 Subject: [PATCH 103/282] Tooltip posrefs are now enums in the GUI Editor. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/gui/ctrl_base.h | 2 + code/nel/src/gui/ctrl_base.cpp | 115 +++++++++--- .../gui_editor/property_browser_ctrl.cpp | 170 ++++++++++++++++++ .../gui_editor/property_browser_ctrl.h | 2 + .../plugins/gui_editor/widgets/CtrlBase.xml | 20 ++- 5 files changed, 280 insertions(+), 29 deletions(-) diff --git a/code/nel/include/nel/gui/ctrl_base.h b/code/nel/include/nel/gui/ctrl_base.h index 28eeb2cd0..71e6cad56 100644 --- a/code/nel/include/nel/gui/ctrl_base.h +++ b/code/nel/include/nel/gui/ctrl_base.h @@ -171,7 +171,9 @@ namespace NLGUI THotSpot _ToolTipPosRefAlt : 6; protected: void convertTooltipHotSpot(const char *prop, THotSpot &parentHS, THotSpot &childHS); + void convertTooltipHotSpot(const char *prop, THotSpot &HS ); static std::string TooltipHotSpotToString( THotSpot parent, THotSpot child ); + static std::string TooltipHotSpotToString( THotSpot HS ); void mapAHString( const std::string &key, const std::string &value ); std::string getAHString( const std::string &key ) const; diff --git a/code/nel/src/gui/ctrl_base.cpp b/code/nel/src/gui/ctrl_base.cpp index f0a2c2f89..98cda02f4 100644 --- a/code/nel/src/gui/ctrl_base.cpp +++ b/code/nel/src/gui/ctrl_base.cpp @@ -220,28 +220,22 @@ namespace NLGUI else if( name == "tooltip_posref" ) { - std::string s; - if( ( _ToolTipParentPosRef == Hotspot_TTAuto ) && ( _ToolTipPosRef == Hotspot_TTAuto ) ) - return "auto"; - else{ - s = CInterfaceElement::HotSpotToString( _ToolTipParentPosRef ); - s += " "; - s += CInterfaceElement::HotSpotToString( _ToolTipPosRef ); - return s; - } + return TooltipHotSpotToString( _ToolTipPosRef ); + } + else + if( name == "tooltip_parent_posref" ) + { + return TooltipHotSpotToString( _ToolTipParentPosRef ); } else if( name == "tooltip_posref_alt" ) { - std::string s; - if( ( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) && ( _ToolTipPosRefAlt == Hotspot_TTAuto ) ) - return "auto"; - else{ - s = CInterfaceElement::HotSpotToString( _ToolTipParentPosRefAlt ); - s += " "; - s += CInterfaceElement::HotSpotToString( _ToolTipPosRefAlt ); - return s; - } + return TooltipHotSpotToString( _ToolTipPosRefAlt ); + } + else + if( name == "tooltip_parent_posref_alt" ) + { + return TooltipHotSpotToString( _ToolTipParentPosRefAlt ); } else if( name == "instant_help" ) @@ -293,21 +287,65 @@ namespace NLGUI else if( name == "tooltip_posref" ) { - THotSpot parentHS; THotSpot HS; - convertTooltipHotSpot( value.c_str(), parentHS, HS ); - _ToolTipParentPosRef = parentHS; + convertTooltipHotSpot( value.c_str(), HS ); _ToolTipPosRef = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipPosRef == Hotspot_TTAuto ) + _ToolTipParentPosRef = Hotspot_TTAuto; + else + if( _ToolTipParentPosRef == Hotspot_TTAuto ) + _ToolTipParentPosRef = _ToolTipPosRef; + + return; + } + else + if( name == "tooltip_parent_posref" ) + { + THotSpot HS; + convertTooltipHotSpot( value.c_str(), HS ); + _ToolTipParentPosRef = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipParentPosRef == Hotspot_TTAuto ) + _ToolTipPosRef = Hotspot_TTAuto; + else + if( _ToolTipPosRef == Hotspot_TTAuto ) + _ToolTipPosRef = _ToolTipParentPosRef; + return; } else if( name == "tooltip_posref_alt" ) { - THotSpot parentHS; THotSpot HS; - convertTooltipHotSpot( value.c_str(), parentHS, HS ); - _ToolTipParentPosRefAlt = parentHS; + convertTooltipHotSpot( value.c_str(), HS ); _ToolTipPosRefAlt = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipPosRefAlt == Hotspot_TTAuto ) + _ToolTipParentPosRefAlt = Hotspot_TTAuto; + else + if( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) + _ToolTipPosRefAlt = _ToolTipParentPosRefAlt; + + return; + } + else + if( name == "tooltip_parent_posref_alt" ) + { + THotSpot HS; + convertTooltipHotSpot( value.c_str(), HS ); + _ToolTipParentPosRefAlt = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) + _ToolTipPosRefAlt = Hotspot_TTAuto; + else + if( _ToolTipPosRefAlt == Hotspot_TTAuto ) + _ToolTipPosRefAlt = _ToolTipParentPosRefAlt; + return; } else @@ -374,6 +412,21 @@ namespace NLGUI } } + void CCtrlBase::convertTooltipHotSpot(const char *prop, THotSpot &HS ) + { + if(prop) + { + const char *ptr = (const char*)prop; + if(stricmp(ptr, "auto")==0) + { + HS = Hotspot_TTAuto; + } + else if(strlen(ptr)==2) + { + HS = convertHotSpot(ptr); + } + } + } std::string CCtrlBase::TooltipHotSpotToString( THotSpot parent, THotSpot child ) { @@ -393,6 +446,20 @@ namespace NLGUI return s; } + std::string CCtrlBase::TooltipHotSpotToString( THotSpot HS ) + { + std::string s; + if( HS == Hotspot_TTAuto ) + { + s = "auto"; + } + else + { + s = HotSpotToString( HS ); + } + return s; + } + // *************************************************************************** bool CCtrlBase::emptyContextHelp() const { diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 4a839cbee..017b4e5a7 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -102,6 +102,83 @@ namespace }; + class NelPosRefTT + { + public: + + enum NELPosRef + { + TTPOSREF_BL = 0, + TTPOSREF_BM = 1, + TTPOSREF_BR = 2, + TTPOSREF_ML = 3, + TTPOSREF_MM = 4, + TTPOSREF_MR = 5, + TTPOSREF_TL = 6, + TTPOSREF_TM = 7, + TTPOSREF_TR = 8, + TTPOSREF_AUTO = 9 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "BL" ) + r = TTPOSREF_BL; + else + if( s == "BM" ) + r = TTPOSREF_BM; + else + if( s == "BR" ) + r = TTPOSREF_BR; + else + if( s == "ML" ) + r = TTPOSREF_ML; + else + if( s == "MM" ) + r = TTPOSREF_MM; + else + if( s == "MR" ) + r = TTPOSREF_MR; + else + if( s == "TL" ) + r = TTPOSREF_TL; + else + if( s == "TM" ) + r = TTPOSREF_TM; + else + if( s == "TR" ) + r = TTPOSREF_TR; + else + r = TTPOSREF_AUTO; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case TTPOSREF_BL: v = "BL"; break; + case TTPOSREF_BM: v = "BM"; break; + case TTPOSREF_BR: v = "BR"; break; + case TTPOSREF_ML: v = "ML"; break; + case TTPOSREF_MM: v = "MM"; break; + case TTPOSREF_MR: v = "MR"; break; + case TTPOSREF_TL: v = "TL"; break; + case TTPOSREF_TM: v = "TM"; break; + case TTPOSREF_TR: v = "TR"; break; + case TTPOSREF_AUTO: v = "auto"; break; + } + + return v; + } + }; + + class NelButtonType { public: @@ -201,6 +278,12 @@ namespace GUIEditor variantFactory = new QtVariantEditorFactory; enumFactory = new QtEnumEditorFactory; + + ttPairs[ "tooltip_posref" ] = "tooltip_parent_posref"; + ttPairs[ "tooltip_parent_posref" ] = "tooltip_posref"; + ttPairs[ "tooltip_posref_alt" ] = "tooltip_parent_posref_alt"; + ttPairs[ "tooltip_parent_posref_alt" ] = "tooltip_posref_alt"; + } CPropBrowserCtrl::~CPropBrowserCtrl() @@ -363,6 +446,56 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } + else + if( type == "posreftt" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelPosRefTT::toString( value ); + if( v.empty() ) + return; + + e->setProperty( propName.toUtf8().constData(), v ); + + // When auto is set as posref for a tooltip, it's pair MUST be auto as well + // When we set anything other than auto, the pair MUST not be auto either + // Only need to set the widget here, since the actual property is changed in the GUI library automatically + { + // Find the pair + std::map< std::string, std::string >::const_iterator ttItr = + ttPairs.find( n ); + + // Found! + if( ttItr != ttPairs.end() ) + { + + // Find the QtProperty that belongs to the pair + std::map< std::string, QtProperty* >::const_iterator pItr = + ttPosRefProps.find( ttItr->second ); + + // Found! + if( pItr != ttPosRefProps.end() ) + { + disablePropertyWatchers(); + + if( value == NelPosRefTT::TTPOSREF_AUTO ) + enumMgr->setValue( pItr->second, NelPosRefTT::TTPOSREF_AUTO ); + else + { + int v = NelPosRefTT::fromString( pItr->second->valueText().toUtf8().constData() ); + if( v == NelPosRefTT::TTPOSREF_AUTO ) + { + enumMgr->setValue( pItr->second, value ); + } + } + + enablePropertyWatchers(); + } + } + } + } } void CPropBrowserCtrl::enablePropertyWatchers() @@ -389,6 +522,7 @@ namespace GUIEditor SWidgetInfo &w = itr->second; nameToType.clear(); + ttPosRefProps.clear(); std::vector< SPropEntry >::const_iterator pItr; for( pItr = w.props.begin(); pItr != w.props.end(); ++pItr ) @@ -490,6 +624,42 @@ namespace GUIEditor return; } else + if( prop.propType == "posreftt" ) + { + std::string j = element->getProperty( prop.propName ); + if( j.empty() ) + return; + + int e = -1; + e = NelPosRefTT::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "BL" ); + enums.push_back( "BM" ); + enums.push_back( "BR" ); + enums.push_back( "ML" ); + enums.push_back( "MM" ); + enums.push_back( "MR" ); + enums.push_back( "TL" ); + enums.push_back( "TM" ); + enums.push_back( "TR" ); + enums.push_back( "auto" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + ttPosRefProps[ prop.propName ] = pp; + + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index efb785d9b..bec4004d3 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -77,6 +77,8 @@ namespace GUIEditor std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; std::map< std::string, std::string > nameToType; + std::map< std::string, QtProperty * > ttPosRefProps; // Tooltip posref properties + std::map< std::string, std::string > ttPairs; }; } diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml index 5c334dea5..732930348 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml @@ -37,17 +37,27 @@ tooltip_special_parent string - + tooltip_posref - string + posreftt auto - + + + tooltip_parent_posref + posreftt + auto + tooltip_posref_alt - string + posreftt auto - + + + tooltip_parent_posref_alt + posreftt + auto + instant_help bool From 7f5973e4623b20ed240237d78943ffd5358f4124 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 02:53:33 +0200 Subject: [PATCH 104/282] tooltip parent is now changable using an enum. --HG-- branch : gsoc2014-dfighter --- code/nel/src/gui/ctrl_base.cpp | 2 +- .../gui_editor/property_browser_ctrl.cpp | 87 +++++++++++++++++++ .../plugins/gui_editor/widgets/CtrlBase.xml | 2 +- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/ctrl_base.cpp b/code/nel/src/gui/ctrl_base.cpp index 98cda02f4..5c250a0da 100644 --- a/code/nel/src/gui/ctrl_base.cpp +++ b/code/nel/src/gui/ctrl_base.cpp @@ -86,7 +86,7 @@ namespace NLGUI break; } - return ""; + return "control"; } CCtrlBase::TToolTipParentType CCtrlBase::stringToToolTipParent( const std::string &str ) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 017b4e5a7..d56062eda 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -28,6 +28,52 @@ namespace { + class NelTTParent + { + public: + + enum NELTTParent + { + TTPARENT_MOUSE = 0, + TTPARENT_CONTROL = 1, + TTPARENT_WINDOW = 2, + TTPARENT_SPECIAL_WINDOW = 3 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "mouse" ) + r = TTPARENT_MOUSE; + else + if( s == "control" ) + r = TTPARENT_CONTROL; + else + if( s == "window" ) + r = TTPARENT_WINDOW; + else + if( s == "special" ) + r = TTPARENT_SPECIAL_WINDOW; + + return r; + } + + static std::string toString( int value ) + { + std::string s; + + switch( value ) + { + case TTPARENT_MOUSE: s = "mouse"; break; + case TTPARENT_CONTROL: s = "control"; break; + case TTPARENT_WINDOW: s = "window"; break; + case TTPARENT_SPECIAL_WINDOW: s = "special"; break; + } + + return s; + } + }; class NelPosRef { @@ -496,6 +542,19 @@ namespace GUIEditor } } } + else + if( type == "tooltip_parent" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelTTParent::toString( value ); + if( v.empty() ) + return; + + e->setProperty( propName.toUtf8().constData(), v ); + } } void CPropBrowserCtrl::enablePropertyWatchers() @@ -538,6 +597,34 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "tooltip_parent" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + int e = -1; + e = NelTTParent::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "mouse" ); + enums.push_back( "control" ); + enums.push_back( "window" ); + enums.push_back( "special window" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + } + else if( prop.propType == "button_type" ) { std::string btype = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml index 732930348..8ac372bdb 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml @@ -30,7 +30,7 @@ tooltip_parent - string + tooltip_parent From 27fe95904a99b4681c59bd3f97bfe9e09627bc62 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 03:01:43 +0200 Subject: [PATCH 105/282] Quelled some compiler compliants. --HG-- branch : gsoc2014-dfighter --- code/nel/src/gui/group_paragraph.cpp | 4 ++++ code/nel/src/gui/group_table.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/code/nel/src/gui/group_paragraph.cpp b/code/nel/src/gui/group_paragraph.cpp index 00ea5f3b7..9e065c878 100644 --- a/code/nel/src/gui/group_paragraph.cpp +++ b/code/nel/src/gui/group_paragraph.cpp @@ -209,6 +209,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "align" ) @@ -229,6 +231,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "space" ) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 9f019ed48..2fdd7e364 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -89,6 +89,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "valign" ) @@ -106,6 +108,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "left_margin" ) From c6312db22238faf8305b68bbdaaf609a74ea3af5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 1 Jul 2014 01:51:41 +0200 Subject: [PATCH 106/282] Bitmap alignment can now be set as an enum. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 87 +++++++++++++++++++ .../plugins/gui_editor/widgets/ViewBitmap.xml | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index d56062eda..a8f129bfd 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -28,6 +28,53 @@ namespace { + class NelBMAlign + { + public: + + enum NELBMAlign + { + LB = 0, + RB = 1, + LT = 2, + RT = 3 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "LB" ) + r = 0; + else + if( s == "RB" ) + r = 1; + else + if( s == "LT" ) + r = 2; + else + if( s == "RT" ) + r = 3; + + return r; + } + + static std::string toString( int value ) + { + std::string s; + + switch( value ) + { + case LB: s = "LB"; break; + case RB: s = "RB"; break; + case LT: s = "LT"; break; + case RT: s = "RT"; break; + } + + return s; + } + }; + class NelTTParent { public: @@ -555,6 +602,19 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } + else + if( type == "bitmap_align" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelBMAlign::toString( value ); + if( v.empty() ) + return; + + e->setProperty( propName.toUtf8().constData(), v ); + } } void CPropBrowserCtrl::enablePropertyWatchers() @@ -597,6 +657,33 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "bitmap_align" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + int e = -1; + e = NelBMAlign::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "LB" ); + enums.push_back( "RB" ); + enums.push_back( "LT" ); + enums.push_back( "RT" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + } + else if( prop.propType == "tooltip_parent" ) { std::string j = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index 9da967b5a..7dddfdbe1 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -60,7 +60,7 @@ align - string + bitmap_align From 471c3a0dc556edcef87c88713cb60f74d211ebde Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 1 Jul 2014 01:54:55 +0200 Subject: [PATCH 107/282] Changed some property types. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml | 2 +- .../src/plugins/gui_editor/widgets/ViewBitmapCombo.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index 7dddfdbe1..c39ecbabc 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -10,7 +10,7 @@ color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml index 0b55f6932..8fc579675 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml @@ -25,17 +25,17 @@ col_normal - string + color col_over - string + color col_pushed - string + color From 0d9022226cae0dfe3a0db2606a80f03ae2fac1f4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 2 Jul 2014 20:44:46 +0200 Subject: [PATCH 108/282] Line endings... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index a8f129bfd..e3594edb0 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -34,8 +34,8 @@ namespace enum NELBMAlign { - LB = 0, - RB = 1, + LB = 0, + RB = 1, LT = 2, RT = 3 }; From 085c1b41b9de1843d2993a72a289a97b17c958c2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 2 Jul 2014 22:27:04 +0200 Subject: [PATCH 109/282] Added facilities for viewing the loaded actions. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/gui/action_handler.h | 2 + code/nel/src/gui/action_handler.cpp | 12 +++ .../src/plugins/gui_editor/CMakeLists.txt | 2 + .../src/plugins/gui_editor/action_list.cpp | 31 ++++++ .../src/plugins/gui_editor/action_list.h | 18 ++++ .../src/plugins/gui_editor/action_list.ui | 94 +++++++++++++++++++ .../plugins/gui_editor/gui_editor_window.cpp | 15 +++ .../plugins/gui_editor/gui_editor_window.h | 4 + 8 files changed, 178 insertions(+) create mode 100644 code/studio/src/plugins/gui_editor/action_list.cpp create mode 100644 code/studio/src/plugins/gui_editor/action_list.h create mode 100644 code/studio/src/plugins/gui_editor/action_list.ui diff --git a/code/nel/include/nel/gui/action_handler.h b/code/nel/include/nel/gui/action_handler.h index 70c4b386e..48b49e451 100644 --- a/code/nel/include/nel/gui/action_handler.h +++ b/code/nel/include/nel/gui/action_handler.h @@ -68,6 +68,8 @@ namespace NLGUI return _GlobalInstance; } + void getActionHandlers( std::vector< std::string > &handlers ); + /// return pointer to action handler or null if it doesn't exist IActionHandler *getActionHandler(const std::string &name) const { diff --git a/code/nel/src/gui/action_handler.cpp b/code/nel/src/gui/action_handler.cpp index 8b0d9c4ee..d7214ef06 100644 --- a/code/nel/src/gui/action_handler.cpp +++ b/code/nel/src/gui/action_handler.cpp @@ -111,6 +111,18 @@ namespace NLGUI } } + void CAHManager::getActionHandlers( std::vector< std::string > &handlers ) + { + handlers.clear(); + + std::map< string, IActionHandler* >::iterator itr = FactoryMap.begin(); + while( itr != FactoryMap.end() ) + { + handlers.push_back( itr->first ); + ++itr; + } + } + // ------------------------------------------------------------------------------------------------ IActionHandler* CAHManager::getAH(const std::string &name, std::string ¶ms) { diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 0c13c4cd6..33b016bd6 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -30,6 +30,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR add_widget_widget.h editor_selection_watcher.h editor_message_processor.h + action_list.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS @@ -45,6 +46,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_UIS new_property_widget.ui new_widget_widget.ui add_widget_widget.ui + action_list.ui ) SET(QT_USE_QTGUI TRUE) diff --git a/code/studio/src/plugins/gui_editor/action_list.cpp b/code/studio/src/plugins/gui_editor/action_list.cpp new file mode 100644 index 000000000..fa61dd6b6 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_list.cpp @@ -0,0 +1,31 @@ +#include "action_list.h" +#include "nel/gui/action_handler.h" +#include +#include + +ActionList::ActionList( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); +} + +ActionList::~ActionList() +{ +} + +void ActionList::load() +{ + actionList->clear(); + + NLGUI::CAHManager *am = NLGUI::CAHManager::getInstance(); + std::vector< std::string > handlers; + am->getActionHandlers( handlers ); + + std::vector< std::string >::const_iterator itr = handlers.begin(); + while( itr != handlers.end() ) + { + actionList->addItem( itr->c_str() ); + ++itr; + } +} + diff --git a/code/studio/src/plugins/gui_editor/action_list.h b/code/studio/src/plugins/gui_editor/action_list.h new file mode 100644 index 000000000..ba668f99e --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_list.h @@ -0,0 +1,18 @@ +#ifndef ACTION_LIST_H +#define ACTION_LIST_H + + +#include "ui_action_list.h" + + +class ActionList : public QDialog, public Ui::ActionListDialog +{ + Q_OBJECT + +public: + ActionList( QDialog *parent = NULL ); + ~ActionList(); + void load(); +}; + +#endif diff --git a/code/studio/src/plugins/gui_editor/action_list.ui b/code/studio/src/plugins/gui_editor/action_list.ui new file mode 100644 index 000000000..ba147cfc2 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_list.ui @@ -0,0 +1,94 @@ + + + ActionListDialog + + + + 0 + 0 + 359 + 258 + + + + Action List + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + okButton + clicked() + ActionListDialog + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + ActionListDialog + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 4f66b61fc..0cbc94947 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -44,6 +44,7 @@ #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" +#include "action_list.h" namespace GUIEditor { @@ -70,6 +71,8 @@ namespace GUIEditor widgetInfoTree = new CWidgetInfoTree; + actionList = new ActionList(); + createMenus(); readSettings(); @@ -115,6 +118,9 @@ namespace GUIEditor removeMenus(); + delete actionList; + actionList = NULL; + delete messageProcessor; messageProcessor = NULL; @@ -341,6 +347,11 @@ namespace GUIEditor } + void GUIEditorWindow::test_actionList() + { + actionList->load(); + actionList->show(); + } void GUIEditorWindow::hideEvent( QHideEvent *evnt ) { @@ -400,6 +411,10 @@ namespace GUIEditor connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); + a = new QAction( "Test actionlist", this ); + connect( a, SIGNAL( triggered( bool ) ), this, SLOT( test_actionList() ) ); + m->addAction( a ); + menu = m; } } diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 517186739..fc1f533cc 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -27,6 +27,7 @@ class QtTreePropertyBrowser; class QMenu; +class ActionList; namespace GUIEditor { @@ -66,6 +67,8 @@ private Q_SLOTS: void onAddWidgetClicked(); void onTreeChanged(); + void test_actionList(); + protected: void hideEvent( QHideEvent *evnt ); void showEvent( QShowEvent *evnt ); @@ -91,6 +94,7 @@ private: CWidgetInfoTree *widgetInfoTree; CEditorMessageProcessor *messageProcessor; AddWidgetWidget *addWidgetWidget; + ActionList *actionList; CPropBrowserCtrl browserCtrl; QString currentProject; From e4e2a57b65e51a19c12ec905fccc24ff11c73d33 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 3 Jul 2014 00:44:38 +0200 Subject: [PATCH 110/282] ActionList dialog can now select an action, and is used with the proc editor. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/action_list.cpp | 18 +++++++++++++++ .../src/plugins/gui_editor/action_list.h | 11 ++++++++++ .../plugins/gui_editor/gui_editor_window.cpp | 16 -------------- .../plugins/gui_editor/gui_editor_window.h | 3 --- .../src/plugins/gui_editor/proc_editor.cpp | 22 ++++++++++--------- .../src/plugins/gui_editor/proc_editor.h | 4 ++++ 6 files changed, 45 insertions(+), 29 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/action_list.cpp b/code/studio/src/plugins/gui_editor/action_list.cpp index fa61dd6b6..8925e6d04 100644 --- a/code/studio/src/plugins/gui_editor/action_list.cpp +++ b/code/studio/src/plugins/gui_editor/action_list.cpp @@ -29,3 +29,21 @@ void ActionList::load() } } +void ActionList::accept() +{ + QListWidgetItem *item = actionList->currentItem(); + if( item == NULL ) + return; + + selectedAction = item->text(); + + QDialog::accept(); +} + +void ActionList::reject() +{ + selectedAction = ""; + + QDialog::reject(); +} + diff --git a/code/studio/src/plugins/gui_editor/action_list.h b/code/studio/src/plugins/gui_editor/action_list.h index ba668f99e..752d66467 100644 --- a/code/studio/src/plugins/gui_editor/action_list.h +++ b/code/studio/src/plugins/gui_editor/action_list.h @@ -3,6 +3,7 @@ #include "ui_action_list.h" +#include class ActionList : public QDialog, public Ui::ActionListDialog @@ -13,6 +14,16 @@ public: ActionList( QDialog *parent = NULL ); ~ActionList(); void load(); + + QString getSelectedAction(){ return selectedAction; } + + +public Q_SLOTS: + void accept(); + void reject(); + +private: + QString selectedAction; }; #endif diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 0cbc94947..9f6568936 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -44,7 +44,6 @@ #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" -#include "action_list.h" namespace GUIEditor { @@ -71,8 +70,6 @@ namespace GUIEditor widgetInfoTree = new CWidgetInfoTree; - actionList = new ActionList(); - createMenus(); readSettings(); @@ -118,9 +115,6 @@ namespace GUIEditor removeMenus(); - delete actionList; - actionList = NULL; - delete messageProcessor; messageProcessor = NULL; @@ -347,12 +341,6 @@ namespace GUIEditor } - void GUIEditorWindow::test_actionList() - { - actionList->load(); - actionList->show(); - } - void GUIEditorWindow::hideEvent( QHideEvent *evnt ) { QWidget::hideEvent( evnt ); @@ -411,10 +399,6 @@ namespace GUIEditor connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); - a = new QAction( "Test actionlist", this ); - connect( a, SIGNAL( triggered( bool ) ), this, SLOT( test_actionList() ) ); - m->addAction( a ); - menu = m; } } diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index fc1f533cc..15935fe74 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -27,7 +27,6 @@ class QtTreePropertyBrowser; class QMenu; -class ActionList; namespace GUIEditor { @@ -67,7 +66,6 @@ private Q_SLOTS: void onAddWidgetClicked(); void onTreeChanged(); - void test_actionList(); protected: void hideEvent( QHideEvent *evnt ); @@ -94,7 +92,6 @@ private: CWidgetInfoTree *widgetInfoTree; CEditorMessageProcessor *messageProcessor; AddWidgetWidget *addWidgetWidget; - ActionList *actionList; CPropBrowserCtrl browserCtrl; QString currentProject; diff --git a/code/studio/src/plugins/gui_editor/proc_editor.cpp b/code/studio/src/plugins/gui_editor/proc_editor.cpp index c36b16f64..e96a1cce1 100644 --- a/code/studio/src/plugins/gui_editor/proc_editor.cpp +++ b/code/studio/src/plugins/gui_editor/proc_editor.cpp @@ -17,6 +17,7 @@ #include "proc_editor.h" #include "action_editor.h" +#include "action_list.h" #include #include #include "nel/gui/interface_group.h" @@ -35,10 +36,15 @@ namespace GUIEditor connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveButtonClicked() ) ); connect( upButton, SIGNAL( clicked( bool ) ), this, SLOT( onUpButtonClicked() ) ); connect( downButton, SIGNAL( clicked( bool ) ), this, SLOT( onDownButtonClicked() ) ); + + alist = new ActionList(); } ProcEditor::~ProcEditor() { + delete alist; + alist = NULL; + delete actionEditor; actionEditor = NULL; } @@ -84,17 +90,13 @@ namespace GUIEditor void ProcEditor::onAddButtonClicked() { - bool ok; - QString name = - QInputDialog::getText( this, - tr( "Adding new Action" ), - tr( "Please specify the name of the new action handler" ), - QLineEdit::Normal, - QString(), - &ok ); - - if( ok ) + alist->load(); + int result = alist->exec(); + + if( result == QDialog::Accepted ) { + QString name = alist->getSelectedAction(); + CProcedure *proc = CWidgetManager::getInstance()->getParser()->getProc( currentProc.toUtf8().constData() ); if( proc != NULL ) diff --git a/code/studio/src/plugins/gui_editor/proc_editor.h b/code/studio/src/plugins/gui_editor/proc_editor.h index 90579daa4..8debfef02 100644 --- a/code/studio/src/plugins/gui_editor/proc_editor.h +++ b/code/studio/src/plugins/gui_editor/proc_editor.h @@ -20,6 +20,8 @@ #include "ui_proc_editor.h" +class ActionList; + namespace GUIEditor { class ActionEditor; @@ -46,6 +48,8 @@ namespace GUIEditor ActionEditor *actionEditor; QString currentProc; + + ActionList *alist; }; } From 1ef330b076f13ffdfd4a482c2fd2582bec4534ab Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Thu, 3 Jul 2014 16:44:37 +0530 Subject: [PATCH 111/282] hook functionality --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/dblayer.php | 2 +- .../ryzom_ams/ams_lib/autoload/helpers.php | 407 +++++++++--------- .../ams_lib/autoload/plugincache.php | 89 +++- .../ryzom_ams/www/html/func/update_plugin.php | 1 - .../tools/server/ryzom_ams/www/html/index.php | 16 +- .../www/html/templates/layout_admin.tpl | 2 + .../www/html/templates/layout_plugin.tpl | 12 + 7 files changed, 322 insertions(+), 207 deletions(-) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php index 63b6bfc81..43282789e 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php @@ -237,7 +237,7 @@ class DBLayer { } catch ( Exception $e ) { - $this -> rollBack(); + $this -> PDO -> rollBack(); throw new Exception( "error in deleting" ); } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php index 2d26f3c21..3410cf602 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php @@ -1,224 +1,241 @@ setCompileDir($SITEBASE.'/templates_c/'); - $smarty->setCacheDir($SITEBASE.'/cache/'); - $smarty -> setConfigDir($SITEBASE . '/configs/' ); + $smarty -> setCompileDir( $SITEBASE . '/templates_c/' ); + $smarty -> setCacheDir( $SITEBASE . '/cache/' ); + $smarty -> setConfigDir( $SITEBASE . '/configs/' ); // turn smarty debugging on/off - $smarty -> debugging = false; + $smarty -> debugging = false; // caching must be disabled for multi-language support - $smarty -> caching = false; + $smarty -> caching = false; $smarty -> cache_lifetime = 5; - - //needed by smarty. - helpers :: create_folders (); - global $FORCE_INGAME; - - //if ingame, then use the ingame templates - if ( helpers::check_if_game_client() or $FORCE_INGAME ){ - $smarty -> template_dir = $AMS_LIB . '/ingame_templates/'; + + // needed by smarty. + helpers :: create_folders (); + global $FORCE_INGAME; + + // if ingame, then use the ingame templates + if ( helpers :: check_if_game_client() or $FORCE_INGAME ) { + $smarty -> template_dir = $AMS_LIB . '/ingame_templates/'; $smarty -> setConfigDir( $AMS_LIB . '/configs' ); $variables = parse_ini_file( $AMS_LIB . '/configs/ingame_layout.ini', true ); - foreach ( $variables[$INGAME_LAYOUT] as $key => $value ){ - $smarty -> assign( $key, $value ); - } - }else{ - $smarty -> template_dir = $SITEBASE . '/templates/'; + foreach ( $variables[$INGAME_LAYOUT] as $key => $value ) { + $smarty -> assign( $key, $value ); + } + } else { + $smarty -> template_dir = $SITEBASE . '/templates/'; $smarty -> setConfigDir( $SITEBASE . '/configs' ); - } - - foreach ( $vars as $key => $value ){ - $smarty -> assign( $key, $value ); - } - - //load page specific variables that are language dependent - $variables = Helpers::handle_language(); - foreach ( $variables[$template] as $key => $value ){ - $smarty -> assign( $key, $value ); - } - - //smarty inheritance for loading the matching wrapper layout (with the matching menu bar) - if( isset($vars['permission']) && $vars['permission'] == 3 ){ - $inherited = "extends:layout_admin.tpl|"; - }else if( isset($vars['permission']) && $vars['permission'] == 2){ - $inherited = "extends:layout_mod.tpl|"; - }else if( isset($vars['permission']) && $vars['permission'] == 1){ - $inherited = "extends:layout_user.tpl|"; - }else{ - $inherited =""; - } - - //if $returnHTML is set to true, return the html by fetching the template else display the template. - if($returnHTML == true){ - return $smarty ->fetch($inherited . $template . '.tpl' ); - }else{ - $smarty -> display( $inherited . $template . '.tpl' ); - } - } - - - /** - * creates the folders that are needed for smarty. - * @todo for the drupal module it might be possible that drupal_mkdir needs to be used instead of mkdir, also this should be in the install.php instead. - */ - static public function create_folders(){ - global $AMS_LIB; + } + + foreach ( $vars as $key => $value ) { + $smarty -> assign( $key, $value ); + } + + // load page specific variables that are language dependent + $variables = Helpers :: handle_language(); + if ( $template != 'layout_plugin' ) + { + foreach ( $variables[$template] as $key => $value ) { + $smarty -> assign( $key, $value ); + } + } + // load ams content variables that are language dependent + foreach ( $variables['ams_content'] as $key => $value ) { + $smarty -> assign( $key, $value ); + } + + // smarty inheritance for loading the matching wrapper layout (with the matching menu bar) + if ( isset( $vars['permission'] ) && $vars['permission'] == 3 ) { + $inherited = "extends:layout_admin.tpl|"; + } else if ( isset( $vars['permission'] ) && $vars['permission'] == 2 ) { + $inherited = "extends:layout_mod.tpl|"; + } else if ( isset( $vars['permission'] ) && $vars['permission'] == 1 ) { + $inherited = "extends:layout_user.tpl|"; + } else { + $inherited = ""; + } + + // if $returnHTML is set to true, return the html by fetching the template else display the template. + if ( $returnHTML == true ) { + return $smarty -> fetch( $inherited . $template . '.tpl' ); + } else { + $smarty -> display( $inherited . $template . '.tpl' ); + } + } + + + /** + * creates the folders that are needed for smarty. + * + * @todo for the drupal module it might be possible that drupal_mkdir needs to be used instead of mkdir, also this should be in the install.php instead. + */ + static public function create_folders() { + global $AMS_LIB; global $SITEBASE; $arr = array( $AMS_LIB . '/ingame_templates/', $AMS_LIB . '/configs', - //$AMS_LIB . '/cache', - $SITEBASE . '/cache/', + // $AMS_LIB . '/cache', + $SITEBASE . '/cache/', $SITEBASE . '/templates/', $SITEBASE . '/templates_c/', $SITEBASE . '/configs' ); - foreach ( $arr as & $value ){ - - if ( !file_exists( $value ) ){ - print($value); - mkdir($value); - } - } - - } - - - /** + foreach ( $arr as &$value ) { + + if ( !file_exists( $value ) ) { + print( $value ); + mkdir( $value ); + } + } + + } + + + /** * check if the http request is sent ingame or not. + * * @return returns true in case it's sent ingame, else false is returned. */ - static public function check_if_game_client() - { - // if HTTP_USER_AGENT is not set then its ryzom core - global $FORCE_INGAME; - if ( ( isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'],"Ryzom") === 0)) || $FORCE_INGAME || ! isset($_SERVER['HTTP_USER_AGENT']) ){ - return true; - }else{ - return false; - } - } - - - /** + static public function check_if_game_client() + { + // if HTTP_USER_AGENT is not set then its ryzom core + global $FORCE_INGAME; + if ( ( isset( $_SERVER['HTTP_USER_AGENT'] ) && ( strpos( $_SERVER['HTTP_USER_AGENT'], "Ryzom" ) === 0 ) ) || $FORCE_INGAME || ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) { + return true; + } else { + return false; + } + } + + + /** * Handles the language specific aspect. * The language can be changed by setting the $_GET['Language'] & $_GET['setLang'] together. This will also change the language entry of the user in the db. * Cookies are also being used in case the user isn't logged in. + * * @return returns the parsed content of the language .ini file related to the users language setting. */ - static public function handle_language(){ - global $DEFAULT_LANGUAGE; - global $AMS_TRANS; - - //if user wants to change the language - if(isset($_GET['Language']) && isset($_GET['setLang'])){ - //The ingame client sometimes sends full words, derive those! - switch($_GET['Language']){ - - case "English": - $lang = "en"; - break; - - case "French": - $lang = "fr"; - break; - - default: - $lang = $_GET['Language']; - } - //if the file exists en the setLang = true - if( file_exists( $AMS_TRANS . '/' . $lang . '.ini' ) && $_GET['setLang'] == "true"){ - //set a cookie & session var and incase logged in write it to the db! - setcookie( 'Language', $lang , time() + 60*60*24*30 ); - $_SESSION['Language'] = $lang; - if(WebUsers::isLoggedIn()){ - WebUsers::setLanguage($_SESSION['id'],$lang); - } - }else{ - $_SESSION['Language'] = $DEFAULT_LANGUAGE; - } - }else{ - //if the session var is not set yet - if(!isset($_SESSION['Language'])){ - //check if a cookie already exists for it - if ( isset( $_COOKIE['Language'] ) ) { - $_SESSION['Language'] = $_COOKIE['Language']; - //else use the default language - }else{ - $_SESSION['Language'] = $DEFAULT_LANGUAGE; - } - } - } - - if ($_SESSION['Language'] == ""){ - $_SESSION['Language'] = $DEFAULT_LANGUAGE; - } - return parse_ini_file( $AMS_TRANS . '/' . $_SESSION['Language'] . '.ini', true ); - - } - + static public function handle_language() { + global $DEFAULT_LANGUAGE; + global $AMS_TRANS; + + // if user wants to change the language + if ( isset( $_GET['Language'] ) && isset( $_GET['setLang'] ) ) { + // The ingame client sometimes sends full words, derive those! + switch ( $_GET['Language'] ) { + + case "English": + $lang = "en"; + break; + + case "French": + $lang = "fr"; + break; + + default: + $lang = $_GET['Language']; + } + // if the file exists en the setLang = true + if ( file_exists( $AMS_TRANS . '/' . $lang . '.ini' ) && $_GET['setLang'] == "true" ) { + // set a cookie & session var and incase logged in write it to the db! + setcookie( 'Language', $lang , time() + 60 * 60 * 24 * 30 ); + $_SESSION['Language'] = $lang; + if ( WebUsers :: isLoggedIn() ) { + WebUsers :: setLanguage( $_SESSION['id'], $lang ); + } + } else { + $_SESSION['Language'] = $DEFAULT_LANGUAGE; + } + } else { + // if the session var is not set yet + if ( !isset( $_SESSION['Language'] ) ) { + // check if a cookie already exists for it + if ( isset( $_COOKIE['Language'] ) ) { + $_SESSION['Language'] = $_COOKIE['Language']; + // else use the default language + } else { + $_SESSION['Language'] = $DEFAULT_LANGUAGE; + } + } + } - /** - * Time output function for handling the time display. - * @return returns the time in the format specified in the $TIME_FORMAT global variable. - */ - static public function outputTime($time, $str = 1){ - global $TIME_FORMAT; - if($str){ - return date($TIME_FORMAT,strtotime($time)); - }else{ - return date($TIME_FORMAT,$time); - } - } - - /** - * Auto login function for ingame use. - * This function will allow users who access the website ingame, to log in without entering the username and password. It uses the COOKIE entry in the open_ring db. - * it checks if the cookie sent by the http request matches the one in the db. This cookie in the db is changed everytime the user relogs. - * @return returns "FALSE" if the cookies didn't match, else it returns an array with the user's id and name. - */ - static public function check_login_ingame(){ - if ( helpers :: check_if_game_client () or $forcelibrender = false ){ - $dbr = new DBLayer("ring"); - if (isset($_GET['UserId']) && isset($_COOKIE['ryzomId'])){ - $id = $_GET['UserId']; - $statement = $dbr->select("ring_users", array('id' => $id, 'cookie' => $_COOKIE['ryzomId']), "user_id=:id AND cookie =:cookie"); - if ($statement->rowCount() ){ - $entry = $statement->fetch(); - //print_r($entry); - return array('id' => $entry['user_id'], 'name' => $entry['user_name']); - }else{ - return "FALSE"; - } - }else{ - return "FALSE"; - } - }else{ - return "FALSE"; - } - } +if ( $_SESSION['Language'] == "" ) { + $_SESSION['Language'] = $DEFAULT_LANGUAGE; + } +return parse_ini_file( $AMS_TRANS . '/' . $_SESSION['Language'] . '.ini', true ); + + } + + +/** + * Time output function for handling the time display. + * + * @return returns the time in the format specified in the $TIME_FORMAT global variable. + */ +static public function outputTime( $time, $str = 1 ) { +global $TIME_FORMAT; + if ( $str ) { + return date( $TIME_FORMAT, strtotime( $time ) ); + } else { + return date( $TIME_FORMAT, $time ); + } +} + +/** + * Auto login function for ingame use. + * This function will allow users who access the website ingame, to log in without entering the username and password. It uses the COOKIE entry in the open_ring db. + * it checks if the cookie sent by the http request matches the one in the db. This cookie in the db is changed everytime the user relogs. + * + * @return returns "FALSE" if the cookies didn't match, else it returns an array with the user's id and name. + */ +static public function check_login_ingame() { +if ( helpers :: check_if_game_client () or $forcelibrender = false ) { + $dbr = new DBLayer( "ring" ); + if ( isset( $_GET['UserId'] ) && isset( $_COOKIE['ryzomId'] ) ) { + $id = $_GET['UserId']; + + $statement = $dbr -> select( "ring_users", array( 'id' => $id, 'cookie' => $_COOKIE['ryzomId'] ), "user_id=:id AND cookie =:cookie" ); + + // $statement = $dbr->execute("SELECT * FROM ring_users WHERE user_id=:id AND cookie =:cookie", array('id' => $id, 'cookie' => $_COOKIE['ryzomId'])); + + if ( $statement -> rowCount() ) { + $entry = $statement -> fetch(); + // print_r($entry); + return array( 'id' => $entry['user_id'], 'name' => $entry['user_name'] ); + } else { + return "FALSE"; + } + } else { + return "FALSE"; + } + } else { + return "FALSE"; + } +} } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index 09bd942b3..42bdda045 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -156,18 +156,17 @@ class Plugincache { } /** - * get update info array attribute of the object. + * get plugin info array attribute of the object. */ public function getUpdateInfo() { return $this -> update_info; } - /** * some more plugin function that requires during plugin operations * */ - + /** * function to remove a non empty directory * @@ -187,4 +186,86 @@ class Plugincache { return rmdir( $dir ); } } - } + + /** + * function to unzip the zipped files + * + * @param $target_path path to the target zipped file + * @param $destination path to the destination + * @return boolean + */ + public static function zipExtraction( $target_path, $destination ) + { + $zip = new ZipArchive(); + $x = $zip -> open( $target_path ); + if ( $x === true ) { + if ( $zip -> extractTo( $destination ) ) + { + $zip -> close(); + return true; + } + else + { + $zip -> close(); + return false; + } + } + } + + /** + * returns plugin information with respect to the id + * + * @param id $ plugin id + * @return field info for the plugin + */ + public static function pluginInfoUsingId( $id, $fieldName ) + { + $db = new DBLayer( 'lib' ); + $sth = $db -> selectWithParameter( $fieldName, 'plugins', array( 'id' => $id ), 'Id=:id' ); + $row = $sth -> fetch(); + return $row[$fieldName]; + } + + /** + * function provides list of active plugins + * + * @return $ac_plugins list of active plugins + */ + public static function activePlugins() + { + $db = new DBLayer( 'lib' ); + $sth = $db -> selectWithParameter( 'Id', 'plugins', array( 'status' => 1 ), 'Status=:status' ); + $row = $sth -> fetchAll(); + return $row; + } + + /** + * function to load hooks for the active plugins + * and return the contents in the hooks in an array + * + * @return $content content available in hooks + */ + public static function loadHooks() + { + $content = array(); + $ac_arr = Plugincache :: activePlugins(); + foreach( $ac_arr as $key => $value ) + { + $plugin_path = Plugincache :: pluginInfoUsingId( $value['Id'], 'FileName' ); + $pluginName = Plugincache :: pluginInfoUsingId( $value['Id'], 'Name' ); + + // calling hooks in the $pluginName.php + include $plugin_path . '/' . strtolower( $pluginName ) . '.php'; + $arr = get_defined_functions(); + + foreach( $arr['user'] as $key => $value ) + { + if ( stristr( $value, strtolower( $pluginName ) ) == true ) + { + $content['hook_info'][$pluginName] = call_user_func( $value ); + } + } + } + return $content; + } + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php index ddf4b0abf..1420572b1 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/update_plugin.php @@ -16,7 +16,6 @@ function update_plugin() { $db = new DBLayer( 'lib' ); $sth = $db -> executeWithoutParams( "SELECT * FROM plugins INNER JOIN updates ON plugins.Id=updates.PluginId Where plugins.Id=$id" ); $row = $sth -> fetch(); - print_r( $row ); // replacing update in the database Plugincache :: rrmdir( $row['FileName'] ); diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/index.php b/code/ryzom/tools/server/ryzom_ams/www/html/index.php index f01eab3e4..e87c5dcd5 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/index.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/index.php @@ -14,7 +14,6 @@ // load required pages and turn error reporting on/off error_reporting( E_ALL ); ini_set( 'display_errors', 'on' ); -require_once( '../../ams_lib/libinclude.php' ); if ( !file_exists( '../is_installed' ) ) { // if is_installed doesnt exist run setup require( 'installer/libsetup.php' ); @@ -25,9 +24,10 @@ if ( !file_exists( '../is_installed' ) ) { // if config exists then include it require( '../config.php' ); } +require_once( $AMS_LIB . '/libinclude.php' ); session_start(); -// Running Cron? +// Running Cron if ( isset( $_GET["cron"] ) ) { if ( $_GET["cron"] == "true" ) { Sync :: syncdata( false ); @@ -39,6 +39,7 @@ Sync :: syncdata( false ); // Decide what page to load if ( ! isset( $_GET["page"] ) ) { + if ( isset( $_SESSION['user'] ) ) { if ( Ticket_User :: isMod( unserialize( $_SESSION['ticket_user'] ) ) ) { $page = 'dashboard'; @@ -101,9 +102,6 @@ if ( isset( $_SESSION['user'] ) ) { $return['username'] = $_SESSION['user']; } - - - // Set permission if ( isset( $_SESSION['ticket_user'] ) ) { $return['permission'] = unserialize( $_SESSION['ticket_user'] ) -> getPermission(); @@ -112,7 +110,6 @@ if ( isset( $_SESSION['ticket_user'] ) ) { $return['permission'] = 0; } - // hide sidebar + topbar in case of login/register if ( $page == 'login' || $page == 'register' || $page == 'logout' || $page == 'forgot_password' || $page == 'reset_password' ) { $return['no_visible_elements'] = 'TRUE'; @@ -126,5 +123,12 @@ if ( $page == 'error' ) { $return['no_visible_elements'] = 'FALSE'; } +// call to load hooks for the active plugins +$hook_content = Plugincache :: loadHooks(); +foreach( $hook_content as $key => $value ) + { + $return[$key] = $value; + } + // load the template with the variables in the $return array helpers :: loadTemplate( $page , $return ); diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl index c50c1c20d..a0d1e49ef 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl @@ -9,6 +9,8 @@
  • Queues
  • Support Groups
  • +
  • Plugins
  • + {if isset($hook_info)} {foreach from=$hook_info item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Syncing
  • Logout
  • {/block} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl new file mode 100644 index 000000000..5bc5938c4 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl @@ -0,0 +1,12 @@ +{block name=content} +
    +{if isset($hook_info)} +{foreach from=$hook_info item=element} +{if $element.menu_display eq $smarty.get.name} +{include file=$element.template_path} +{/if} +{/foreach} +{/if} +
    +{/block} + From 1e6dc1cc37574af4bad6b175826d1267153f41bb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 02:55:46 +0200 Subject: [PATCH 112/282] Prototype of the texture chooser. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/CMakeLists.txt | 2 + .../plugins/gui_editor/gui_editor_window.cpp | 16 +++ .../plugins/gui_editor/gui_editor_window.h | 5 + .../plugins/gui_editor/texture_chooser.cpp | 98 +++++++++++++++ .../src/plugins/gui_editor/texture_chooser.h | 26 ++++ .../src/plugins/gui_editor/texture_chooser.ui | 116 ++++++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 code/studio/src/plugins/gui_editor/texture_chooser.cpp create mode 100644 code/studio/src/plugins/gui_editor/texture_chooser.h create mode 100644 code/studio/src/plugins/gui_editor/texture_chooser.ui diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 33b016bd6..31d83ae83 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -31,6 +31,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR editor_selection_watcher.h editor_message_processor.h action_list.h + texture_chooser.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS @@ -47,6 +48,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_UIS new_widget_widget.ui add_widget_widget.ui action_list.ui + texture_chooser.ui ) SET(QT_USE_QTGUI TRUE) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 9f6568936..3f4e318db 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -44,6 +44,7 @@ #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" +#include "texture_chooser.h" namespace GUIEditor { @@ -70,6 +71,8 @@ namespace GUIEditor widgetInfoTree = new CWidgetInfoTree; + tc = new TextureChooser(); + createMenus(); readSettings(); @@ -115,6 +118,9 @@ namespace GUIEditor removeMenus(); + delete tc; + tc = NULL; + delete messageProcessor; messageProcessor = NULL; @@ -353,6 +359,12 @@ namespace GUIEditor GUICtrl->show(); } + void GUIEditorWindow::onTCClicked() + { + tc->load(); + tc->exec(); + } + void GUIEditorWindow::createMenus() { Core::MenuManager *mm = Core::ICore::instance()->menuManager(); @@ -399,6 +411,10 @@ namespace GUIEditor connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); + a = new QAction( "Texture Chooser", this ); + connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onTCClicked() ) ); + m->addAction( a ); + menu = m; } } diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 15935fe74..d18a24813 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -28,6 +28,8 @@ class QtTreePropertyBrowser; class QMenu; +class TextureChooser; + namespace GUIEditor { @@ -65,6 +67,7 @@ private Q_SLOTS: void onGUILoaded(); void onAddWidgetClicked(); void onTreeChanged(); + void onTCClicked(); protected: @@ -98,6 +101,8 @@ private: QString currentProjectFile; QMenu *menu; + + TextureChooser *tc; }; } diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp new file mode 100644 index 000000000..11e5a30fd --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -0,0 +1,98 @@ +#include "texture_chooser.h" +#include "nel/misc/path.h" +#include "nel/misc/bitmap.h" +#include "nel/misc/file.h" +#include +#include +#include +#include + +TextureChooser::TextureChooser( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); + data = NULL; +} + +TextureChooser::~TextureChooser() +{ + delete data; + data = NULL; +} + + +void TextureChooser::load() +{ + listWidget->clear(); + + std::vector< std::string > textures; + NLMISC::CPath::getFileList( "tga", textures ); + + std::vector< std::string >::const_iterator itr = textures.begin(); + while( itr != textures.end() ) + { + listWidget->addItem( itr->c_str() ); + ++itr; + } +} + +void TextureChooser::onCurrentRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = listWidget->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + rfn = NLMISC::CPath::lookup( rfn ); + + NLMISC::CIFile f; + bool b = f.open( rfn ); + if( !b ) + { + return; + } + + NLMISC::CBitmap bm; + uint8 depth = bm.load( f ); + f.close(); + + uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image + + if( data != NULL ) + delete data; + + data = new uint8[ size ]; + bm.getData( data ); + + /// Convert from ABGR to ARGB + { + int i = 0; + while( i < size ) + { + uint8 t = 0; + + /// ABGR + t = data[ i ]; + data[ i ] = data[ i + 2 ]; + data[ i + 2 ] = t; + + i += 4; + } + } + + QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); + label->setPixmap( QPixmap::fromImage( img ) ); + +} + + +void TextureChooser::setupConnections() +{ + connect( listWidget, SIGNAL( currentRowChanged( int ) ), this, SLOT( onCurrentRowChanged( int ) ) ); +} + + + diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h new file mode 100644 index 000000000..fecd0aa1e --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -0,0 +1,26 @@ +#ifndef TEXTURE_CHOOSER_H +#define TEXTURE_CHOOSER_H + +#include "ui_texture_chooser.h" + +class TextureChooser : public QDialog, public Ui::TextureChooser +{ + Q_OBJECT + +public: + TextureChooser( QDialog *parent = NULL ); + ~TextureChooser(); + + void load(); + +private Q_SLOTS: + void onCurrentRowChanged( int row ); + +private: + void setupConnections(); + + unsigned char *data; +}; + +#endif + diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.ui b/code/studio/src/plugins/gui_editor/texture_chooser.ui new file mode 100644 index 000000000..0f635e96f --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_chooser.ui @@ -0,0 +1,116 @@ + + + TextureChooser + + + Qt::ApplicationModal + + + + 0 + 0 + 686 + 300 + + + + Texture Chooser + + + + + + + + + + 0 + 0 + + + + + 351 + 231 + + + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + okButton + clicked() + TextureChooser + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + TextureChooser + reject() + + + 369 + 253 + + + 179 + 282 + + + + + From 1dee9d232bb46049a6247d2a00ffa6a7ddd03ad7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 03:13:01 +0200 Subject: [PATCH 113/282] No need to store the loaded image data after passing it to the label. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/gui_editor/texture_chooser.cpp | 11 ++++------- code/studio/src/plugins/gui_editor/texture_chooser.h | 2 -- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 11e5a30fd..04328d9ef 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -12,13 +12,10 @@ QDialog( parent ) { setupUi( this ); setupConnections(); - data = NULL; } TextureChooser::~TextureChooser() { - delete data; - data = NULL; } @@ -61,10 +58,7 @@ void TextureChooser::onCurrentRowChanged( int row ) uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image - if( data != NULL ) - delete data; - - data = new uint8[ size ]; + uint8 *data = new uint8[ size ]; bm.getData( data ); /// Convert from ABGR to ARGB @@ -86,6 +80,9 @@ void TextureChooser::onCurrentRowChanged( int row ) QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); label->setPixmap( QPixmap::fromImage( img ) ); + delete data; + data = NULL; + } diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index fecd0aa1e..24b93fc40 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -18,8 +18,6 @@ private Q_SLOTS: private: void setupConnections(); - - unsigned char *data; }; #endif From 6119f2c4802cccdaaff765d08a27c114a8b9256f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 03:31:21 +0200 Subject: [PATCH 114/282] Make sure to always convert to plain bitmap. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/texture_chooser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 04328d9ef..95a081897 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -55,6 +55,11 @@ void TextureChooser::onCurrentRowChanged( int row ) NLMISC::CBitmap bm; uint8 depth = bm.load( f ); f.close(); + b = bm.convertToType( NLMISC::CBitmap::RGBA ); + if( !b ) + { + return; + } uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image From d59b6cc642b3675ce2a7eadfd639d5d81a5c3f56 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Sat, 5 Jul 2014 13:01:56 +0530 Subject: [PATCH 115/282] updates database --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/www/html/installer/libsetup.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index a590e6d7d..e8ca6d57a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -172,6 +172,26 @@ PRIMARY KEY (`Id`) ) ENGINE = InnoDB; + -- ----------------------------------------------------- + -- Table `" . $cfg['db']['lib']['name'] ."`.`updates` + -- ----------------------------------------------------- + DROP TABLE IF EXISTS `" . $cfg['db']['lib']['name'] ."`.`updates` ; + + CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`updates` ( + `s.no` int(10) NOT NULL AUTO_INCREMENT, + `PluginId` int(10) DEFAULT NULL, + `UpdatePath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `UpdateInfo` text COLLATE utf8_unicode_ci, + PRIMARY KEY (`s.no`), + KEY `PluginId` (`PluginId`)) + ENGINE=InnoDB; + + -- ----------------------------------------- + -- Constraints for table `updates` + -- ----------------------------------------- + ALTER TABLE `" . $cfg['db']['lib']['name'] ."`.`updates` + ADD CONSTRAINT `updates_ibfk_1` FOREIGN KEY (`PluginId`) REFERENCES `plugins` (`Id`); + -- ----------------------------------------------------- -- Table `" . $cfg['db']['lib']['name'] ."`.`ticket` From 931d18323b62b440dcf804d83659b653cb65a961 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 7 Jul 2014 01:48:42 +0530 Subject: [PATCH 116/282] removed merged conflicts --HG-- branch : Gsoc14-ryzomAppImprovements --- .../tools/server/ryzom_ams/ams_lib/autoload/plugincache.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index 42bdda045..b056c02bb 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -6,7 +6,6 @@ * * @author shubham meena mentored by Matthew Lagoe */ - class Plugincache { private $id; private $plugin_name; @@ -268,4 +267,4 @@ class Plugincache { } return $content; } - } + } \ No newline at end of file From fe58435bb5354b27d279389dcdb199f6fe114372 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 6 Jul 2014 23:21:25 +0200 Subject: [PATCH 117/282] CPath can now return the file list with a path filter. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/misc/path.h | 8 +++ code/nel/src/misc/path.cpp | 61 +++++++++++++++++++ .../plugins/gui_editor/texture_chooser.cpp | 3 +- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/code/nel/include/nel/misc/path.h b/code/nel/include/nel/misc/path.h index 73652a581..f3120c907 100644 --- a/code/nel/include/nel/misc/path.h +++ b/code/nel/include/nel/misc/path.h @@ -200,6 +200,10 @@ public: */ void getFileListByName(const std::string &extension, const std::string &name, std::vector &filenames); + /** Create a list of file having the requested string in the path and the requested extension. + */ + void getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames); + /** Make a path relative to another if possible, else doesn't change it. * \param basePath is the base path to be relative to. * \param relativePath is the path to make relative to basePath. @@ -492,6 +496,10 @@ public: */ static void getFileListByName(const std::string &extension, const std::string &name, std::vector &filenames); + /** Create a list of file having the requested string in the path and the requested extension + */ + static void getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames); + /** Make a path relative to another if possible, else doesn't change it. * \param basePath is the base path to be relative to. * \param relativePath is the path to make relative to basePath. diff --git a/code/nel/src/misc/path.cpp b/code/nel/src/misc/path.cpp index f92b0bda7..c5a80e830 100644 --- a/code/nel/src/misc/path.cpp +++ b/code/nel/src/misc/path.cpp @@ -219,6 +219,67 @@ void CFileContainer::getFileListByName(const std::string &extension, const std:: } } +void CPath::getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames) +{ + getInstance()->_FileContainer.getFileListByPath(extension, path, filenames); +} + +void CFileContainer::getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames) +{ + if (!_MemoryCompressed) + { + TFiles::iterator first(_Files.begin()), last(_Files.end()); + + if( !path.empty() ) + { + for (; first != last; ++ first) + { + string ext = SSMext.get(first->second.idExt); + string p = SSMpath.get(first->second.idPath); + if (p.find(path) != string::npos && (ext == extension || extension.empty())) + { + filenames.push_back(first->first); + } + } + } + // if extension is empty we keep all files + else + { + for (; first != last; ++ first) + { + filenames.push_back(first->first); + } + } + } + else + { + // compressed memory version + std::vector::iterator first(_MCFiles.begin()), last(_MCFiles.end()); + + if( !path.empty() ) + { + for (; first != last; ++ first) + { + string ext = SSMext.get(first->idExt); + string p = SSMpath.get(first->idPath); + + if (strstr(p.c_str(), path.c_str()) != NULL && (ext == extension || extension.empty())) + { + filenames.push_back(first->Name); + } + } + } + // if extension is empty we keep all files + else + { + for (; first != last; ++ first) + { + filenames.push_back(first->Name); + } + } + } +} + void CPath::clearMap () { getInstance()->_FileContainer.clearMap(); diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 95a081897..7545d2803 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -24,7 +24,8 @@ void TextureChooser::load() listWidget->clear(); std::vector< std::string > textures; - NLMISC::CPath::getFileList( "tga", textures ); + //NLMISC::CPath::getFileList( "tga", textures ); + NLMISC::CPath::getFileListByPath( "tga", "interfaces", textures ); std::vector< std::string >::const_iterator itr = textures.begin(); while( itr != textures.end() ) From 4c0d3e53fc0aaddc378b14575dcd855537bc35f8 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 7 Jul 2014 13:56:58 +0530 Subject: [PATCH 118/282] fixed few bugs --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 20 ++++---- .../ryzom_ams/ams_lib/autoload/users.php | 12 ++--- .../ryzom_ams/www/html/func/delete_plugin.php | 23 +-------- .../ryzom_ams/www/html/installer/libsetup.php | 47 ++++++++++--------- .../www/html/templates/layout_user.tpl | 1 + 5 files changed, 39 insertions(+), 64 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index 7c43e1877..ae8f1129c 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -173,17 +173,13 @@ class Plugincache { * @return boolean */ public static function rrmdir( $dir ) { - if ( is_dir( $dir ) ) { - $objects = scandir( $dir ); - foreach ( $objects as $object ) { - if ( $object != "." && $object != ".." ) { - if ( filetype( $dir . "/" . $object ) == "dir" ) rmdir( $dir . "/" . $object ); - else unlink( $dir . "/" . $object ); - } - } - reset( $objects ); - return rmdir( $dir ); - } + $result=array_diff(scandir($dir),array('.','..')); + foreach($result as $item) + { + if(!@unlink($dir.'/'.$item)) + Plugincache::rrmdir($dir.'/'.$item); + } + return rmdir($dir); } /** @@ -267,4 +263,4 @@ class Plugincache { } return $content; } - } \ No newline at end of file + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php index e9463b0b0..b398270e4 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php @@ -289,12 +289,13 @@ class Users{ public static function createUser($values, $user_id){ try { //make connection with and put into shard db - $values['user_id']= $user_id; $dbs = new DBLayer("shard"); $dbs->insert("user", $values); $dbr = new DBLayer("ring"); - $values['user_type'] = 'ut_pioneer'; - $dbr->insert("ring_users", $values); + $valuesRing['user_id'] =$user_id; + $valuesRing['user_name'] = $values['Login']; + $valuesRing['user_type'] = 'ut_pioneer'; + $dbr->insert("ring_users", $valuesRing); ticket_user::createTicketUser( $user_id, 1); return "ok"; } @@ -303,7 +304,7 @@ class Users{ try { $dbl = new DBLayer("lib"); $dbl->insert("ams_querycache", array("type" => "createUser", - "query" => json_encode(array($values["name"],$values["pass"],$values["mail"])), "db" => "shard")); + "query" => json_encode(array($values["Login"],$values["Password"],$values["Email"])), "db" => "shard")); ticket_user::createTicketUser( $user_id , 1 ); return "shardoffline"; }catch (PDOException $e) { @@ -472,6 +473,3 @@ class Users{ } } } - - - diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php index 53af36157..f3dc0311a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/delete_plugin.php @@ -23,7 +23,7 @@ function delete_plugin() { if ( is_dir( "$name[FileName]" ) ) { // removing plugin directory from the code base - if ( rrmdir( "$name[FileName]" ) ) + if ( Plugincache::rrmdir( "$name[FileName]" ) ) { $db -> delete( 'plugins', array( 'id' => $id ), "Id=:id" ); @@ -45,24 +45,3 @@ function delete_plugin() { } } } - -/** - * function to remove a non empty directory - * - * @param $dir directory address - * @return boolean - */ -function rrmdir( $dir ) { - if ( is_dir( $dir ) ) { - $objects = scandir( $dir ); - foreach ( $objects as $object ) { - if ( $object != "." && $object != ".." ) { - if ( filetype( $dir . "/" . $object ) == "dir" ) rmdir( $dir . "/" . $object ); - else unlink( $dir . "/" . $object ); - } - } - reset( $objects ); - return rmdir( $dir ); - } - } - diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index 492f67549..d020f1644 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -184,37 +184,38 @@ DROP TABLE IF EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ; CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ( - `Id` INT(10) NOT NULL AUTO_INCREMENT, - `FileName VARCHAR(255) NOT NULL, + `Id` INT(10) NOT NULL AUTO_INCREMENT, + `FileName` VARCHAR(255) NOT NULL, `Name` VARCHAR(11) NOT NULL, `Type` VARCHAR(12) NOT NULL, `Owner` VARCHAR(25) NOT NULL, `Permission` VARCHAR(5) NOT NULL, `Status` INT(11) NOT NULL DEFAULT 0, `Weight` INT(11) NOT NULL DEFAULT 0, - `Info` TEXT NULL DEFAULT NULL, + `Info` TEXT NULL DEFAULT NULL, PRIMARY KEY (`Id`) ) ENGINE = InnoDB; + -- ----------------------------------------------------- -- Table `" . $cfg['db']['lib']['name'] ."`.`updates` -- ----------------------------------------------------- DROP TABLE IF EXISTS `" . $cfg['db']['lib']['name'] ."`.`updates` ; CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`updates` ( - `s.no` int(10) NOT NULL AUTO_INCREMENT, - `PluginId` int(10) DEFAULT NULL, - `UpdatePath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, - `UpdateInfo` text COLLATE utf8_unicode_ci, - PRIMARY KEY (`s.no`), - KEY `PluginId` (`PluginId`)) - ENGINE=InnoDB; - - -- ----------------------------------------- - -- Constraints for table `updates` - -- ----------------------------------------- - ALTER TABLE `" . $cfg['db']['lib']['name'] ."`.`updates` - ADD CONSTRAINT `updates_ibfk_1` FOREIGN KEY (`PluginId`) REFERENCES `plugins` (`Id`); + `s.no` int(10) NOT NULL AUTO_INCREMENT, + `PluginId` int(10) DEFAULT NULL, + `UpdatePath` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, + `UpdateInfo` text COLLATE utf8_unicode_ci, + PRIMARY KEY (`s.no`), + KEY `PluginId` (`PluginId`)) + ENGINE=InnoDB; + + -- ----------------------------------------- + -- Constraints for table `updates` + -- ----------------------------------------- + ALTER TABLE `" . $cfg['db']['lib']['name'] ."`.`updates` + ADD CONSTRAINT `updates_ibfk_1` FOREIGN KEY (`PluginId`) REFERENCES `plugins` (`Id`); -- ----------------------------------------------------- @@ -1772,14 +1773,14 @@ //Now create an admin account! $hashpass = crypt("admin", Users::generateSALT()); $params = array( - 'name' => "admin", - 'pass' => $hashpass, - 'mail' => "admin@admin.com", + 'Login' => "admin", + 'Password' => $hashpass, + 'Email' => "admin@admin.com", ); try{ - $user_id = WebUsers::createWebuser($params['name'], $params['pass'],$params['mail']); + $user_id = WebUsers::createWebuser($params['Login'], $params['Password'],$params['Email']); $result = Webusers::createUser($params, $user_id); - Users::createPermissions(array($params['name'])); + Users::createPermissions(array($params['Login'])); $dbl = new DBLayer("lib"); $dbl->execute("UPDATE ticket_user SET Permission = 3 WHERE TUserId = :user_id",array('user_id' => $user_id)); print "The admin account is created, you can login with id: admin, pass: admin!"; @@ -1802,5 +1803,5 @@ print "There was an error while installing"; print_r($e); } - } - + } + diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl index 301af12b6..4b452962a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl @@ -5,6 +5,7 @@
  • Settings
  • Create New Ticket
  • + {if isset($hook_info)} {foreach from=$hook_info item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Logout
  • {/block} From 396a3c2db2ae58ac30d8279ca00d4bdfc433bb85 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 7 Jul 2014 19:19:03 +0200 Subject: [PATCH 119/282] Allow TextureChooser's texture selection to be queried. --HG-- branch : gsoc2014-dfighter --- .../plugins/gui_editor/texture_chooser.cpp | 19 +++++++++++++++++++ .../src/plugins/gui_editor/texture_chooser.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 7545d2803..d857d9bdc 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -33,6 +33,25 @@ void TextureChooser::load() listWidget->addItem( itr->c_str() ); ++itr; } + + listWidget->setCurrentRow( 0 ); +} + +void TextureChooser::accept() +{ + QListWidgetItem *item = listWidget->currentItem(); + if( item == NULL ) + return; + + selection = item->text(); + QDialog::accept(); +} + +void TextureChooser::reject() +{ + selection = ""; + + QDialog::reject(); } void TextureChooser::onCurrentRowChanged( int row ) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index 24b93fc40..bab1dd1dc 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -12,12 +12,19 @@ public: ~TextureChooser(); void load(); + QString getSelection(){ return selection; } + +public Q_SLOTS: + void accept(); + void reject(); private Q_SLOTS: void onCurrentRowChanged( int row ); private: void setupConnections(); + + QString selection; }; #endif From 7cbc82fe8f8246178a109cb5d9d0f1258eb0f327 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 8 Jul 2014 18:26:20 +0200 Subject: [PATCH 120/282] Added action property editor, editor factory, manager. Actions can now be edited using the editor widget in the property tree. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/CMakeLists.txt | 1 + .../gui_editor/action_property_manager.cpp | 333 ++++++++++++++++++ .../gui_editor/action_property_manager.h | 125 +++++++ .../gui_editor/property_browser_ctrl.cpp | 45 ++- .../gui_editor/property_browser_ctrl.h | 6 + .../gui_editor/widgets/CtrlBaseButton.xml | 12 +- .../gui_editor/widgets/GroupContainer.xml | 16 +- .../gui_editor/widgets/InterfaceGroup.xml | 10 +- .../widgets/InterfaceGroupWheel.xml | 4 +- 9 files changed, 529 insertions(+), 23 deletions(-) create mode 100644 code/studio/src/plugins/gui_editor/action_property_manager.cpp create mode 100644 code/studio/src/plugins/gui_editor/action_property_manager.h diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 31d83ae83..f95e6c0a7 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -32,6 +32,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR editor_message_processor.h action_list.h texture_chooser.h + action_property_manager.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS diff --git a/code/studio/src/plugins/gui_editor/action_property_manager.cpp b/code/studio/src/plugins/gui_editor/action_property_manager.cpp new file mode 100644 index 000000000..9e7690a56 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_property_manager.cpp @@ -0,0 +1,333 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "action_property_manager.h" +#include "action_list.h" +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + + +struct ActionPropertyManagerPrivate +{ + QMap< const QtProperty*, QString > values; +}; + +ActionPropertyManager::ActionPropertyManager( QObject *parent ) : +QtAbstractPropertyManager( parent ) +{ + d_ptr = new ActionPropertyManagerPrivate(); +} + +ActionPropertyManager::~ActionPropertyManager() +{ + delete d_ptr; + d_ptr = NULL; +} + +QString ActionPropertyManager::value( const QtProperty *p ) const +{ + return valueText( p ); +} + +void ActionPropertyManager::setValue( QtProperty *p, const QString &value ) +{ + if( !d_ptr->values.contains( p ) ) + return; + + if( d_ptr->values[ p ] == value ) + return; + + d_ptr->values[ p ] = value; + + Q_EMIT propertyChanged( p ); + Q_EMIT valueChanged( p, value ); +} + +bool ActionPropertyManager::hasValue( const QtProperty *p ) const +{ + return d_ptr->values.contains( p ); +} + +QString ActionPropertyManager::valueText( const QtProperty *p ) const +{ + if( !d_ptr->values.contains( p ) ) + return ""; + + return d_ptr->values[ p ]; +} + +void ActionPropertyManager::initializeProperty( QtProperty *p ) +{ + if( d_ptr->values.contains( p ) ) + return; + + d_ptr->values[ p ] = ""; +} + +void ActionPropertyManager::uninitializeProperty( QtProperty *p ) +{ + d_ptr->values.remove( p ); +} + + + +//////////////////////////////////////////////////////////////////// Factory /////////////////////////////////////////////////////////////////////// + + + +struct ActionEditorFactoryPrivate +{ + QMap< QtProperty*, QList< ActionPropertyEditor* > > createdEditors; + QMap< ActionPropertyEditor*, QtProperty* > editorToProperty; + + ~ActionEditorFactoryPrivate() + { + createdEditors.clear(); + + QMap< ActionPropertyEditor*, QtProperty* >::iterator itr = editorToProperty.begin(); + while( itr != editorToProperty.end() ) + { + delete itr.key(); + ++itr; + } + editorToProperty.clear(); + } + + void addEditor( QtProperty *p, ActionPropertyEditor *editor ) + { + QMap< QtProperty*, QList< ActionPropertyEditor* > >::iterator itr = createdEditors.find( p ); + + if( itr != createdEditors.end() ) + { + itr->push_back( editor ); + } + else + { + QList< ActionPropertyEditor* > l; + l.push_back( editor ); + createdEditors.insert( p, l ); + } + + editorToProperty.insert( editor, p ); + } + + void removeEditor( QObject *o ) + { + // Remove from editorToProperty first + QMap< ActionPropertyEditor*, QtProperty* >::iterator itr1 = editorToProperty.begin(); + while( itr1 != editorToProperty.end() ) + { + if( itr1.key() == o ) + break; + + ++itr1; + } + if( itr1 != editorToProperty.end() ) + editorToProperty.erase( itr1 ); + + // Then from createdEditors + QMap< QtProperty*, QList< ActionPropertyEditor* > >::iterator itr2 = createdEditors.begin(); + while( itr2 != createdEditors.end() ) + { + QList< ActionPropertyEditor* > &l = *itr2; + QList< ActionPropertyEditor* >::iterator itr = l.begin(); + while( itr != l.end() ) + { + if( *itr == o ) + { + QList< ActionPropertyEditor* >::iterator d = itr; + ++itr; + l.erase( d ); + continue; + } + + ++itr; + } + + ++itr2; + } + } + +}; + +ActionEditorFactory::ActionEditorFactory( QObject *parent ) : +QtAbstractEditorFactory( parent ) +{ + d_ptr = new ActionEditorFactoryPrivate(); +} + +ActionEditorFactory::~ActionEditorFactory() +{ + delete d_ptr; + d_ptr = NULL; +} + +void ActionEditorFactory::connectPropertyManager( ActionPropertyManager *manager ) +{ + connect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +void ActionEditorFactory::disconnectPropertyManager( ActionPropertyManager *manager ) +{ + disconnect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +QWidget* ActionEditorFactory::createEditor( ActionPropertyManager *manager, QtProperty *p, QWidget *parent ) +{ + ActionPropertyEditor *editor = new ActionPropertyEditor( parent ); + editor->setValue( manager->value( p ) ); + + connect( editor, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onSetValue( const QString& ) ) ); + connect( editor, SIGNAL( destroyed( QObject* ) ), this, SLOT( onEditorDestroyed( QObject* ) ) ); + + d_ptr->addEditor( p, editor ); + + return editor; +} + +void ActionEditorFactory::onPropertyChanged( QtProperty *p, const QString &value ) +{ + QMap< QtProperty*, QList< ActionPropertyEditor* > >::iterator itr = d_ptr->createdEditors.find( p ); + if( itr == d_ptr->createdEditors.end() ) + return; + + QList< ActionPropertyEditor* > &l = *itr; + QList< ActionPropertyEditor* >::iterator i = l.begin(); + while( i != l.end() ) + { + ActionPropertyEditor *editor = *i; + + editor->blockSignals( true ); + editor->setValue( value ); + editor->blockSignals( false ); + + ++i; + } +} + +void ActionEditorFactory::onSetValue( const QString &value ) +{ + QObject *s = sender(); + ActionPropertyEditor *editor = qobject_cast< ActionPropertyEditor* >( s ); + if( editor == NULL ) + return; + + QMap< ActionPropertyEditor*, QtProperty* >::iterator itr = d_ptr->editorToProperty.find( editor ); + if( itr == d_ptr->editorToProperty.end() ) + return; + + QtProperty *p = *itr; + + ActionPropertyManager *manager = qobject_cast< ActionPropertyManager* >( p->propertyManager() ); + if( manager == NULL ) + return; + + blockSignals( true ); + manager->setValue( p, value ); + blockSignals( false ); +} + +void ActionEditorFactory::onEditorDestroyed( QObject *editor ) +{ + d_ptr->removeEditor( editor ); +} + + + +//////////////////////////////////////////////////////////////////////// Editor ////////////////////////////////////////////////////////////////// + + + +ActionPropertyEditor::ActionPropertyEditor( QWidget *parent ) : +QWidget( parent ) +{ + setupUi(); + setupConnections(); +} + +ActionPropertyEditor::~ActionPropertyEditor() +{ +} + +void ActionPropertyEditor::setValue( const QString &value ) +{ + if( lineEdit->text() == value ) + return; + + disableConnections(); + lineEdit->setText( value ); + setupConnections(); +} + +void ActionPropertyEditor::showEvent( QShowEvent *e ) +{ + QWidget::showEvent( e ); +} + +void ActionPropertyEditor::onToolButtonClicked() +{ + ActionList d; + d.load(); + + int result = d.exec(); + if( QDialog::Accepted != result ) + return; + + lineEdit->setText( d.getSelectedAction() ); +} + +void ActionPropertyEditor::onTextChanged( const QString &text ) +{ + Q_EMIT valueChanged( text ); +} + +void ActionPropertyEditor::setupConnections() +{ + connect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + connect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ActionPropertyEditor::disableConnections() +{ + disconnect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + disconnect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ActionPropertyEditor::setupUi() +{ + lineEdit = new QLineEdit(); + toolButton = new QToolButton(); + toolButton->setText( "..." ); + + QHBoxLayout *lt = new QHBoxLayout( this ); + lt->setContentsMargins( 0, 0, 0, 0 ); + lt->setSpacing( 0 ); + lt->addWidget( lineEdit ); + lt->addWidget( toolButton ); + + setFocusProxy( lineEdit ); + setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); + +} + + diff --git a/code/studio/src/plugins/gui_editor/action_property_manager.h b/code/studio/src/plugins/gui_editor/action_property_manager.h new file mode 100644 index 000000000..06cd714d7 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_property_manager.h @@ -0,0 +1,125 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef ACTION_PROPERTY_MANAGER +#define ACTION_PROPERTY_MANAGER + +#define QT_QTPROPERTYBROWSER_IMPORT + +#include "3rdparty/qtpropertybrowser/qtpropertybrowser.h" +#include + +/////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + +struct ActionPropertyManagerPrivate; + +class ActionPropertyManager : public QtAbstractPropertyManager +{ + Q_OBJECT + +public: + ActionPropertyManager( QObject *parent = NULL ); + ~ActionPropertyManager(); + + QString value( const QtProperty *p ) const; + +public Q_SLOTS: + void setValue( QtProperty *p, const QString &value ); + +Q_SIGNALS: + void valueChanged( QtProperty *p, const QString &value ); + +protected: + bool hasValue( const QtProperty *p ) const; + QString valueText( const QtProperty *p ) const; + void initializeProperty( QtProperty *p ); + void uninitializeProperty( QtProperty *p ); + +private: + ActionPropertyManagerPrivate *d_ptr; + + Q_DISABLE_COPY( ActionPropertyManager ); +}; + + +////////////////////////////////////////////////////////////////// Factory ///////////////////////////////////////////////////////////////////////// + +struct ActionEditorFactoryPrivate; + +class ActionEditorFactory : public QtAbstractEditorFactory< ActionPropertyManager > +{ + Q_OBJECT + +public: + ActionEditorFactory( QObject *parent = NULL ); + ~ActionEditorFactory(); + +protected: + void connectPropertyManager( ActionPropertyManager *manager ); + void disconnectPropertyManager( ActionPropertyManager *manager ); + + QWidget* createEditor( ActionPropertyManager *manager, QtProperty *p, QWidget *parent ); + +private Q_SLOTS: + void onPropertyChanged( QtProperty *p, const QString &value ); + void onSetValue( const QString &value ); + void onEditorDestroyed( QObject *editor ); + +private: + ActionEditorFactoryPrivate *d_ptr; + + Q_DISABLE_COPY( ActionEditorFactory ); +}; + + +///////////////////////////////////////////////////////////////// Editor /////////////////////////////////////////////////////////////////////////// + +class QLineEdit; +class QToolButton; + +class ActionPropertyEditor : public QWidget +{ + Q_OBJECT +public: + ActionPropertyEditor( QWidget *parent = NULL ); + ~ActionPropertyEditor(); + +public Q_SLOTS: + void setValue( const QString &value ); + +protected: + void showEvent( QShowEvent *e ); + +private Q_SLOTS: + void onToolButtonClicked(); + void onTextChanged( const QString &text ); + +Q_SIGNALS: + void valueChanged( const QString &value ); + +private: + void setupUi(); + void setupConnections(); + void disableConnections(); + + + QLineEdit *lineEdit; + QToolButton *toolButton; +}; + +#endif + diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index e3594edb0..e7029dd37 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -26,6 +26,8 @@ #include "widget_info_tree.h" #include +#include "action_property_manager.h" + namespace { class NelBMAlign @@ -368,9 +370,11 @@ namespace GUIEditor browser = NULL; propertyMgr = new QtVariantPropertyManager; enumMgr = new QtEnumPropertyManager; + actionMgr = new ActionPropertyManager; variantFactory = new QtVariantEditorFactory; enumFactory = new QtEnumEditorFactory; + actionFactory = new ActionEditorFactory; ttPairs[ "tooltip_posref" ] = "tooltip_parent_posref"; ttPairs[ "tooltip_parent_posref" ] = "tooltip_posref"; @@ -381,11 +385,15 @@ namespace GUIEditor CPropBrowserCtrl::~CPropBrowserCtrl() { + delete actionMgr; + actionMgr = NULL; delete enumMgr; enumMgr = NULL; delete propertyMgr; propertyMgr = NULL; + delete actionFactory; + actionFactory = NULL; delete variantFactory; variantFactory = NULL; delete enumFactory; @@ -447,7 +455,7 @@ namespace GUIEditor // probably the clear() method clears them too... browser->setFactoryForManager( propertyMgr, variantFactory ); browser->setFactoryForManager( enumMgr, enumFactory ); - + browser->setFactoryForManager( actionMgr, actionFactory ); enablePropertyWatchers(); } @@ -617,12 +625,27 @@ namespace GUIEditor } } + + void CPropBrowserCtrl::onActionPropertyChanged( QtProperty *p, const QString &v ) + { + QString propName = p->propertyName(); + + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); + } + void CPropBrowserCtrl::enablePropertyWatchers() { connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + + connect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::disablePropertyWatchers() @@ -631,6 +654,9 @@ namespace GUIEditor this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + + disconnect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) @@ -656,7 +682,22 @@ namespace GUIEditor { QtVariantProperty *p = NULL; QVariant v; - + + if( prop.propType == "action" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + QtProperty *pp = actionMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + actionMgr->setValue( pp, j.c_str() ); + browser->addProperty( pp ); + } + else if( prop.propType == "bitmap_align" ) { std::string j = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index bec4004d3..80118bc0b 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -31,6 +31,9 @@ class QtEnumEditorFactory; class QtProperty; class QVariant; +class ActionPropertyManager; +class ActionEditorFactory; + namespace NLGUI { class CInterfaceElement; @@ -59,6 +62,7 @@ namespace GUIEditor private Q_SLOTS: void onPropertyChanged( QtProperty *prop, const QVariant &v ); void onEnumPropertyChanged( QtProperty *prop, int value ); + void onActionPropertyChanged( QtProperty *p, const QString &v ); private: void enablePropertyWatchers(); @@ -70,9 +74,11 @@ namespace GUIEditor QtTreePropertyBrowser *browser; QtVariantPropertyManager *propertyMgr; QtEnumPropertyManager *enumMgr; + ActionPropertyManager *actionMgr; QtVariantEditorFactory *variantFactory; QtEnumEditorFactory *enumFactory; + ActionEditorFactory *actionFactory; std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml index 72e362556..33f9f3a3f 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml @@ -60,7 +60,7 @@
    onover - string + action @@ -70,7 +70,7 @@ onclick_l - string + action @@ -80,7 +80,7 @@ ondblclick_l - string + action @@ -90,7 +90,7 @@ onclick_r - string + action @@ -100,7 +100,7 @@ onlongclick_l - string + action @@ -110,7 +110,7 @@ onclock_tick - string + action diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml index b374bca19..3d879a150 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml @@ -110,7 +110,7 @@ on_open - string + action @@ -120,7 +120,7 @@ on_close - string + action @@ -130,7 +130,7 @@ on_close_button - string + action @@ -140,7 +140,7 @@ on_move - string + action @@ -150,7 +150,7 @@ on_deactive_check - string + action @@ -160,7 +160,7 @@ on_resize - string + action @@ -170,7 +170,7 @@ on_alpha_settings_changed - string + action @@ -180,7 +180,7 @@ on_begin_move - string + action diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml index b9e99d336..ddcdf01e6 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml @@ -40,7 +40,7 @@ on_active - string + action @@ -50,7 +50,7 @@ on_deactive - string + action @@ -80,7 +80,7 @@ group_onclick_r - string + action @@ -90,7 +90,7 @@ group_onclick_l - string + action @@ -100,7 +100,7 @@ on_enter - string + action handler diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml index 62d67cc0a..b095ecac5 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml @@ -10,7 +10,7 @@ on_wheel_up - string + action @@ -20,7 +20,7 @@ on_wheel_down - string + action From a1b0f9d7e21221fe0674b2bfd2e3c610ae6bf226 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 8 Jul 2014 18:59:30 +0200 Subject: [PATCH 121/282] Added texture property editor, editor factory, manager. Textures can now be selected using these in the property tree browser. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/CMakeLists.txt | 1 + .../gui_editor/property_browser_ctrl.cpp | 38 ++ .../gui_editor/property_browser_ctrl.h | 5 + .../gui_editor/texture_property_manager.cpp | 333 ++++++++++++++++++ .../gui_editor/texture_property_manager.h | 125 +++++++ .../plugins/gui_editor/widgets/ViewBitmap.xml | 2 +- 6 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/gui_editor/texture_property_manager.cpp create mode 100644 code/studio/src/plugins/gui_editor/texture_property_manager.h diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index f95e6c0a7..4b50ec8d1 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -33,6 +33,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR action_list.h texture_chooser.h action_property_manager.h + texture_property_manager.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index e7029dd37..bd73fb7fa 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -27,6 +27,7 @@ #include #include "action_property_manager.h" +#include "texture_property_manager.h" namespace { @@ -371,10 +372,12 @@ namespace GUIEditor propertyMgr = new QtVariantPropertyManager; enumMgr = new QtEnumPropertyManager; actionMgr = new ActionPropertyManager; + textureMgr = new TexturePropertyManager; variantFactory = new QtVariantEditorFactory; enumFactory = new QtEnumEditorFactory; actionFactory = new ActionEditorFactory; + textureFactory = new TextureEditorFactory; ttPairs[ "tooltip_posref" ] = "tooltip_parent_posref"; ttPairs[ "tooltip_parent_posref" ] = "tooltip_posref"; @@ -385,6 +388,8 @@ namespace GUIEditor CPropBrowserCtrl::~CPropBrowserCtrl() { + delete textureMgr; + textureMgr = NULL; delete actionMgr; actionMgr = NULL; delete enumMgr; @@ -392,6 +397,8 @@ namespace GUIEditor delete propertyMgr; propertyMgr = NULL; + delete textureFactory; + textureFactory = NULL; delete actionFactory; actionFactory = NULL; delete variantFactory; @@ -456,6 +463,7 @@ namespace GUIEditor browser->setFactoryForManager( propertyMgr, variantFactory ); browser->setFactoryForManager( enumMgr, enumFactory ); browser->setFactoryForManager( actionMgr, actionFactory ); + browser->setFactoryForManager( textureMgr, textureFactory ); enablePropertyWatchers(); } @@ -637,6 +645,17 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); } + void CPropBrowserCtrl::onTexturePropertyChanged( QtProperty *p, const QString &v ) + { + QString propName = p->propertyName(); + + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); + } + void CPropBrowserCtrl::enablePropertyWatchers() { connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), @@ -646,6 +665,8 @@ namespace GUIEditor connect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); + connect( textureMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onTexturePropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::disablePropertyWatchers() @@ -657,6 +678,8 @@ namespace GUIEditor disconnect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); + disconnect( textureMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onTexturePropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) @@ -683,6 +706,21 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "texture" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + QtProperty *pp = textureMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + textureMgr->setValue( pp, j.c_str() ); + browser->addProperty( pp ); + } + else if( prop.propType == "action" ) { std::string j = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index 80118bc0b..abf80d7de 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -33,6 +33,8 @@ class QVariant; class ActionPropertyManager; class ActionEditorFactory; +class TexturePropertyManager; +class TextureEditorFactory; namespace NLGUI { @@ -63,6 +65,7 @@ namespace GUIEditor void onPropertyChanged( QtProperty *prop, const QVariant &v ); void onEnumPropertyChanged( QtProperty *prop, int value ); void onActionPropertyChanged( QtProperty *p, const QString &v ); + void onTexturePropertyChanged( QtProperty *p, const QString &v ); private: void enablePropertyWatchers(); @@ -75,10 +78,12 @@ namespace GUIEditor QtVariantPropertyManager *propertyMgr; QtEnumPropertyManager *enumMgr; ActionPropertyManager *actionMgr; + TexturePropertyManager *textureMgr; QtVariantEditorFactory *variantFactory; QtEnumEditorFactory *enumFactory; ActionEditorFactory *actionFactory; + TextureEditorFactory *textureFactory; std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; diff --git a/code/studio/src/plugins/gui_editor/texture_property_manager.cpp b/code/studio/src/plugins/gui_editor/texture_property_manager.cpp new file mode 100644 index 000000000..6b40abc7f --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_property_manager.cpp @@ -0,0 +1,333 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "texture_property_manager.h" +#include "texture_chooser.h" +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + + +struct TexturePropertyManagerPrivate +{ + QMap< const QtProperty*, QString > values; +}; + +TexturePropertyManager::TexturePropertyManager( QObject *parent ) : +QtAbstractPropertyManager( parent ) +{ + d_ptr = new TexturePropertyManagerPrivate(); +} + +TexturePropertyManager::~TexturePropertyManager() +{ + delete d_ptr; + d_ptr = NULL; +} + +QString TexturePropertyManager::value( const QtProperty *p ) const +{ + return valueText( p ); +} + +void TexturePropertyManager::setValue( QtProperty *p, const QString &value ) +{ + if( !d_ptr->values.contains( p ) ) + return; + + if( d_ptr->values[ p ] == value ) + return; + + d_ptr->values[ p ] = value; + + Q_EMIT propertyChanged( p ); + Q_EMIT valueChanged( p, value ); +} + +bool TexturePropertyManager::hasValue( const QtProperty *p ) const +{ + return d_ptr->values.contains( p ); +} + +QString TexturePropertyManager::valueText( const QtProperty *p ) const +{ + if( !d_ptr->values.contains( p ) ) + return ""; + + return d_ptr->values[ p ]; +} + +void TexturePropertyManager::initializeProperty( QtProperty *p ) +{ + if( d_ptr->values.contains( p ) ) + return; + + d_ptr->values[ p ] = ""; +} + +void TexturePropertyManager::uninitializeProperty( QtProperty *p ) +{ + d_ptr->values.remove( p ); +} + + + +//////////////////////////////////////////////////////////////////// Factory /////////////////////////////////////////////////////////////////////// + + + +struct TextureEditorFactoryPrivate +{ + QMap< QtProperty*, QList< TexturePropertyEditor* > > createdEditors; + QMap< TexturePropertyEditor*, QtProperty* > editorToProperty; + + ~TextureEditorFactoryPrivate() + { + createdEditors.clear(); + + QMap< TexturePropertyEditor*, QtProperty* >::iterator itr = editorToProperty.begin(); + while( itr != editorToProperty.end() ) + { + delete itr.key(); + ++itr; + } + editorToProperty.clear(); + } + + void addEditor( QtProperty *p, TexturePropertyEditor *editor ) + { + QMap< QtProperty*, QList< TexturePropertyEditor* > >::iterator itr = createdEditors.find( p ); + + if( itr != createdEditors.end() ) + { + itr->push_back( editor ); + } + else + { + QList< TexturePropertyEditor* > l; + l.push_back( editor ); + createdEditors.insert( p, l ); + } + + editorToProperty.insert( editor, p ); + } + + void removeEditor( QObject *o ) + { + // Remove from editorToProperty first + QMap< TexturePropertyEditor*, QtProperty* >::iterator itr1 = editorToProperty.begin(); + while( itr1 != editorToProperty.end() ) + { + if( itr1.key() == o ) + break; + + ++itr1; + } + if( itr1 != editorToProperty.end() ) + editorToProperty.erase( itr1 ); + + // Then from createdEditors + QMap< QtProperty*, QList< TexturePropertyEditor* > >::iterator itr2 = createdEditors.begin(); + while( itr2 != createdEditors.end() ) + { + QList< TexturePropertyEditor* > &l = *itr2; + QList< TexturePropertyEditor* >::iterator itr = l.begin(); + while( itr != l.end() ) + { + if( *itr == o ) + { + QList< TexturePropertyEditor* >::iterator d = itr; + ++itr; + l.erase( d ); + continue; + } + + ++itr; + } + + ++itr2; + } + } + +}; + +TextureEditorFactory::TextureEditorFactory( QObject *parent ) : +QtAbstractEditorFactory( parent ) +{ + d_ptr = new TextureEditorFactoryPrivate(); +} + +TextureEditorFactory::~TextureEditorFactory() +{ + delete d_ptr; + d_ptr = NULL; +} + +void TextureEditorFactory::connectPropertyManager( TexturePropertyManager *manager ) +{ + connect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +void TextureEditorFactory::disconnectPropertyManager( TexturePropertyManager *manager ) +{ + disconnect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +QWidget* TextureEditorFactory::createEditor( TexturePropertyManager *manager, QtProperty *p, QWidget *parent ) +{ + TexturePropertyEditor *editor = new TexturePropertyEditor( parent ); + editor->setValue( manager->value( p ) ); + + connect( editor, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onSetValue( const QString& ) ) ); + connect( editor, SIGNAL( destroyed( QObject* ) ), this, SLOT( onEditorDestroyed( QObject* ) ) ); + + d_ptr->addEditor( p, editor ); + + return editor; +} + +void TextureEditorFactory::onPropertyChanged( QtProperty *p, const QString &value ) +{ + QMap< QtProperty*, QList< TexturePropertyEditor* > >::iterator itr = d_ptr->createdEditors.find( p ); + if( itr == d_ptr->createdEditors.end() ) + return; + + QList< TexturePropertyEditor* > &l = *itr; + QList< TexturePropertyEditor* >::iterator i = l.begin(); + while( i != l.end() ) + { + TexturePropertyEditor *editor = *i; + + editor->blockSignals( true ); + editor->setValue( value ); + editor->blockSignals( false ); + + ++i; + } +} + +void TextureEditorFactory::onSetValue( const QString &value ) +{ + QObject *s = sender(); + TexturePropertyEditor *editor = qobject_cast< TexturePropertyEditor* >( s ); + if( editor == NULL ) + return; + + QMap< TexturePropertyEditor*, QtProperty* >::iterator itr = d_ptr->editorToProperty.find( editor ); + if( itr == d_ptr->editorToProperty.end() ) + return; + + QtProperty *p = *itr; + + TexturePropertyManager *manager = qobject_cast< TexturePropertyManager* >( p->propertyManager() ); + if( manager == NULL ) + return; + + blockSignals( true ); + manager->setValue( p, value ); + blockSignals( false ); +} + +void TextureEditorFactory::onEditorDestroyed( QObject *editor ) +{ + d_ptr->removeEditor( editor ); +} + + + +//////////////////////////////////////////////////////////////////////// Editor ////////////////////////////////////////////////////////////////// + + + +TexturePropertyEditor::TexturePropertyEditor( QWidget *parent ) : +QWidget( parent ) +{ + setupUi(); + setupConnections(); +} + +TexturePropertyEditor::~TexturePropertyEditor() +{ +} + +void TexturePropertyEditor::setValue( const QString &value ) +{ + if( lineEdit->text() == value ) + return; + + disableConnections(); + lineEdit->setText( value ); + setupConnections(); +} + +void TexturePropertyEditor::showEvent( QShowEvent *e ) +{ + QWidget::showEvent( e ); +} + +void TexturePropertyEditor::onToolButtonClicked() +{ + TextureChooser d; + d.load(); + + int result = d.exec(); + if( QDialog::Accepted != result ) + return; + + lineEdit->setText( d.getSelection() ); +} + +void TexturePropertyEditor::onTextChanged( const QString &text ) +{ + Q_EMIT valueChanged( text ); +} + +void TexturePropertyEditor::setupConnections() +{ + connect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + connect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void TexturePropertyEditor::disableConnections() +{ + disconnect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + disconnect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void TexturePropertyEditor::setupUi() +{ + lineEdit = new QLineEdit(); + toolButton = new QToolButton(); + toolButton->setText( "..." ); + + QHBoxLayout *lt = new QHBoxLayout( this ); + lt->setContentsMargins( 0, 0, 0, 0 ); + lt->setSpacing( 0 ); + lt->addWidget( lineEdit ); + lt->addWidget( toolButton ); + + setFocusProxy( lineEdit ); + setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); + +} + + diff --git a/code/studio/src/plugins/gui_editor/texture_property_manager.h b/code/studio/src/plugins/gui_editor/texture_property_manager.h new file mode 100644 index 000000000..9b686ea04 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_property_manager.h @@ -0,0 +1,125 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TEXTURE_PROPERTY_MANAGER +#define TEXTURE_PROPERTY_MANAGER + +#define QT_QTPROPERTYBROWSER_IMPORT + +#include "3rdparty/qtpropertybrowser/qtpropertybrowser.h" +#include + +/////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + +struct TexturePropertyManagerPrivate; + +class TexturePropertyManager : public QtAbstractPropertyManager +{ + Q_OBJECT + +public: + TexturePropertyManager( QObject *parent = NULL ); + ~TexturePropertyManager(); + + QString value( const QtProperty *p ) const; + +public Q_SLOTS: + void setValue( QtProperty *p, const QString &value ); + +Q_SIGNALS: + void valueChanged( QtProperty *p, const QString &value ); + +protected: + bool hasValue( const QtProperty *p ) const; + QString valueText( const QtProperty *p ) const; + void initializeProperty( QtProperty *p ); + void uninitializeProperty( QtProperty *p ); + +private: + TexturePropertyManagerPrivate *d_ptr; + + Q_DISABLE_COPY( TexturePropertyManager ); +}; + + +////////////////////////////////////////////////////////////////// Factory ///////////////////////////////////////////////////////////////////////// + +struct TextureEditorFactoryPrivate; + +class TextureEditorFactory : public QtAbstractEditorFactory< TexturePropertyManager > +{ + Q_OBJECT + +public: + TextureEditorFactory( QObject *parent = NULL ); + ~TextureEditorFactory(); + +protected: + void connectPropertyManager( TexturePropertyManager *manager ); + void disconnectPropertyManager( TexturePropertyManager *manager ); + + QWidget* createEditor( TexturePropertyManager *manager, QtProperty *p, QWidget *parent ); + +private Q_SLOTS: + void onPropertyChanged( QtProperty *p, const QString &value ); + void onSetValue( const QString &value ); + void onEditorDestroyed( QObject *editor ); + +private: + TextureEditorFactoryPrivate *d_ptr; + + Q_DISABLE_COPY( TextureEditorFactory ); +}; + + +///////////////////////////////////////////////////////////////// Editor /////////////////////////////////////////////////////////////////////////// + +class QLineEdit; +class QToolButton; + +class TexturePropertyEditor : public QWidget +{ + Q_OBJECT +public: + TexturePropertyEditor( QWidget *parent = NULL ); + ~TexturePropertyEditor(); + +public Q_SLOTS: + void setValue( const QString &value ); + +protected: + void showEvent( QShowEvent *e ); + +private Q_SLOTS: + void onToolButtonClicked(); + void onTextChanged( const QString &text ); + +Q_SIGNALS: + void valueChanged( const QString &value ); + +private: + void setupUi(); + void setupConnections(); + void disableConnections(); + + + QLineEdit *lineEdit; + QToolButton *toolButton; +}; + +#endif + diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index c39ecbabc..21ef7daff 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -35,7 +35,7 @@ texture - string + texture From 012ad9680603863fc50ce4f6090e625a29e90708 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 21:07:12 +0200 Subject: [PATCH 122/282] Texture chooser now supports atlas textures as well. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/gui/view_renderer.h | 6 ++ code/nel/src/gui/view_renderer.cpp | 40 ++++++++ .../plugins/gui_editor/texture_chooser.cpp | 97 ++++++++++++++++--- .../src/plugins/gui_editor/texture_chooser.h | 13 ++- .../src/plugins/gui_editor/texture_chooser.ui | 8 +- 5 files changed, 146 insertions(+), 18 deletions(-) diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h index 83ac4457e..fe5dad405 100644 --- a/code/nel/include/nel/gui/view_renderer.h +++ b/code/nel/include/nel/gui/view_renderer.h @@ -286,6 +286,12 @@ namespace NLGUI */ void flush (); + /// Retrives a texture + bool getTexture( NLMISC::CBitmap &bm, const std::string &name ); + + /// Retrieve the texture names + void getTextureNames( std::vector< std::string > &textures ); + /** * get a texture file pointer from a string name. O(logN) * \param id : the id of the texture diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index b2758c634..6e6675599 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -1064,6 +1064,46 @@ namespace NLGUI } } + bool CViewRenderer::getTexture( NLMISC::CBitmap &bm, const std::string &name ) + { + TTextureMap::const_iterator itr = _TextureMap.find( name ); + if( itr == _TextureMap.end() ) + return false; + + sint32 id = itr->second; + SImage *si = getSImage( id ); + NLMISC::CBitmap *src = si->GlobalTexturePtr->Texture->generateDatas(); + + if( src->getPixelFormat() != NLMISC::CBitmap::RGBA ) + return false; + + uint x0 = (uint)( si->UVMin.U * si->GlobalTexturePtr->Width ); + uint y0 = (uint)( si->UVMin.V * si->GlobalTexturePtr->Height ); + uint x1 = (uint)( si->UVMax.U * si->GlobalTexturePtr->Width ); + uint y1 = (uint)( si->UVMax.V * si->GlobalTexturePtr->Height ); + + if( x1 == x0 ) + return false; + + if( y1 == y0 ) + return false; + + bm.resize( x1 - x0, y1 - y0 ); + bm.blit( *src, x0, y0, ( x1 - x0 ), ( y1 - y0 ), 0, 0 ); + + return true; + } + + void CViewRenderer::getTextureNames( std::vector< std::string > &textures ) + { + TTextureMap::const_iterator itr = _TextureMap.begin(); + while( itr != _TextureMap.end() ) + { + textures.push_back( itr->first ); + ++itr; + } + } + /* * getTextureIdFromName */ diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index d857d9bdc..1c5e692ee 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -6,40 +6,81 @@ #include #include #include +#include + +#include "nel/gui/view_renderer.h" + +struct TextureChooserPrivate +{ + QListWidget *fileTextures; + QListWidget *atlasTextures; + + TextureChooserPrivate() + { + fileTextures = new QListWidget(); + atlasTextures = new QListWidget(); + } +}; TextureChooser::TextureChooser( QDialog *parent ) : QDialog( parent ) { setupUi( this ); + + d_ptr = new TextureChooserPrivate; + this->tabWidget->clear(); + this->tabWidget->addTab( d_ptr->fileTextures, tr( "File textures" ) ); + this->tabWidget->addTab( d_ptr->atlasTextures, tr( "Atlas texture" ) ); + setupConnections(); } TextureChooser::~TextureChooser() { + delete d_ptr; + d_ptr = NULL; } void TextureChooser::load() { - listWidget->clear(); + // Load the file textures + d_ptr->fileTextures->clear(); std::vector< std::string > textures; //NLMISC::CPath::getFileList( "tga", textures ); - NLMISC::CPath::getFileListByPath( "tga", "interfaces", textures ); + NLMISC::CPath::getFileListByPath( "dds", "interfaces", textures ); + NLMISC::CPath::getFileListByPath( "dds", "gamedev", textures ); + + std::sort( textures.begin(), textures.end() ); std::vector< std::string >::const_iterator itr = textures.begin(); while( itr != textures.end() ) { - listWidget->addItem( itr->c_str() ); + d_ptr->fileTextures->addItem( itr->c_str() ); ++itr; } - listWidget->setCurrentRow( 0 ); + // Now load the atlas textures + d_ptr->atlasTextures->clear(); + textures.clear(); + + NLGUI::CViewRenderer::getInstance()->getTextureNames( textures ); + itr = textures.begin(); + while( itr != textures.end() ) + { + d_ptr->atlasTextures->addItem( itr->c_str() ); + ++itr; + } + + // set the file textures row after the atlas, because they are shown first + d_ptr->atlasTextures->setCurrentRow( 0 ); + d_ptr->fileTextures->setCurrentRow( 0 ); } void TextureChooser::accept() { - QListWidgetItem *item = listWidget->currentItem(); + QListWidgetItem *item = d_ptr->fileTextures->currentItem(); if( item == NULL ) return; @@ -54,12 +95,12 @@ void TextureChooser::reject() QDialog::reject(); } -void TextureChooser::onCurrentRowChanged( int row ) +void TextureChooser::onFileTxtRowChanged( int row ) { if( row < 0 ) return; - QListWidgetItem *item = listWidget->item( row ); + QListWidgetItem *item = d_ptr->fileTextures->item( row ); QString fn = item->text(); std::string rfn = fn.toUtf8().constData(); @@ -81,11 +122,42 @@ void TextureChooser::onCurrentRowChanged( int row ) return; } - uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image + setPreviewImage( bm ); +} +void TextureChooser::onAtlasTxtRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = d_ptr->atlasTextures->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + + NLMISC::CBitmap bm; + + bool b = NLGUI::CViewRenderer::getInstance()->getTexture( bm, rfn ); + if( !b ) + return; + + setPreviewImage( bm ); +} + + +void TextureChooser::setupConnections() +{ + connect( d_ptr->fileTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onFileTxtRowChanged( int ) ) ); + connect( d_ptr->atlasTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onAtlasTxtRowChanged( int ) ) ); +} + +void TextureChooser::setPreviewImage( NLMISC::CBitmap &bm ) +{ + // should be depth, but CBitmap always uses 32 bit to store the image + uint32 size = bm.getSize() * ( 32 / 8 ); uint8 *data = new uint8[ size ]; bm.getData( data ); - + /// Convert from ABGR to ARGB { int i = 0; @@ -107,13 +179,6 @@ void TextureChooser::onCurrentRowChanged( int row ) delete data; data = NULL; - -} - - -void TextureChooser::setupConnections() -{ - connect( listWidget, SIGNAL( currentRowChanged( int ) ), this, SLOT( onCurrentRowChanged( int ) ) ); } diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index bab1dd1dc..9a615c266 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -3,6 +3,13 @@ #include "ui_texture_chooser.h" +namespace NLMISC +{ + class CBitmap; +} + +struct TextureChooserPrivate; + class TextureChooser : public QDialog, public Ui::TextureChooser { Q_OBJECT @@ -19,12 +26,16 @@ public Q_SLOTS: void reject(); private Q_SLOTS: - void onCurrentRowChanged( int row ); + void onFileTxtRowChanged( int row ); + void onAtlasTxtRowChanged( int row ); private: void setupConnections(); + void setPreviewImage( NLMISC::CBitmap &bm ); QString selection; + + TextureChooserPrivate *d_ptr; }; #endif diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.ui b/code/studio/src/plugins/gui_editor/texture_chooser.ui index 0f635e96f..a0837ee83 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.ui +++ b/code/studio/src/plugins/gui_editor/texture_chooser.ui @@ -18,7 +18,13 @@ - + + + + tab + + + From d850a07e9e870c1e2ad35575b31e33613487ebad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 21:13:57 +0200 Subject: [PATCH 123/282] Copyright banner + line endings... I always mess this up somehow.. --HG-- branch : gsoc2014-dfighter --- .../plugins/gui_editor/texture_chooser.cpp | 386 +++++++++--------- .../src/plugins/gui_editor/texture_chooser.h | 100 +++-- 2 files changed, 259 insertions(+), 227 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 1c5e692ee..57a0e8d51 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -1,185 +1,201 @@ -#include "texture_chooser.h" -#include "nel/misc/path.h" -#include "nel/misc/bitmap.h" -#include "nel/misc/file.h" -#include -#include -#include -#include -#include - -#include "nel/gui/view_renderer.h" - -struct TextureChooserPrivate -{ - QListWidget *fileTextures; - QListWidget *atlasTextures; - - TextureChooserPrivate() - { - fileTextures = new QListWidget(); - atlasTextures = new QListWidget(); - } -}; - -TextureChooser::TextureChooser( QDialog *parent ) : -QDialog( parent ) -{ - setupUi( this ); - - d_ptr = new TextureChooserPrivate; - this->tabWidget->clear(); - this->tabWidget->addTab( d_ptr->fileTextures, tr( "File textures" ) ); - this->tabWidget->addTab( d_ptr->atlasTextures, tr( "Atlas texture" ) ); - - setupConnections(); -} - -TextureChooser::~TextureChooser() -{ - delete d_ptr; - d_ptr = NULL; -} - - -void TextureChooser::load() -{ - // Load the file textures - d_ptr->fileTextures->clear(); - - std::vector< std::string > textures; - //NLMISC::CPath::getFileList( "tga", textures ); - NLMISC::CPath::getFileListByPath( "dds", "interfaces", textures ); - NLMISC::CPath::getFileListByPath( "dds", "gamedev", textures ); - - std::sort( textures.begin(), textures.end() ); - - std::vector< std::string >::const_iterator itr = textures.begin(); - while( itr != textures.end() ) - { - d_ptr->fileTextures->addItem( itr->c_str() ); - ++itr; - } - - // Now load the atlas textures - d_ptr->atlasTextures->clear(); - textures.clear(); - - NLGUI::CViewRenderer::getInstance()->getTextureNames( textures ); - itr = textures.begin(); - while( itr != textures.end() ) - { - d_ptr->atlasTextures->addItem( itr->c_str() ); - ++itr; - } - - // set the file textures row after the atlas, because they are shown first - d_ptr->atlasTextures->setCurrentRow( 0 ); - d_ptr->fileTextures->setCurrentRow( 0 ); -} - -void TextureChooser::accept() -{ - QListWidgetItem *item = d_ptr->fileTextures->currentItem(); - if( item == NULL ) - return; - - selection = item->text(); - QDialog::accept(); -} - -void TextureChooser::reject() -{ - selection = ""; - - QDialog::reject(); -} - -void TextureChooser::onFileTxtRowChanged( int row ) -{ - if( row < 0 ) - return; - - QListWidgetItem *item = d_ptr->fileTextures->item( row ); - QString fn = item->text(); - - std::string rfn = fn.toUtf8().constData(); - rfn = NLMISC::CPath::lookup( rfn ); - - NLMISC::CIFile f; - bool b = f.open( rfn ); - if( !b ) - { - return; - } - - NLMISC::CBitmap bm; - uint8 depth = bm.load( f ); - f.close(); - b = bm.convertToType( NLMISC::CBitmap::RGBA ); - if( !b ) - { - return; - } - - setPreviewImage( bm ); -} - -void TextureChooser::onAtlasTxtRowChanged( int row ) -{ - if( row < 0 ) - return; - - QListWidgetItem *item = d_ptr->atlasTextures->item( row ); - QString fn = item->text(); - - std::string rfn = fn.toUtf8().constData(); - - NLMISC::CBitmap bm; - - bool b = NLGUI::CViewRenderer::getInstance()->getTexture( bm, rfn ); - if( !b ) - return; - - setPreviewImage( bm ); -} - - -void TextureChooser::setupConnections() -{ - connect( d_ptr->fileTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onFileTxtRowChanged( int ) ) ); - connect( d_ptr->atlasTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onAtlasTxtRowChanged( int ) ) ); -} - -void TextureChooser::setPreviewImage( NLMISC::CBitmap &bm ) -{ - // should be depth, but CBitmap always uses 32 bit to store the image - uint32 size = bm.getSize() * ( 32 / 8 ); - uint8 *data = new uint8[ size ]; - bm.getData( data ); - - /// Convert from ABGR to ARGB - { - int i = 0; - while( i < size ) - { - uint8 t = 0; - - /// ABGR - t = data[ i ]; - data[ i ] = data[ i + 2 ]; - data[ i + 2 ] = t; - - i += 4; - } - } - - QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); - label->setPixmap( QPixmap::fromImage( img ) ); - - delete data; - data = NULL; -} - - - +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "texture_chooser.h" +#include "nel/misc/path.h" +#include "nel/misc/bitmap.h" +#include "nel/misc/file.h" +#include +#include +#include +#include +#include + +#include "nel/gui/view_renderer.h" + +struct TextureChooserPrivate +{ + QListWidget *fileTextures; + QListWidget *atlasTextures; + + TextureChooserPrivate() + { + fileTextures = new QListWidget(); + atlasTextures = new QListWidget(); + } +}; + +TextureChooser::TextureChooser( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + + d_ptr = new TextureChooserPrivate; + this->tabWidget->clear(); + this->tabWidget->addTab( d_ptr->fileTextures, tr( "File textures" ) ); + this->tabWidget->addTab( d_ptr->atlasTextures, tr( "Atlas texture" ) ); + + setupConnections(); +} + +TextureChooser::~TextureChooser() +{ + delete d_ptr; + d_ptr = NULL; +} + + +void TextureChooser::load() +{ + // Load the file textures + d_ptr->fileTextures->clear(); + + std::vector< std::string > textures; + //NLMISC::CPath::getFileList( "tga", textures ); + NLMISC::CPath::getFileListByPath( "dds", "interfaces", textures ); + NLMISC::CPath::getFileListByPath( "dds", "gamedev", textures ); + + std::sort( textures.begin(), textures.end() ); + + std::vector< std::string >::const_iterator itr = textures.begin(); + while( itr != textures.end() ) + { + d_ptr->fileTextures->addItem( itr->c_str() ); + ++itr; + } + + // Now load the atlas textures + d_ptr->atlasTextures->clear(); + textures.clear(); + + NLGUI::CViewRenderer::getInstance()->getTextureNames( textures ); + itr = textures.begin(); + while( itr != textures.end() ) + { + d_ptr->atlasTextures->addItem( itr->c_str() ); + ++itr; + } + + // set the file textures row after the atlas, because they are shown first + d_ptr->atlasTextures->setCurrentRow( 0 ); + d_ptr->fileTextures->setCurrentRow( 0 ); +} + +void TextureChooser::accept() +{ + QListWidgetItem *item = d_ptr->fileTextures->currentItem(); + if( item == NULL ) + return; + + selection = item->text(); + QDialog::accept(); +} + +void TextureChooser::reject() +{ + selection = ""; + + QDialog::reject(); +} + +void TextureChooser::onFileTxtRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = d_ptr->fileTextures->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + rfn = NLMISC::CPath::lookup( rfn ); + + NLMISC::CIFile f; + bool b = f.open( rfn ); + if( !b ) + { + return; + } + + NLMISC::CBitmap bm; + uint8 depth = bm.load( f ); + f.close(); + b = bm.convertToType( NLMISC::CBitmap::RGBA ); + if( !b ) + { + return; + } + + setPreviewImage( bm ); +} + +void TextureChooser::onAtlasTxtRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = d_ptr->atlasTextures->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + + NLMISC::CBitmap bm; + + bool b = NLGUI::CViewRenderer::getInstance()->getTexture( bm, rfn ); + if( !b ) + return; + + setPreviewImage( bm ); +} + + +void TextureChooser::setupConnections() +{ + connect( d_ptr->fileTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onFileTxtRowChanged( int ) ) ); + connect( d_ptr->atlasTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onAtlasTxtRowChanged( int ) ) ); +} + +void TextureChooser::setPreviewImage( NLMISC::CBitmap &bm ) +{ + // should be depth, but CBitmap always uses 32 bit to store the image + uint32 size = bm.getSize() * ( 32 / 8 ); + uint8 *data = new uint8[ size ]; + bm.getData( data ); + + /// Convert from ABGR to ARGB + { + int i = 0; + while( i < size ) + { + uint8 t = 0; + + /// ABGR + t = data[ i ]; + data[ i ] = data[ i + 2 ]; + data[ i + 2 ] = t; + + i += 4; + } + } + + QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); + label->setPixmap( QPixmap::fromImage( img ) ); + + delete data; + data = NULL; +} + + + diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index 9a615c266..160b31481 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -1,42 +1,58 @@ -#ifndef TEXTURE_CHOOSER_H -#define TEXTURE_CHOOSER_H - -#include "ui_texture_chooser.h" - -namespace NLMISC -{ - class CBitmap; -} - -struct TextureChooserPrivate; - -class TextureChooser : public QDialog, public Ui::TextureChooser -{ - Q_OBJECT - -public: - TextureChooser( QDialog *parent = NULL ); - ~TextureChooser(); - - void load(); - QString getSelection(){ return selection; } - -public Q_SLOTS: - void accept(); - void reject(); - -private Q_SLOTS: - void onFileTxtRowChanged( int row ); - void onAtlasTxtRowChanged( int row ); - -private: - void setupConnections(); - void setPreviewImage( NLMISC::CBitmap &bm ); - - QString selection; - - TextureChooserPrivate *d_ptr; -}; - -#endif - +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TEXTURE_CHOOSER_H +#define TEXTURE_CHOOSER_H + +#include "ui_texture_chooser.h" + +namespace NLMISC +{ + class CBitmap; +} + +struct TextureChooserPrivate; + +class TextureChooser : public QDialog, public Ui::TextureChooser +{ + Q_OBJECT + +public: + TextureChooser( QDialog *parent = NULL ); + ~TextureChooser(); + + void load(); + QString getSelection(){ return selection; } + +public Q_SLOTS: + void accept(); + void reject(); + +private Q_SLOTS: + void onFileTxtRowChanged( int row ); + void onAtlasTxtRowChanged( int row ); + +private: + void setupConnections(); + void setPreviewImage( NLMISC::CBitmap &bm ); + + QString selection; + + TextureChooserPrivate *d_ptr; +}; + +#endif + From 094210a079445fc59cc71fd205e518bdc9417583 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 23:20:50 +0200 Subject: [PATCH 124/282] Workaround related to the unknown statusbar crash. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/landscape_editor/landscape_editor_window.cpp | 4 ++++ code/studio/src/plugins/world_editor/world_editor_window.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp index bbc996b94..aeca41906 100644 --- a/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp +++ b/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp @@ -104,6 +104,10 @@ LandscapeEditorWindow::~LandscapeEditorWindow() { writeSettings(); delete m_zoneBuilder; + + Core::ICore::instance()->mainWindow()->statusBar()->removeWidget( m_statusInfo ); + delete m_statusInfo; + m_statusInfo = NULL; } QUndoStack *LandscapeEditorWindow::undoStack() const diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index b23e62063..afb667358 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -121,6 +121,10 @@ WorldEditorWindow::~WorldEditorWindow() writeSettings(); delete m_zoneBuilderBase; + + Core::ICore::instance()->mainWindow()->statusBar()->removeWidget( m_statusInfo ); + delete m_statusInfo; + m_statusInfo = NULL; } QUndoStack *WorldEditorWindow::undoStack() const From a222e44eaab12ab0a259bdd89b52c42abfe6a912 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:35:05 +0200 Subject: [PATCH 125/282] Implemented const_string_array editor. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/world_editor/CMakeLists.txt | 3 + .../const_string_array_editor.cpp | 106 +++++ .../world_editor/const_string_array_editor.h | 50 +++ .../world_editor/const_string_array_editor.ui | 130 +++++++ .../const_string_array_property.cpp | 363 ++++++++++++++++++ .../const_string_array_property.h | 131 +++++++ .../world_editor/property_editor_widget.cpp | 30 +- .../world_editor/property_editor_widget.h | 6 + 8 files changed, 800 insertions(+), 19 deletions(-) create mode 100644 code/studio/src/plugins/world_editor/const_string_array_editor.cpp create mode 100644 code/studio/src/plugins/world_editor/const_string_array_editor.h create mode 100644 code/studio/src/plugins/world_editor/const_string_array_editor.ui create mode 100644 code/studio/src/plugins/world_editor/const_string_array_property.cpp create mode 100644 code/studio/src/plugins/world_editor/const_string_array_property.h diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index 7b76ed810..ac5231aea 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -20,12 +20,15 @@ SET(OVQT_PLUGIN_WORLD_EDITOR_HDR world_editor_plugin.h project_settings_dialog.h property_editor_widget.h world_editor_settings_page.h + const_string_array_property.h + const_string_array_editor.h ) SET(OVQT_PLUGIN_WORLD_EDITOR_UIS world_editor_window.ui project_settings_dialog.ui property_editor_widget.ui world_editor_settings_page.ui + const_string_array_editor.ui ) SET(OVQT_PLUGIN_WORLD_EDITOR_RCS world_editor.qrc) diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.cpp b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp new file mode 100644 index 000000000..05e5e4cf5 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp @@ -0,0 +1,106 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "const_string_array_editor.h" + +ConstStrArrEditDialog::ConstStrArrEditDialog( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); +} + +ConstStrArrEditDialog::~ConstStrArrEditDialog() +{ +} + +void ConstStrArrEditDialog::setStrings( const QStringList &strings ) +{ + cb->clear(); + + QStringListIterator itr( strings ); + while( itr.hasNext() ) + { + cb->addItem( itr.next() ); + } + + cb->setCurrentIndex( 0 ); +} + +void ConstStrArrEditDialog::setValue( const QString &value ) +{ + listWidget->clear(); + + if( value.isEmpty() ) + return; + + QStringList l = value.split( ';' ); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + listWidget->addItem( itr.next() ); + } +} + +QString ConstStrArrEditDialog::getValue() const +{ + QString value; + + for( int i = 0; i < listWidget->count(); i++ ) + { + QListWidgetItem *item = listWidget->item( i ); + value += item->text(); + + if( i < ( listWidget->count() - 1 ) ) + value += ';'; + } + + return value; +} + +void ConstStrArrEditDialog::accept() +{ + QDialog::accept(); +} + +void ConstStrArrEditDialog::reject() +{ + QDialog::reject(); +} + +void ConstStrArrEditDialog::onAddClicked() +{ + listWidget->addItem( cb->currentText() ); +} + +void ConstStrArrEditDialog::onRemoveClicked() +{ + QListWidgetItem *item = listWidget->currentItem(); + if( item == NULL ) + return; + + delete item; +} + +void ConstStrArrEditDialog::setupConnections() +{ + connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( onAddClicked() ) ); + connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveClicked() ) ); +} + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.h b/code/studio/src/plugins/world_editor/const_string_array_editor.h new file mode 100644 index 000000000..a2c458e7c --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.h @@ -0,0 +1,50 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CONST_STR_ARR_EDIT_DLG +#define CONST_STR_ARR_EDIT_DLG + +#include "ui_const_string_array_editor.h" +#include + +class ConstStrArrEditDialog : public QDialog, public Ui::ConstStrArrEditorDialog +{ + Q_OBJECT +public: + ConstStrArrEditDialog( QDialog *parent = NULL ); + ~ConstStrArrEditDialog(); + + void setStrings( const QStringList &strings ); + void setValue( const QString &value ); + QString getValue() const; + +public Q_SLOTS: + void accept(); + void reject(); + +private Q_SLOTS: + void onAddClicked(); + void onRemoveClicked(); + +private: + void setupConnections(); +}; + + +#endif + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.ui b/code/studio/src/plugins/world_editor/const_string_array_editor.ui new file mode 100644 index 000000000..6aec02352 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.ui @@ -0,0 +1,130 @@ + + + ConstStrArrEditorDialog + + + + 0 + 0 + 392 + 293 + + + + Dialog + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Add + + + + + + + + 0 + 0 + + + + Remove + + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + okButton + clicked() + ConstStrArrEditorDialog + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + ConstStrArrEditorDialog + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_property.cpp b/code/studio/src/plugins/world_editor/const_string_array_property.cpp new file mode 100644 index 000000000..5ef7566d8 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_property.cpp @@ -0,0 +1,363 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "const_string_array_property.h" +#include "const_string_array_editor.h" +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + + +struct ConstStrArrPropMgrPriv +{ + QMap< const QtProperty*, QString > values; +}; + +ConstStrArrPropMgr::ConstStrArrPropMgr( QObject *parent ) : +QtAbstractPropertyManager( parent ) +{ + d_ptr = new ConstStrArrPropMgrPriv(); +} + +ConstStrArrPropMgr::~ConstStrArrPropMgr() +{ + delete d_ptr; + d_ptr = NULL; +} + +QString ConstStrArrPropMgr::value( const QtProperty *p ) const +{ + return valueText( p ); +} + +void ConstStrArrPropMgr::setValue( QtProperty *p, const QString &value ) +{ + if( !d_ptr->values.contains( p ) ) + return; + + if( d_ptr->values[ p ] == value ) + return; + + d_ptr->values[ p ] = value; + + Q_EMIT propertyChanged( p ); + Q_EMIT valueChanged( p, value ); +} + +void ConstStrArrPropMgr::setStrings( QtProperty *p, const QStringList &strings ) +{ + Q_EMIT stringsChanged( p, strings ); +} + +bool ConstStrArrPropMgr::hasValue( const QtProperty *p ) const +{ + return d_ptr->values.contains( p ); +} + +QString ConstStrArrPropMgr::valueText( const QtProperty *p ) const +{ + if( !d_ptr->values.contains( p ) ) + return ""; + + return d_ptr->values[ p ]; +} + +void ConstStrArrPropMgr::initializeProperty( QtProperty *p ) +{ + if( d_ptr->values.contains( p ) ) + return; + + d_ptr->values[ p ] = ""; +} + +void ConstStrArrPropMgr::uninitializeProperty( QtProperty *p ) +{ + d_ptr->values.remove( p ); +} + + + +//////////////////////////////////////////////////////////////////// Factory /////////////////////////////////////////////////////////////////////// + + + +struct ConstStrArrEditorFactoryPriv +{ + QMap< QtProperty*, QList< ConstStrArrEditor* > > createdEditors; + QMap< ConstStrArrEditor*, QtProperty* > editorToProperty; + QMap< QtProperty*, QStringList > strings; + + ~ConstStrArrEditorFactoryPriv() + { + createdEditors.clear(); + + QMap< ConstStrArrEditor*, QtProperty* >::iterator itr = editorToProperty.begin(); + while( itr != editorToProperty.end() ) + { + delete itr.key(); + ++itr; + } + editorToProperty.clear(); + } + + void addEditor( QtProperty *p, ConstStrArrEditor *editor ) + { + QMap< QtProperty*, QList< ConstStrArrEditor* > >::iterator itr = createdEditors.find( p ); + + if( itr != createdEditors.end() ) + { + itr->push_back( editor ); + } + else + { + QList< ConstStrArrEditor* > l; + l.push_back( editor ); + createdEditors.insert( p, l ); + } + + editorToProperty.insert( editor, p ); + } + + void removeEditor( QObject *o ) + { + // Remove from editorToProperty first + QMap< ConstStrArrEditor*, QtProperty* >::iterator itr1 = editorToProperty.begin(); + while( itr1 != editorToProperty.end() ) + { + if( itr1.key() == o ) + break; + + ++itr1; + } + if( itr1 != editorToProperty.end() ) + editorToProperty.erase( itr1 ); + + // Then from createdEditors + QMap< QtProperty*, QList< ConstStrArrEditor* > >::iterator itr2 = createdEditors.begin(); + while( itr2 != createdEditors.end() ) + { + QList< ConstStrArrEditor* > &l = *itr2; + QList< ConstStrArrEditor* >::iterator itr = l.begin(); + while( itr != l.end() ) + { + if( *itr == o ) + { + QList< ConstStrArrEditor* >::iterator d = itr; + ++itr; + l.erase( d ); + continue; + } + + ++itr; + } + + ++itr2; + } + } + +}; + +ConstStrArrEditorFactory::ConstStrArrEditorFactory( QObject *parent ) : +QtAbstractEditorFactory( parent ) +{ + d_ptr = new ConstStrArrEditorFactoryPriv(); +} + +ConstStrArrEditorFactory::~ConstStrArrEditorFactory() +{ + delete d_ptr; + d_ptr = NULL; +} + +void ConstStrArrEditorFactory::connectPropertyManager( ConstStrArrPropMgr *manager ) +{ + connect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); + connect( manager, SIGNAL( stringsChanged( QtProperty*, const QStringList& ) ), this, SLOT( onStringsChanged( QtProperty*, const QStringList & ) ) ); +} + +void ConstStrArrEditorFactory::disconnectPropertyManager( ConstStrArrPropMgr *manager ) +{ + disconnect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); + disconnect( manager, SIGNAL( stringsChanged( const QStringList& ) ), this, SLOT( onStringsChanged( const QStringList & ) ) ); +} + +QWidget* ConstStrArrEditorFactory::createEditor( ConstStrArrPropMgr *manager, QtProperty *p, QWidget *parent ) +{ + ConstStrArrEditor *editor = new ConstStrArrEditor( parent ); + editor->setValue( manager->value( p ) ); + + QMap< QtProperty*, QStringList >::iterator itr = d_ptr->strings.find( p ); + if( itr != d_ptr->strings.end() ) + { + editor->setStrings( *itr ); + } + + connect( editor, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onSetValue( const QString& ) ) ); + connect( editor, SIGNAL( destroyed( QObject* ) ), this, SLOT( onEditorDestroyed( QObject* ) ) ); + + d_ptr->addEditor( p, editor ); + + return editor; +} + +void ConstStrArrEditorFactory::onPropertyChanged( QtProperty *p, const QString &value ) +{ + QMap< QtProperty*, QList< ConstStrArrEditor* > >::iterator itr = d_ptr->createdEditors.find( p ); + if( itr == d_ptr->createdEditors.end() ) + return; + + QList< ConstStrArrEditor* > &l = *itr; + QList< ConstStrArrEditor* >::iterator i = l.begin(); + while( i != l.end() ) + { + ConstStrArrEditor *editor = *i; + + editor->blockSignals( true ); + editor->setValue( value ); + editor->blockSignals( false ); + + ++i; + } +} + +void ConstStrArrEditorFactory::onStringsChanged( QtProperty *p, const QStringList &strings ) +{ + if( p == NULL ) + return; + + d_ptr->strings[ p ] = strings; +} + +void ConstStrArrEditorFactory::onSetValue( const QString &value ) +{ + QObject *s = sender(); + ConstStrArrEditor *editor = qobject_cast< ConstStrArrEditor* >( s ); + if( editor == NULL ) + return; + + QMap< ConstStrArrEditor*, QtProperty* >::iterator itr = d_ptr->editorToProperty.find( editor ); + if( itr == d_ptr->editorToProperty.end() ) + return; + + QtProperty *p = *itr; + + ConstStrArrPropMgr *manager = qobject_cast< ConstStrArrPropMgr* >( p->propertyManager() ); + if( manager == NULL ) + return; + + blockSignals( true ); + manager->setValue( p, value ); + blockSignals( false ); +} + +void ConstStrArrEditorFactory::onEditorDestroyed( QObject *editor ) +{ + d_ptr->removeEditor( editor ); +} + + + +//////////////////////////////////////////////////////////////////////// Editor ////////////////////////////////////////////////////////////////// + +ConstStrArrEditor::ConstStrArrEditor( QWidget *parent ) : +QWidget( parent ) +{ + setupUi(); + setupConnections(); +} + +ConstStrArrEditor::~ConstStrArrEditor() +{ +} + +void ConstStrArrEditor::setStrings( const QStringList &strings ) +{ + this->strings.clear(); + + QStringListIterator itr( strings ); + while( itr.hasNext() ) + { + this->strings.push_back( itr.next() ); + } +} + +void ConstStrArrEditor::setValue( const QString &value ) +{ + if( lineEdit->text() == value ) + return; + + disableConnections(); + lineEdit->setText( value ); + setupConnections(); +} + +void ConstStrArrEditor::showEvent( QShowEvent *e ) +{ + QWidget::showEvent( e ); +} + +void ConstStrArrEditor::onToolButtonClicked() +{ + ConstStrArrEditDialog d; + d.setStrings( strings ); + d.setValue( lineEdit->text() ); + int result = d.exec(); + if( QDialog::Accepted != result ) + return; + lineEdit->setText( d.getValue() ); +} + +void ConstStrArrEditor::onTextChanged( const QString &text ) +{ + Q_EMIT valueChanged( text ); +} + +void ConstStrArrEditor::setupConnections() +{ + connect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + connect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ConstStrArrEditor::disableConnections() +{ + disconnect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + disconnect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ConstStrArrEditor::setupUi() +{ + lineEdit = new QLineEdit(); + toolButton = new QToolButton(); + toolButton->setText( "..." ); + + QHBoxLayout *lt = new QHBoxLayout( this ); + lt->setContentsMargins( 0, 0, 0, 0 ); + lt->setSpacing( 0 ); + lt->addWidget( lineEdit ); + lt->addWidget( toolButton ); + + setFocusProxy( lineEdit ); + setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); + +} + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_property.h b/code/studio/src/plugins/world_editor/const_string_array_property.h new file mode 100644 index 000000000..a079f4802 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_property.h @@ -0,0 +1,131 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CONST_STR_ARR_PROP_H +#define CONST_STR_ARR_PROP_H + +#define QT_QTPROPERTYBROWSER_IMPORT + +#include "3rdparty/qtpropertybrowser/qtpropertybrowser.h" +#include +#include + +/////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + +struct ConstStrArrPropMgrPriv; + +class ConstStrArrPropMgr : public QtAbstractPropertyManager +{ + Q_OBJECT + +public: + ConstStrArrPropMgr( QObject *parent = NULL ); + ~ConstStrArrPropMgr(); + + QString value( const QtProperty *p ) const; + +public Q_SLOTS: + void setValue( QtProperty *p, const QString &value ); + void setStrings( QtProperty *p, const QStringList &strings ); + +Q_SIGNALS: + void valueChanged( QtProperty *p, const QString &value ); + void stringsChanged( QtProperty *p, const QStringList &strings ); + +protected: + bool hasValue( const QtProperty *p ) const; + QString valueText( const QtProperty *p ) const; + void initializeProperty( QtProperty *p ); + void uninitializeProperty( QtProperty *p ); + +private: + ConstStrArrPropMgrPriv *d_ptr; + + Q_DISABLE_COPY( ConstStrArrPropMgr ); +}; + + +////////////////////////////////////////////////////////////////// Factory ///////////////////////////////////////////////////////////////////////// + +struct ConstStrArrEditorFactoryPriv; + +class ConstStrArrEditorFactory : public QtAbstractEditorFactory< ConstStrArrPropMgr > +{ + Q_OBJECT + +public: + ConstStrArrEditorFactory( QObject *parent = NULL ); + ~ConstStrArrEditorFactory(); + +protected: + void connectPropertyManager( ConstStrArrPropMgr *manager ); + void disconnectPropertyManager( ConstStrArrPropMgr *manager ); + + QWidget* createEditor( ConstStrArrPropMgr *manager, QtProperty *p, QWidget *parent ); + +private Q_SLOTS: + void onPropertyChanged( QtProperty *p, const QString &value ); + void onStringsChanged( QtProperty *p, const QStringList &strings ); + void onSetValue( const QString &value ); + void onEditorDestroyed( QObject *editor ); + +private: + ConstStrArrEditorFactoryPriv *d_ptr; + + Q_DISABLE_COPY( ConstStrArrEditorFactory ); +}; + + +///////////////////////////////////////////////////////////////// Editor /////////////////////////////////////////////////////////////////////////// + +class QLineEdit; +class QToolButton; + +class ConstStrArrEditor : public QWidget +{ + Q_OBJECT +public: + ConstStrArrEditor( QWidget *parent = NULL ); + ~ConstStrArrEditor(); + void setStrings( const QStringList &strings ); + +public Q_SLOTS: + void setValue( const QString &value ); + +protected: + void showEvent( QShowEvent *e ); + +private Q_SLOTS: + void onToolButtonClicked(); + void onTextChanged( const QString &text ); + +Q_SIGNALS: + void valueChanged( const QString &value ); + +private: + void setupUi(); + void setupConnections(); + void disableConnections(); + + + QLineEdit *lineEdit; + QToolButton *toolButton; + QStringList strings; +}; + +#endif + diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 6d3fdaec1..4f28d383d 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -29,6 +29,8 @@ // Qt includes #include +#include "const_string_array_property.h" + namespace WorldEditor { @@ -42,6 +44,9 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) m_enumManager = new QtEnumPropertyManager(this); m_stringArrayManager = new QtTextPropertyManager(this); + m_constStrArrPropMgr = new ConstStrArrPropMgr(this); + m_constStrArrEditorFactory = new ConstStrArrEditorFactory(this); + QtLineEditFactory *lineEditFactory = new QtLineEditFactory(this); QtCheckBoxFactory *boolFactory = new QtCheckBoxFactory(this); QtEnumEditorFactory *enumFactory = new QtEnumEditorFactory(this); @@ -51,6 +56,7 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) m_ui.treePropertyBrowser->setFactoryForManager(m_boolManager, boolFactory); m_ui.treePropertyBrowser->setFactoryForManager(m_enumManager, enumFactory); m_ui.treePropertyBrowser->setFactoryForManager(m_stringArrayManager, textFactory); + m_ui.treePropertyBrowser->setFactoryForManager(m_constStrArrPropMgr, m_constStrArrEditorFactory); m_groupManager = new QtGroupPropertyManager(this); @@ -58,6 +64,7 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_stringArrayManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + connect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_boolManager, SIGNAL(resetProperty(QtProperty *)), this, SLOT(resetProperty(QtProperty *))); connect(m_stringManager, SIGNAL(resetProperty(QtProperty *)), this, SLOT(resetProperty(QtProperty *))); @@ -326,32 +333,18 @@ QtProperty *PropertyEditorWidget::addConstStringArrayProperty(const NLLIGO::IPro primitive->getPropertyByName(name.c_str(), value); // Create qt property -// QtProperty *prop = m_enumManager->addProperty(parameter.Name.c_str()); - QtProperty *prop = m_stringArrayManager->addProperty(parameter.Name.c_str()); + QtProperty *prop = m_constStrArrPropMgr->addProperty(parameter.Name.c_str()); QStringList listEnums = getComboValues(parameter); if (listEnums.isEmpty()) { -// listEnums << QString(value.c_str()) + tr(" (WRN: Check leveldesign!)"); -// m_enumManager->setEnumNames(prop, listEnums); -// m_enumManager->setValue(prop, 0); prop->setEnabled(false); } else { // Fill qt property - m_enumManager->setEnumNames(prop, listEnums); - - // Find index of current value - //for (int i = 0; i < listEnums.size(); i++) - //{ - // if (value == std::string(listEnums[i].toUtf8().constData())) - // { - // m_enumManager->setValue(prop, i); - // break; - // } - //} + m_constStrArrPropMgr->setStrings(prop, listEnums); const NLLIGO::IProperty *ligoProperty; std::vector vectString; @@ -371,17 +364,16 @@ QtProperty *PropertyEditorWidget::addConstStringArrayProperty(const NLLIGO::IPro if (i != (vectString.size() - 1)) temp += '\n'; } - m_stringArrayManager->setValue(prop, temp.c_str()); + m_constStrArrPropMgr->setValue(prop, temp.c_str()); prop->setToolTip(temp.c_str()); } } else { - m_stringArrayManager->setValue(prop, "StringArray :("); + m_constStrArrPropMgr->setValue(prop, "StringArray :("); } } - m_enumManager->setValue(prop, 0); } return prop; diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index 85935cccd..81a8ad008 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -33,6 +33,9 @@ // Qt includes +class ConstStrArrPropMgr; +class ConstStrArrEditorFactory; + namespace WorldEditor { /** @@ -84,6 +87,9 @@ private: QtGroupPropertyManager *m_groupManager; QtTextPropertyManager *m_stringArrayManager; + ConstStrArrPropMgr *m_constStrArrPropMgr; + ConstStrArrEditorFactory *m_constStrArrEditorFactory; + Ui::PropertyEditorWidget m_ui; }; /* PropertyEditorWidget */ From 8ff5317f011dbbc7a65c0ade61b186f8a2500616 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:37:32 +0200 Subject: [PATCH 126/282] Identation --HG-- branch : gsoc2014-dfighter --- .../world_editor/property_editor_widget.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 4f28d383d..e3e9f0884 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -346,33 +346,33 @@ QtProperty *PropertyEditorWidget::addConstStringArrayProperty(const NLLIGO::IPro // Fill qt property m_constStrArrPropMgr->setStrings(prop, listEnums); - const NLLIGO::IProperty *ligoProperty; - std::vector vectString; + const NLLIGO::IProperty *ligoProperty; + std::vector vectString; - if (primitive->getPropertyByName (parameter.Name.c_str(), ligoProperty)) - { - const NLLIGO::CPropertyStringArray *const propStringArray = dynamic_cast (ligoProperty); - if (propStringArray) + if (primitive->getPropertyByName (parameter.Name.c_str(), ligoProperty)) { - const std::vector &vectString = propStringArray->StringArray; - if (!vectString.empty()) + const NLLIGO::CPropertyStringArray *const propStringArray = dynamic_cast (ligoProperty); + if (propStringArray) { - std::string temp; - for (size_t i = 0; i < vectString.size(); i++) + const std::vector &vectString = propStringArray->StringArray; + if (!vectString.empty()) { - temp += vectString[i]; - if (i != (vectString.size() - 1)) - temp += '\n'; + std::string temp; + for (size_t i = 0; i < vectString.size(); i++) + { + temp += vectString[i]; + if (i != (vectString.size() - 1)) + temp += '\n'; + } + m_constStrArrPropMgr->setValue(prop, temp.c_str()); + prop->setToolTip(temp.c_str()); } - m_constStrArrPropMgr->setValue(prop, temp.c_str()); - prop->setToolTip(temp.c_str()); + } + else + { + m_constStrArrPropMgr->setValue(prop, "StringArray :("); } } - else - { - m_constStrArrPropMgr->setValue(prop, "StringArray :("); - } - } } From aa82655ee77d49ecb4978941089cb19a1a215f8d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:41:15 +0200 Subject: [PATCH 127/282] Use \n instead of ; as a separator. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/world_editor/const_string_array_editor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.cpp b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp index 05e5e4cf5..1f9907646 100644 --- a/code/studio/src/plugins/world_editor/const_string_array_editor.cpp +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp @@ -48,7 +48,7 @@ void ConstStrArrEditDialog::setValue( const QString &value ) if( value.isEmpty() ) return; - QStringList l = value.split( ';' ); + QStringList l = value.split( '\n' ); QStringListIterator itr( l ); while( itr.hasNext() ) @@ -67,7 +67,7 @@ QString ConstStrArrEditDialog::getValue() const value += item->text(); if( i < ( listWidget->count() - 1 ) ) - value += ';'; + value += '\n'; } return value; From 820b6bc8cab8c13ff24071088fa327afc470cc6b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:47:24 +0200 Subject: [PATCH 128/282] Changed property to p, property is a reserved word in VS. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/world_editor/property_editor_widget.cpp | 4 ++-- code/studio/src/plugins/world_editor/property_editor_widget.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index e3e9f0884..17be420cb 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -195,9 +195,9 @@ void PropertyEditorWidget::updateSelection(Node *node) blockSignalsOfProperties(false); } -void PropertyEditorWidget::propertyChanged(QtProperty *property) +void PropertyEditorWidget::propertyChanged(QtProperty *p) { - nlinfo(QString("property %1 changed").arg(property->propertyName()).toUtf8().constData()); + nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); } void PropertyEditorWidget::resetProperty(QtProperty *property) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index 81a8ad008..4152eec0a 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -57,7 +57,7 @@ public Q_SLOTS: /// Update of selections void updateSelection(Node *node); - void propertyChanged(QtProperty *property); + void propertyChanged(QtProperty *p); void resetProperty(QtProperty *property); private: From 8f8b4fae65c6fc316a8e90571bce1c471a316b4d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 00:01:17 +0200 Subject: [PATCH 129/282] Store QtProperty, IPrimitive pairs and look the primitive up when the property changes. --HG-- branch : gsoc2014-dfighter --- .../world_editor/property_editor_widget.cpp | 50 +++++++++++++++++++ .../world_editor/property_editor_widget.h | 5 ++ 2 files changed, 55 insertions(+) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 17be420cb..0927ce6f7 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -28,12 +28,48 @@ // Qt includes #include +#include #include "const_string_array_property.h" namespace WorldEditor { +struct PropertyEditorWidgetPrivate +{ + QMap< QtProperty*, NLLIGO::IPrimitive* > propToPrim; + + void clearPrimitives() + { + propToPrim.clear(); + } + + void addPrimitive( QtProperty *p, NLLIGO::IPrimitive *prim ) + { + QMap< QtProperty*, NLLIGO::IPrimitive* >::const_iterator itr + = propToPrim.find( p ); + if( itr != propToPrim.end() ) + return; + + propToPrim[ p ] = prim; + } + + NLLIGO::IPrimitive* getPrimitive( QtProperty *p ) + { + NLLIGO::IPrimitive *prim = NULL; + + QMap< QtProperty*, NLLIGO::IPrimitive* >::const_iterator itr + = propToPrim.find( p ); + + if( itr != propToPrim.end() ) + { + prim = itr.value(); + } + + return prim; + } +}; + PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) : QWidget(parent) { @@ -60,6 +96,8 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) m_groupManager = new QtGroupPropertyManager(this); + d_ptr = new PropertyEditorWidgetPrivate(); + connect(m_stringManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); @@ -74,10 +112,13 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) PropertyEditorWidget::~PropertyEditorWidget() { + delete d_ptr; + d_ptr = NULL; } void PropertyEditorWidget::clearProperties() { + d_ptr->clearPrimitives(); m_ui.treePropertyBrowser->clear(); } @@ -170,6 +211,8 @@ void PropertyEditorWidget::updateSelection(Node *node) else prop = addBoolProperty(ligoProperty, parameter, primitive); + d_ptr->addPrimitive( prop, const_cast< NLLIGO::IPrimitive* >( primitive ) ); + // Default value ? if ((ligoProperty == NULL) || (ligoProperty->Default)) prop->setModified(false); @@ -198,6 +241,12 @@ void PropertyEditorWidget::updateSelection(Node *node) void PropertyEditorWidget::propertyChanged(QtProperty *p) { nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); + + NLLIGO::IPrimitive *prim = d_ptr->getPrimitive( p ); + if( prim != NULL ) + { + + } } void PropertyEditorWidget::resetProperty(QtProperty *property) @@ -422,5 +471,6 @@ void PropertyEditorWidget::blockSignalsOfProperties(bool block) m_boolManager->blockSignals(block); m_enumManager->blockSignals(block); m_stringArrayManager->blockSignals(block); + m_constStrArrPropMgr->blockSignals(block); } } /* namespace WorldEditor */ diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index 4152eec0a..e77b92664 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -38,6 +38,9 @@ class ConstStrArrEditorFactory; namespace WorldEditor { + +struct PropertyEditorWidgetPrivate; + /** @class PropertyEditorWidget @brief PropertyEditorWidget @@ -91,6 +94,8 @@ private: ConstStrArrEditorFactory *m_constStrArrEditorFactory; Ui::PropertyEditorWidget m_ui; + + PropertyEditorWidgetPrivate *d_ptr; }; /* PropertyEditorWidget */ } /* namespace WorldEditor */ From 3ad5ffee15d86cfb308ca1edc90b5812ca60792a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 00:38:35 +0200 Subject: [PATCH 130/282] Block only the propertychanged signal in the const_string_array property manager. --HG-- branch : gsoc2014-dfighter --- .../plugins/world_editor/property_editor_widget.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 0927ce6f7..93e9f31cf 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -471,6 +471,14 @@ void PropertyEditorWidget::blockSignalsOfProperties(bool block) m_boolManager->blockSignals(block); m_enumManager->blockSignals(block); m_stringArrayManager->blockSignals(block); - m_constStrArrPropMgr->blockSignals(block); + + if( block ) + { + disconnect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + } + else + { + connect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + } } } /* namespace WorldEditor */ From 351728352610d9586d75b6e9052df211ac1ea1df Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 01:54:45 +0200 Subject: [PATCH 131/282] Apply property changes. --HG-- branch : gsoc2014-dfighter --- .../world_editor/property_editor_widget.cpp | 133 +++++++++++++++++- .../world_editor/property_editor_widget.h | 9 ++ 2 files changed, 138 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 93e9f31cf..0854dcd15 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -241,19 +241,114 @@ void PropertyEditorWidget::updateSelection(Node *node) void PropertyEditorWidget::propertyChanged(QtProperty *p) { nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); - +} + +void PropertyEditorWidget::resetProperty(QtProperty *property) +{ + nlinfo(QString("property %1 reset").arg(property->propertyName()).toUtf8().constData()); +} + +NLLIGO::IProperty* PropertyEditorWidget::getLigoProperty( QtProperty *p ) +{ NLLIGO::IPrimitive *prim = d_ptr->getPrimitive( p ); - if( prim != NULL ) + if( prim == NULL ) { + return NULL; + } + NLLIGO::IProperty *prop = NULL; + prim->getPropertyByName( p->propertyName().toUtf8().constData(), prop ); + if( prop == NULL ) + { + return NULL; } + + return prop; } -void PropertyEditorWidget::resetProperty(QtProperty *property) +void PropertyEditorWidget::onBoolValueChanged( QtProperty *p, bool v ) { - nlinfo(QString("property %1 reset").arg(property->propertyName()).toUtf8().constData()); + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyString *pp = dynamic_cast< NLLIGO::CPropertyString* >( prop ); + if( pp == NULL ) + return; + + if( v ) + pp->String = "true"; + else + pp->String = "false"; +} + +void PropertyEditorWidget::onStringValueChanged( QtProperty *p, const QString &v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyString *pp = dynamic_cast< NLLIGO::CPropertyString* >( prop ); + if( pp == NULL ) + return; + + pp->String = v.toUtf8().constData(); +} + +void PropertyEditorWidget::onEnumValueChanged( QtProperty *p, int v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyString *pp = dynamic_cast< NLLIGO::CPropertyString* >( prop ); + if( pp == NULL ) + return; + + pp->String = p->valueText().toUtf8().constData(); +} + +void PropertyEditorWidget::onStrArrValueChanged( QtProperty *p, const QString &v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyStringArray *pp = dynamic_cast< NLLIGO::CPropertyStringArray* >( prop ); + if( pp == NULL ) + return; + + pp->StringArray.clear(); + + QStringList l = v.split( '\n' ); + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + pp->StringArray.push_back( itr.next().toUtf8().constData() ); + } +} + +void PropertyEditorWidget::onConstStrArrValueChanged( QtProperty *p, const QString &v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyStringArray *pp = dynamic_cast< NLLIGO::CPropertyStringArray* >( prop ); + if( pp == NULL ) + return; + + pp->StringArray.clear(); + + QStringList l = v.split( '\n' ); + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + pp->StringArray.push_back( itr.next().toUtf8().constData() ); + } } + QtProperty *PropertyEditorWidget::addBoolProperty(const NLLIGO::IProperty *property, const NLLIGO::CPrimitiveClass::CParameter ¶meter, const NLLIGO::IPrimitive *primitive) @@ -475,10 +570,40 @@ void PropertyEditorWidget::blockSignalsOfProperties(bool block) if( block ) { disconnect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + + disconnect(m_boolManager, SIGNAL( valueChanged( QtProperty*, bool ) ), + this, SLOT( onBoolValueChanged( QtProperty*, bool ) ) ); + + disconnect(m_stringManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStringValueChanged( QtProperty*, const QString& ) ) ); + + disconnect(m_enumManager, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumValueChanged( QtProperty*, int ) ) ); + + disconnect(m_stringArrayManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStrArrValueChanged( QtProperty*, const QString& ) ) ); + + disconnect(m_constStrArrPropMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onConstStrArrValueChanged( QtProperty*, const QString& ) ) ); } else { connect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + + connect(m_boolManager, SIGNAL( valueChanged( QtProperty*, bool ) ), + this, SLOT( onBoolValueChanged( QtProperty*, bool ) ) ); + + connect(m_stringManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStringValueChanged( QtProperty*, const QString& ) ) ); + + connect(m_enumManager, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumValueChanged( QtProperty*, int ) ) ); + + connect(m_stringArrayManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStrArrValueChanged( QtProperty*, const QString& ) ) ); + + connect(m_constStrArrPropMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onConstStrArrValueChanged( QtProperty*, const QString& ) ) ); } } } /* namespace WorldEditor */ diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index e77b92664..dae7ad13e 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -63,6 +63,15 @@ public Q_SLOTS: void propertyChanged(QtProperty *p); void resetProperty(QtProperty *property); + NLLIGO::IProperty* getLigoProperty( QtProperty *p ); + + void onBoolValueChanged( QtProperty *p, bool v ); + void onStringValueChanged( QtProperty *p, const QString &v ); + void onEnumValueChanged( QtProperty *p, int v ); + void onStrArrValueChanged( QtProperty *p, const QString &v ); + void onConstStrArrValueChanged( QtProperty *p, const QString &v ); + + private: QtProperty *addBoolProperty(const NLLIGO::IProperty *property, const NLLIGO::CPrimitiveClass::CParameter ¶meter, From 2d865a85671f248c4bee1e73dbf8cc8952a31cb7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 13 Jul 2014 21:38:14 +0200 Subject: [PATCH 132/282] Trying to load an invalid world editor file shouldn't crash the application, and an error messagebox should inform the user. --HG-- branch : gsoc2014-dfighter --- .../world_editor/world_editor_misc.cpp | 93 ++++++++++++------- .../plugins/world_editor/world_editor_misc.h | 2 + .../world_editor/world_editor_window.cpp | 7 +- 3 files changed, 65 insertions(+), 37 deletions(-) diff --git a/code/studio/src/plugins/world_editor/world_editor_misc.cpp b/code/studio/src/plugins/world_editor/world_editor_misc.cpp index 7401f49fb..5d6b7f94e 100644 --- a/code/studio/src/plugins/world_editor/world_editor_misc.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_misc.cpp @@ -34,35 +34,11 @@ namespace WorldEditor namespace Utils { -void syntaxError(const char *filename, xmlNodePtr xmlNode, const char *format, ...) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - nlerror("(%s), node (%s), line (%s) :\n%s", filename, xmlNode->name, xmlNode->content, buffer); -} +std::string lastError; -bool getPropertyString(std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) +std::string getLastError() { - // Call the CIXml version - if (!NLMISC::CIXml::getPropertyString(result, xmlNode, propName)) - { - // Output a formated error - syntaxError(filename, xmlNode, "Missing XML node property (%s)", propName); - return false; - } - return true; + return lastError; } uint32 getUniqueId() @@ -81,6 +57,8 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList { bool result = false; + lastError = ""; + // Load the document NLMISC::CIFile file; if (file.open(fileName)) @@ -110,20 +88,31 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList } if (version == -1) - syntaxError(fileName.c_str(), rootNode, "No version node"); + { + std::string error = "No version node in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; + } else { // Old format, if (version <= 1) { - syntaxError(fileName.c_str(), rootNode, "Old version node"); + std::string error = "Old version node in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } else { // Read it if (version > WORLD_EDITOR_FILE_VERSION) { - syntaxError(fileName.c_str(), node, "Unknown file version"); + std::string error = "Unknown file version in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } else { @@ -153,11 +142,12 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList { // Get the type std::string type; - if (getPropertyString(type, fileName.c_str(), node, "TYPE")) + + if ( NLMISC::CIXml::getPropertyString(type, node, "TYPE")) { // Read the filename std::string filenameChild; - if (getPropertyString(filenameChild, fileName.c_str(), node, "FILENAME")) + if ( NLMISC::CIXml::getPropertyString(filenameChild, node, "FILENAME")) { // Is it a landscape ? if (type == "landscape") @@ -179,11 +169,34 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList } } else + if ( type == "primitive" ) { worldEditList.push_back(WorldEditItem(PrimitiveType, filenameChild)); } + else + if( type.empty() ) + { + std::string error = "Empty type node property in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; + } } + else + { + std::string error = "Missing filename node property in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; + } + } + else + { + std::string error = "Missing type node property in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } } while (node = NLMISC::CIXml::getNextChildNode(node, "DATABASE_ELEMENT")); @@ -197,18 +210,26 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList } else { - // Error - syntaxError(fileName.c_str(), rootNode, "Unknown file header : %s", rootNode->name); + std::string error = "Unknown file header in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } } } catch (NLMISC::Exception &e) { - nlerror("Error reading file %s : %s", fileName.c_str(), e.what()); + std::string error = "Error reading file " + fileName + " : " + std::string( e.what() ); + lastError = error; + nlinfo( "%s", error.c_str() ); } } else - nlerror("Can't open the file %s for reading.", fileName.c_str()); + { + std::string error = "Can't open the file " + fileName + " for reading."; + lastError = error; + nlinfo( "%s", error.c_str() ); + } return result; } diff --git a/code/studio/src/plugins/world_editor/world_editor_misc.h b/code/studio/src/plugins/world_editor/world_editor_misc.h index d29b2553b..36c7b1a6a 100644 --- a/code/studio/src/plugins/world_editor/world_editor_misc.h +++ b/code/studio/src/plugins/world_editor/world_editor_misc.h @@ -49,6 +49,8 @@ typedef std::vector WorldEditList; // Generate unique identificator uint32 getUniqueId(); +std::string getLastError(); + // Load *.worldedit file and return list primitives and landscapes. bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList); diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index afb667358..d4ae355f4 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -174,7 +174,12 @@ void WorldEditorWindow::loadWorldEditFile(const QString &fileName) Utils::WorldEditList worldEditList; if (!Utils::loadWorldEditFile(fileName.toUtf8().constData(), worldEditList)) { - // TODO: add the message box + std::string error = Utils::getLastError(); + + QMessageBox::critical( this, + tr( "Error opening world editor file" ), + tr( error.c_str() ) ); + return; } From 61b8a4ef820d6288417f89262f056f890200e749 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 01:30:30 +0200 Subject: [PATCH 133/282] Save world editor files. --HG-- branch : gsoc2014-dfighter --- .../world_editor/world_editor_actions.cpp | 172 ++++++++++++++++++ .../world_editor/world_editor_actions.h | 25 +++ .../world_editor/world_editor_window.cpp | 12 ++ .../world_editor/world_editor_window.h | 3 + 4 files changed, 212 insertions(+) diff --git a/code/studio/src/plugins/world_editor/world_editor_actions.cpp b/code/studio/src/plugins/world_editor/world_editor_actions.cpp index e10e15745..5255e976f 100644 --- a/code/studio/src/plugins/world_editor/world_editor_actions.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_actions.cpp @@ -209,6 +209,178 @@ void CreateWorldCommand::redo() m_model->createWorldEditNode(m_fileName); } + +WorldSaver::WorldSaver( PrimitivesTreeModel *model, LandscapeEditor::ZoneBuilderBase *zoneBuilder, const std::string &dataDir, const std::string &context ) +{ + m_model = model; + m_zoneBuilder = zoneBuilder; + m_dataDir = dataDir; + m_context = context; +} + +bool WorldSaver::save() +{ + QModelIndex pidx = m_model->index( 0, 0 ); + if( !pidx.isValid() ) + { + lastError = "No root node."; + return false; + } + + int rows = m_model->rowCount( pidx ); + bool ok = false; + + for( int i = 0; i < rows; i++ ) + { + QModelIndex idx = m_model->index( i, 0, pidx ); + + Node *node = reinterpret_cast< Node* >( idx.internalPointer() ); + Node::NodeType t = node->type(); + + switch( t ) + { + case Node::LandscapeNodeType: ok = saveLandscapeNode( node ); break; + case Node::RootPrimitiveNodeType: ok = savePrimitiveNode( node ); break; + } + + if( !ok ) + return false; + } + + ok = saveWorldEditFile(); + return ok; +} + +bool WorldSaver::saveLandscapeNode( Node *node ) +{ + LandscapeNode *n = dynamic_cast< LandscapeNode* >( node ); + if( n == NULL ) + { + lastError = "Trying to save a non-landscape node as landscape."; + return false; + } + + LandscapeEditor::ZoneRegionObject *z = m_zoneBuilder->zoneRegion( n->id() ); + if( z == NULL ) + { + lastError = "The specified zoneregion doesn't exist."; + return false; + } + + z->setFileName( n->fileName().toUtf8().constData() ); + bool ok = z->save(); + + if( ok ) + { + std::pair< std::string, std::string > p; + p.first = "landscape"; + p.second = n->fileName().toUtf8().constData(); + + m_data.push_back( p ); + } + else + { + lastError = "Couldn't save landscape file " + std::string( n->fileName().toUtf8().constData() ); + } + + return ok; +} + +bool WorldSaver::savePrimitiveNode( Node *node ) +{ + RootPrimitiveNode *n = dynamic_cast< RootPrimitiveNode* >( node ); + if( n == NULL ) + { + lastError = "Trying to save a non-primitive node as primitive."; + return false; + } + + bool ok = NLLIGO::saveXmlPrimitiveFile( *(n->primitives()), n->fileName().toUtf8().constData() ); + + if( ok ) + { + std::pair< std::string, std::string > p; + p.first = "primitive"; + p.second = n->fileName().toUtf8().constData(); + + m_data.push_back( p ); + } + else + { + lastError = "Couldn't save primitive file " + std::string( n->fileName().toUtf8().constData() ); + } + + return ok; +} + +bool WorldSaver::saveWorldEditFile() +{ + QModelIndex idx = m_model->index( 0, 0 ); + Node *node = reinterpret_cast< Node* >( idx.internalPointer() ); + Node::NodeType t = node->type(); + + WorldEditNode *n = dynamic_cast< WorldEditNode* >( node ); + if( n == NULL ) + { + lastError = "Not a worldedit node."; + return false; + } + + std::string fn = n->data( 0 ).toString().toUtf8().constData(); + bool ok = writeWorldEditFile( fn ); + + return ok; +} + +bool WorldSaver::writeWorldEditFile( const std::string &fn ) +{ + if( fn.empty() ) + return false; + + NLMISC::COFile of; + if( !of.open( fn, false, true, false ) ) + { + lastError = "Couldn't open file " + fn + " for writing."; + return false; + } + + NLMISC::COXml xml; + xml.init( &of ); + + xmlNodePtr rootNode = xmlNewDocNode (xml.getDocument (), NULL, (const xmlChar*)"NEL_WORLD_EDITOR_PROJECT", NULL); + xmlDocSetRootElement (xml.getDocument (), rootNode); + xmlNodePtr node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"VERSION", NULL); + xmlNodePtr text = xmlNewText ((const xmlChar *) NLMISC::toString( WORLD_EDITOR_FILE_VERSION ).c_str ()); + xmlAddChild( node, text ); + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATA_DIRECTORY", NULL); + xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)m_dataDir.c_str ()); + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"CONTEXT", NULL); + xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)m_context.c_str ()); + + std::vector< std::pair< std::string, std::string > >::const_iterator itr = m_data.begin(); + while( itr != m_data.end() ) + { + const std::pair< std::string, std::string > &p = *itr; + + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATABASE_ELEMENT", NULL); + xmlSetProp (node, (const xmlChar*)"FILENAME", (const xmlChar*)p.second.c_str ()); + + if( p.first == "landscape" ) + xmlSetProp (node, (const xmlChar*)"TYPE", (const xmlChar*)("landscape")); + else + xmlSetProp (node, (const xmlChar*)"TYPE", (const xmlChar*)("primitive")); + + ++itr; + } + + xml.flush(); + + of.close(); + + + return true; +} + LoadLandscapeCommand::LoadLandscapeCommand(const QString &fileName, PrimitivesTreeModel *model, LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent) : QUndoCommand(parent), diff --git a/code/studio/src/plugins/world_editor/world_editor_actions.h b/code/studio/src/plugins/world_editor/world_editor_actions.h index 89de14e9a..95ce093e2 100644 --- a/code/studio/src/plugins/world_editor/world_editor_actions.h +++ b/code/studio/src/plugins/world_editor/world_editor_actions.h @@ -72,6 +72,31 @@ private: PrimitivesTreeModel *const m_model; }; + +class WorldSaver +{ +public: + WorldSaver( PrimitivesTreeModel *model, LandscapeEditor::ZoneBuilderBase *zoneBuilder, const std::string &dataDir, const std::string &context ); + bool save(); + + std::string getLastError() const{ return lastError; } + +private: + bool saveLandscapeNode( Node *node ); + bool savePrimitiveNode( Node *node ); + bool saveWorldEditFile(); + bool writeWorldEditFile( const std::string &fn ); + + std::string m_dataDir; + std::string m_context; + PrimitivesTreeModel *m_model; + LandscapeEditor::ZoneBuilderBase *m_zoneBuilder; + + std::vector< std::pair< std::string, std::string > > m_data; + + std::string lastError; +}; + /** @class LoadLandscapeCommand @brief diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index d4ae355f4..cec3baee1 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -194,8 +194,10 @@ void WorldEditorWindow::loadWorldEditFile(const QString &fileName) { case Utils::DataDirectoryType: m_zoneBuilderBase->init(QString(worldEditList[i].second.c_str()), true); + m_dataDir = worldEditList[i].second.c_str(); break; case Utils::ContextType: + m_context = worldEditList[i].second.c_str(); break; case Utils::LandscapeType: m_undoStack->push(new LoadLandscapeCommand(QString(worldEditList[i].second.c_str()), m_primitivesModel, m_zoneBuilderBase)); @@ -221,6 +223,16 @@ void WorldEditorWindow::newWorldEditFile() void WorldEditorWindow::saveWorldEditFile() { + WorldSaver saver( m_primitivesModel, m_zoneBuilderBase, m_dataDir.toUtf8().constData(), m_context.toUtf8().constData() ); + bool ok = saver.save(); + QString error = saver.getLastError().c_str(); + + if( !ok ) + { + QMessageBox::critical( this, + tr( "Failed to save world editor files" ), + tr( "Failed to save world editor files.\nError:\n " ) + error ); + } } void WorldEditorWindow::openProjectSettings() diff --git a/code/studio/src/plugins/world_editor/world_editor_window.h b/code/studio/src/plugins/world_editor/world_editor_window.h index f289e6c2a..60a6a988a 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.h +++ b/code/studio/src/plugins/world_editor/world_editor_window.h @@ -76,6 +76,9 @@ private: void loadWorldEditFile(const QString &fileName); void checkCurrentWorld(); + QString m_context; + QString m_dataDir; + QString m_lastDir; QLabel *m_statusInfo; From 56a4c3ea7d259270a9601e5e946b16d3d334d869 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 18:51:06 +0200 Subject: [PATCH 134/282] When changing a property make sure to set default to false, so it's actually saved! --HG-- branch : gsoc2014-dfighter --- .../src/plugins/world_editor/property_editor_widget.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 0854dcd15..9c24c8452 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -280,6 +280,8 @@ void PropertyEditorWidget::onBoolValueChanged( QtProperty *p, bool v ) pp->String = "true"; else pp->String = "false"; + + pp->Default = false; } void PropertyEditorWidget::onStringValueChanged( QtProperty *p, const QString &v ) @@ -293,6 +295,7 @@ void PropertyEditorWidget::onStringValueChanged( QtProperty *p, const QString &v return; pp->String = v.toUtf8().constData(); + pp->Default = false; } void PropertyEditorWidget::onEnumValueChanged( QtProperty *p, int v ) @@ -306,6 +309,7 @@ void PropertyEditorWidget::onEnumValueChanged( QtProperty *p, int v ) return; pp->String = p->valueText().toUtf8().constData(); + pp->Default = false; } void PropertyEditorWidget::onStrArrValueChanged( QtProperty *p, const QString &v ) @@ -326,6 +330,8 @@ void PropertyEditorWidget::onStrArrValueChanged( QtProperty *p, const QString &v { pp->StringArray.push_back( itr.next().toUtf8().constData() ); } + + pp->Default = false; } void PropertyEditorWidget::onConstStrArrValueChanged( QtProperty *p, const QString &v ) @@ -346,6 +352,8 @@ void PropertyEditorWidget::onConstStrArrValueChanged( QtProperty *p, const QStri { pp->StringArray.push_back( itr.next().toUtf8().constData() ); } + + pp->Default = false; } From 1cbcca259c8a8e11712b88c6ab23f492f14a414a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 20:19:53 +0200 Subject: [PATCH 135/282] 'Fixed' the Mission Compiler crash. --HG-- branch : gsoc2014-dfighter --- .../mission_compiler/mission_compiler_main_window.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp index e01f5f617..10985aa38 100644 --- a/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp +++ b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp @@ -90,7 +90,14 @@ MissionCompilerMainWindow::MissionCompilerMainWindow(QWidget *parent) : NLLIGO::Register(); // TODO try/catch exception. Crashes if path invalid. - m_ligoConfig.readPrimitiveClass(NLMISC::CPath::lookup("world_editor_classes.xml").c_str(), false); + try{ + m_ligoConfig.readPrimitiveClass(NLMISC::CPath::lookup("world_editor_classes.xml").c_str(), false); + } + catch( NLMISC::Exception &e ) + { + nlinfo( "Exception occured during Mission Compiler LIGO startup: %s", e.what() ); + } + NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig; } From 63b6a03f85afbb944f5baa0c6da8d436aa0e6cec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 20:29:57 +0200 Subject: [PATCH 136/282] Fixed another crash. --HG-- branch : gsoc2014-dfighter --- .../mission_compiler/mission_compiler_settings_page.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp index ad115cffd..28dc4f9ce 100644 --- a/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp +++ b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp @@ -191,7 +191,9 @@ void MissionCompilerSettingsPage::writeSettings() { for(int column = 0; column < m_ui.serversTableWidget->columnCount(); column++) { - items << m_ui.serversTableWidget->item(row, column)->text(); + QTableWidgetItem *item = m_ui.serversTableWidget->item(row, column); + if( item != NULL ) + items << item->text(); } } From d30e9ad226c60ebdd63ee2bc1a73981666e835e6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 21:41:11 +0200 Subject: [PATCH 137/282] Initialize the undostack to NULL, so we get a proper crash instead of a dangled pointer crash. --HG-- branch : gsoc2014-dfighter --- .../plugins/translation_manager/translation_manager_editor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_editor.h b/code/studio/src/plugins/translation_manager/translation_manager_editor.h index fd53ba863..3ded2c3af 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_editor.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_editor.h @@ -32,8 +32,8 @@ class CEditor : public QMdiSubWindow Q_OBJECT public: - CEditor(QMdiArea *parent) : QMdiSubWindow(parent) {} - CEditor() : QMdiSubWindow() {} + CEditor(QMdiArea *parent) : QMdiSubWindow(parent) { current_stack = NULL; } + CEditor() : QMdiSubWindow() { current_stack = NULL; } virtual void open(QString filename) =0; virtual void save() =0; virtual void saveAs(QString filename) =0; From 28c30b70f15f72139c0bb585580c1517fd8e5500 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 21:46:16 +0200 Subject: [PATCH 138/282] Set the undostack so we won't crash... --HG-- branch : gsoc2014-dfighter --- .../translation_manager/translation_manager_main_window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 244a5a92c..44d0963ae 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -280,6 +280,7 @@ void CMainWindow::openWorkFile(QString file) if(isWorksheetEditor(file_path->filePath())) { CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea); + new_window->setUndoStack( m_undoStack ); new_window->open(file_path->filePath()); new_window->activateWindow(); } From f60f761b7abbc81029a9dcb5957b2fa8ed56d631 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 16 Jul 2014 02:52:17 +0200 Subject: [PATCH 139/282] I don't really know what to write here. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/translation_manager_main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 44d0963ae..dcade72ef 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -558,7 +558,7 @@ void CMainWindow::readSettings() // core settings settings->beginGroup(Core::Constants::DATA_PATH_SECTION); level_design_path = settings->value(Core::Constants::LEVELDESIGN_PATH).toString(); - primitives_path = QString(Core::Constants::PRIMITIVES_PATH); //TODO + primitives_path = settings->value( Core::Constants::PRIMITIVES_PATH ).toString(); settings->endGroup(); } From d33fb9345e07caf756e1c4c4ee179934cc5c5d80 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 17 Jul 2014 19:08:29 +0200 Subject: [PATCH 140/282] UXT Editor widget --HG-- branch : gsoc2014-dfighter --- .../translation_manager/CMakeLists.txt | 1 + .../translation_manager_constants.h | 4 +- .../translation_manager_main_window.cpp | 14 +++ .../translation_manager_main_window.h | 1 + .../translation_manager/uxt_editor.cpp | 96 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 33 +++++++ 6 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/translation_manager/uxt_editor.cpp create mode 100644 code/studio/src/plugins/translation_manager/uxt_editor.h diff --git a/code/studio/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt index 6f0f7a1c2..b35c64735 100644 --- a/code/studio/src/plugins/translation_manager/CMakeLists.txt +++ b/code/studio/src/plugins/translation_manager/CMakeLists.txt @@ -17,6 +17,7 @@ SET(OVQT_PLUG_TRANSLATION_MANAGER_HDR translation_manager_plugin.h ftp_selection.h editor_worksheet.h editor_phrase.h + uxt_editor.h ) SET(OVQT_PLUG_TRANSLATION_MANAGER_UIS translation_manager_settings_page.ui diff --git a/code/studio/src/plugins/translation_manager/translation_manager_constants.h b/code/studio/src/plugins/translation_manager/translation_manager_constants.h index d72a2b223..7ff813d40 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_constants.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_constants.h @@ -21,8 +21,9 @@ namespace TranslationManager { namespace Constants { -const int ED_SHEET = 1; +const int ED_SHEET = 1; const int ED_PHRASE = 2; +const int ED_UXT = 3; const char *const WK_BOTNAMES = "bot_names_wk.txt"; const char *const WK_ITEM = "item_words_wk.txt"; @@ -32,6 +33,7 @@ const char *const WK_SPHRASE = "sphrase_words_wk.txt"; const char *const WK_PLACE = "place_words_wk.txt"; const char *const WK_CONTINENT = "place_words_wk.txt"; const char *const WK_STABLE = "place_words_wk.txt"; +const char *const WK_UXT = "wk.uxt"; } } diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index dcade72ef..f3e882739 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -41,6 +41,8 @@ #include #include +#include "uxt_editor.h" + namespace TranslationManager { @@ -84,6 +86,10 @@ void CMainWindow::createMenus() if( m != NULL ) { windowMenu = m->addMenu("Window"); + + QAction *a = m->addAction( "Uxt" ); + connect( a, SIGNAL( triggered() ), this, SLOT( onUxtClicked() ) ); + menu = m; } @@ -544,6 +550,14 @@ void CMainWindow::mergeSingleFile() } } +void CMainWindow::onUxtClicked() +{ + UXTEditor *e = new UXTEditor(); + e->open( work_path + "/" + QString( Constants::WK_UXT ) ); + _ui.mdiArea->addSubWindow( e ); + e->activateWindow(); +} + // Read the settings from QSettings void CMainWindow::readSettings() { diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h index 73bccdd8e..ba6ce8746 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h @@ -90,6 +90,7 @@ private Q_SLOTS: void setActiveSubWindow(QWidget *window); void updateWindowsList(); void mergeSingleFile(); + void onUxtClicked(); private: void openWorkFile(QString file); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp new file mode 100644 index 000000000..e13a6300d --- /dev/null +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -0,0 +1,96 @@ +#include "translation_manager_constants.h" +#include "uxt_editor.h" + +#include +#include +#include + +#include "nel/misc/diff_tool.h" + +namespace TranslationManager +{ + +class UXTEditorPvt +{ +public: + + UXTEditorPvt() + { + t = new QTableWidget(); + } + + QTableWidget *t; +}; + + +UXTEditor::UXTEditor( QMdiArea *parent ) : +CEditor( parent ) +{ + editor_type = Constants::ED_UXT; + setAttribute( Qt::WA_DeleteOnClose ); + + d_ptr = new UXTEditorPvt(); +} + +UXTEditor::~UXTEditor() +{ + delete d_ptr; + d_ptr = NULL; +} + +void UXTEditor::open( QString filename ) +{ + std::vector< STRING_MANAGER::TStringInfo > infos; + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + + if( infos.size() == 0 ) + return; + + d_ptr->t->clear(); + d_ptr->t->setColumnCount( 2 ); + d_ptr->t->setRowCount( infos.size() ); + + int i = 0; + + std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = infos.begin(); + while( itr != infos.end() ) + { + const STRING_MANAGER::TStringInfo &info = *itr; + + QTableWidgetItem *name = new QTableWidgetItem( info.Identifier.c_str() ); + QTableWidgetItem *text1 = new QTableWidgetItem( info.Text.toUtf8().c_str() ); + + d_ptr->t->setItem( i, 0, name ); + d_ptr->t->setItem( i, 1, text1 ); + + ++itr; + i++; + } + + d_ptr->t->resizeColumnsToContents(); + + setWidget( d_ptr->t ); + setCurrentFile( filename ); +} + +void UXTEditor::save() +{ +} + +void UXTEditor::saveAs( QString filename ) +{ +} + +void UXTEditor::activateWindow() +{ + showMaximized(); +} + + +void UXTEditor::closeEvent( QCloseEvent *e ) +{ + e->accept(); + close(); +} + +} diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h new file mode 100644 index 000000000..231461bc3 --- /dev/null +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -0,0 +1,33 @@ +#ifndef UXT_EDITOR_H +#define UXT_EDITOR_H + +#include "translation_manager_editor.h" + +namespace TranslationManager +{ + +class UXTEditorPvt; + +class UXTEditor : public CEditor +{ + Q_OBJECT +public: + UXTEditor( QMdiArea *parent = NULL ); + ~UXTEditor(); + + void open( QString filename ); + void save(); + void saveAs( QString filename ); + void activateWindow(); + +protected: + void closeEvent( QCloseEvent *e ); + +private: + UXTEditorPvt *d_ptr; +}; + +} + +#endif + From 0de5152aa928b8f89c7a866450aeff096ff686a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 17 Jul 2014 19:17:02 +0200 Subject: [PATCH 141/282] Set header texts. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 12 ++++ .../plugins/translation_manager/uxt_editor.h | 58 ++++++++++--------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index e13a6300d..3ac7cb066 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -50,6 +50,8 @@ void UXTEditor::open( QString filename ) d_ptr->t->setColumnCount( 2 ); d_ptr->t->setRowCount( infos.size() ); + setHeaderText( "Id", "Text" ); + int i = 0; std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = infos.begin(); @@ -93,4 +95,14 @@ void UXTEditor::closeEvent( QCloseEvent *e ) close(); } +void UXTEditor::setHeaderText( const QString &id, const QString &text ) +{ + QTableWidgetItem *h1 = new QTableWidgetItem( id ); + QTableWidgetItem *h2 = new QTableWidgetItem( text ); + h1->setTextAlignment( Qt::AlignLeft ); + h2->setTextAlignment( Qt::AlignLeft ); + d_ptr->t->setHorizontalHeaderItem( 0, h1 ); + d_ptr->t->setHorizontalHeaderItem( 1, h2 ); +} + } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 231461bc3..3f6d52b3a 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -1,33 +1,35 @@ -#ifndef UXT_EDITOR_H -#define UXT_EDITOR_H - -#include "translation_manager_editor.h" - -namespace TranslationManager -{ - -class UXTEditorPvt; - -class UXTEditor : public CEditor -{ - Q_OBJECT -public: - UXTEditor( QMdiArea *parent = NULL ); +#ifndef UXT_EDITOR_H +#define UXT_EDITOR_H + +#include "translation_manager_editor.h" + +namespace TranslationManager +{ + +class UXTEditorPvt; + +class UXTEditor : public CEditor +{ + Q_OBJECT +public: + UXTEditor( QMdiArea *parent = NULL ); ~UXTEditor(); void open( QString filename ); void save(); void saveAs( QString filename ); - void activateWindow(); - -protected: - void closeEvent( QCloseEvent *e ); - -private: - UXTEditorPvt *d_ptr; -}; - -} - -#endif - + void activateWindow(); + +protected: + void closeEvent( QCloseEvent *e ); + +private: + void setHeaderText( const QString &id, const QString &text ); + + UXTEditorPvt *d_ptr; +}; + +} + +#endif + From fbc1632d040861a6f52e28fe10e181b8989f5ef4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:27:05 +0200 Subject: [PATCH 142/282] Apply table changes to the loaded data, and offer to save when closing the changed table. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 52 ++++++++++++++++++- .../plugins/translation_manager/uxt_editor.h | 4 ++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 3ac7cb066..69cd1a9b6 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "nel/misc/diff_tool.h" @@ -17,9 +18,12 @@ public: UXTEditorPvt() { t = new QTableWidget(); + changed = false; } QTableWidget *t; + std::vector< STRING_MANAGER::TStringInfo > infos; + bool changed; }; @@ -30,6 +34,8 @@ CEditor( parent ) setAttribute( Qt::WA_DeleteOnClose ); d_ptr = new UXTEditorPvt(); + + blockTableSignals( false ); } UXTEditor::~UXTEditor() @@ -40,12 +46,16 @@ UXTEditor::~UXTEditor() void UXTEditor::open( QString filename ) { - std::vector< STRING_MANAGER::TStringInfo > infos; + std::vector< STRING_MANAGER::TStringInfo > &infos = d_ptr->infos; + + infos.clear(); STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); - if( infos.size() == 0 ) + if( d_ptr->infos.size() == 0 ) return; + blockTableSignals( true ); + d_ptr->t->clear(); d_ptr->t->setColumnCount( 2 ); d_ptr->t->setRowCount( infos.size() ); @@ -71,6 +81,8 @@ void UXTEditor::open( QString filename ) d_ptr->t->resizeColumnsToContents(); + blockTableSignals( false ); + setWidget( d_ptr->t ); setCurrentFile( filename ); } @@ -91,10 +103,38 @@ void UXTEditor::activateWindow() void UXTEditor::closeEvent( QCloseEvent *e ) { + if( d_ptr->changed ) + { + int reply = QMessageBox::question( this, + tr( "Table changed" ), + tr( "The table has changed. Would you like to save your changes?" ), + QMessageBox::Yes, + QMessageBox::No + ); + + if( reply == QMessageBox::Yes ) + save(); + + } + e->accept(); close(); } +void UXTEditor::onCellChanged( int row, int column ) +{ + QTableWidgetItem *item = d_ptr->t->item( row, column ); + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ row ]; + + if( column == 0 ) + info.Identifier = item->text().toUtf8().constData(); + else + if( column == 1 ) + info.Text = item->text().toUtf8().constData(); + + d_ptr->changed = true; +} + void UXTEditor::setHeaderText( const QString &id, const QString &text ) { QTableWidgetItem *h1 = new QTableWidgetItem( id ); @@ -105,4 +145,12 @@ void UXTEditor::setHeaderText( const QString &id, const QString &text ) d_ptr->t->setHorizontalHeaderItem( 1, h2 ); } +void UXTEditor::blockTableSignals( bool block ) +{ + if( block ) + disconnect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); + else + connect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); +} + } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 3f6d52b3a..5a96377a6 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -23,8 +23,12 @@ public: protected: void closeEvent( QCloseEvent *e ); +private Q_SLOTS: + void onCellChanged( int row, int column ); + private: void setHeaderText( const QString &id, const QString &text ); + void blockTableSignals( bool block = false ); UXTEditorPvt *d_ptr; }; From 05216897f0e96e63feea777c1cc8ac5b0e5bd9b0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:50:40 +0200 Subject: [PATCH 143/282] Implemented saving. --HG-- branch : gsoc2014-dfighter --- .../translation_manager_main_window.cpp | 4 ++- .../translation_manager/uxt_editor.cpp | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index f3e882739..59e8d5ebe 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -553,7 +553,9 @@ void CMainWindow::mergeSingleFile() void CMainWindow::onUxtClicked() { UXTEditor *e = new UXTEditor(); - e->open( work_path + "/" + QString( Constants::WK_UXT ) ); + QString path = work_path + "/" + QString( Constants::WK_UXT ); + e->open( path ); + e->setCurrentFile( path ); _ui.mdiArea->addSubWindow( e ); e->activateWindow(); } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 69cd1a9b6..6147b8de2 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include + #include "nel/misc/diff_tool.h" namespace TranslationManager @@ -89,10 +92,39 @@ void UXTEditor::open( QString filename ) void UXTEditor::save() { + saveAs( current_file ); } void UXTEditor::saveAs( QString filename ) { + QFile f( filename ); + if( !f.open( QIODevice::WriteOnly ) ) + return; + + QTextStream out( &f ); + + std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); + while( itr != d_ptr->infos.end() ) + { + QString line = ""; + + line += itr->Identifier.c_str(); + line += "\t"; + + line += "["; + line += itr->Text.toUtf8().c_str(); + line += "]"; + + line += "\r\n"; + + out << line; + + ++itr; + } + + f.close(); + + d_ptr->changed = false; } void UXTEditor::activateWindow() From 9bda0bd1e7c81e92437ecb4cc83fec5b6484f683 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:53:36 +0200 Subject: [PATCH 144/282] Added copyright headers to the new files. --HG-- branch : gsoc2014-dfighter --- .../plugins/translation_manager/uxt_editor.cpp | 17 +++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 6147b8de2..a6c4ec500 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Translation Manager Plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "translation_manager_constants.h" #include "uxt_editor.h" diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 5a96377a6..738f88f7d 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Translation Manager Plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef UXT_EDITOR_H #define UXT_EDITOR_H From 3e188334fe8ce8900e9144c457e3c7b29feef6af Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:08:31 +0200 Subject: [PATCH 145/282] Allow only 1 instance of the uxt editor. --HG-- branch : gsoc2014-dfighter --- .../translation_manager_main_window.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 59e8d5ebe..aafc6f473 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -552,8 +552,13 @@ void CMainWindow::mergeSingleFile() void CMainWindow::onUxtClicked() { - UXTEditor *e = new UXTEditor(); QString path = work_path + "/" + QString( Constants::WK_UXT ); + path.replace( "\\", "/" ); + + if( getEditorByWindowFilePath( path ) != NULL ) + return; + + UXTEditor *e = new UXTEditor(); e->open( path ); e->setCurrentFile( path ); _ui.mdiArea->addSubWindow( e ); From 485ee77406f367c2453fd5e476cba14666e0dd0e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:18:41 +0200 Subject: [PATCH 146/282] Use the QWidget modified property instead of the UXTEditor's own. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/translation_manager/uxt_editor.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index a6c4ec500..bf6e787b6 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -38,12 +38,10 @@ public: UXTEditorPvt() { t = new QTableWidget(); - changed = false; } QTableWidget *t; std::vector< STRING_MANAGER::TStringInfo > infos; - bool changed; }; @@ -141,7 +139,7 @@ void UXTEditor::saveAs( QString filename ) f.close(); - d_ptr->changed = false; + setWindowModified( false ); } void UXTEditor::activateWindow() @@ -152,7 +150,7 @@ void UXTEditor::activateWindow() void UXTEditor::closeEvent( QCloseEvent *e ) { - if( d_ptr->changed ) + if( isWindowModified() ) { int reply = QMessageBox::question( this, tr( "Table changed" ), @@ -181,7 +179,7 @@ void UXTEditor::onCellChanged( int row, int column ) if( column == 1 ) info.Text = item->text().toUtf8().constData(); - d_ptr->changed = true; + setWindowModified( true ); } void UXTEditor::setHeaderText( const QString &id, const QString &text ) From d9c2620e6e08f2e110ab6c4a6df638148b51539c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:52:23 +0200 Subject: [PATCH 147/282] Implemented row deletion / insertion. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 24 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index bf6e787b6..cb4a0a0f3 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -148,6 +148,30 @@ void UXTEditor::activateWindow() } +void UXTEditor::insertRow() +{ + d_ptr->infos.push_back( STRING_MANAGER::TStringInfo() ); + d_ptr->t->setRowCount( d_ptr->t->rowCount() + 1 ); + + setWindowModified( true ); +} + + +void UXTEditor::deleteRow() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + std::vector< STRING_MANAGER::TStringInfo >::iterator itr = d_ptr->infos.begin(); + itr += r; + d_ptr->infos.erase( itr ); + + d_ptr->t->removeRow( r ); + + setWindowModified( true ); +} + void UXTEditor::closeEvent( QCloseEvent *e ) { if( isWindowModified() ) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 738f88f7d..d37be8c72 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -37,6 +37,10 @@ public: void saveAs( QString filename ); void activateWindow(); +public Q_SLOTS: + void insertRow(); + void deleteRow(); + protected: void closeEvent( QCloseEvent *e ); From 62a6b408a26534426964445b737148bd14e1c1d1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 19 Jul 2014 17:23:53 +0200 Subject: [PATCH 148/282] Show insert / delete row in context menu. --HG-- branch : gsoc2014-dfighter --- .../plugins/translation_manager/uxt_editor.cpp | 16 ++++++++++++++++ .../src/plugins/translation_manager/uxt_editor.h | 1 + 2 files changed, 17 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index cb4a0a0f3..88d866fe2 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include #include #include @@ -192,6 +194,20 @@ void UXTEditor::closeEvent( QCloseEvent *e ) close(); } +void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) +{ + QMenu *menu = new QMenu( this ); + QAction *insertAction = new QAction( "Insert row", menu ); + QAction *deleteAction = new QAction( "Delete row", menu ); + + connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); + connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + + menu->addAction( insertAction ); + menu->addAction( deleteAction ); + menu->exec( e->globalPos() ); +} + void UXTEditor::onCellChanged( int row, int column ) { QTableWidgetItem *item = d_ptr->t->item( row, column ); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index d37be8c72..7499df44c 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -43,6 +43,7 @@ public Q_SLOTS: protected: void closeEvent( QCloseEvent *e ); + void contextMenuEvent( QContextMenuEvent *e ); private Q_SLOTS: void onCellChanged( int row, int column ); From fbcfa4ee6f2dbb854ac00db7a0ec23a8993bfccc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 19 Jul 2014 17:26:59 +0200 Subject: [PATCH 149/282] Ask for confirmation before deleting a row. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/translation_manager/uxt_editor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 88d866fe2..4004c05e4 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -165,6 +165,14 @@ void UXTEditor::deleteRow() if( r < 0 ) return; + int answer = QMessageBox::question( this, + tr( "Deleting a row" ), + tr( "Are you sure you want to delete this row?" ), + QMessageBox::Yes, + QMessageBox::Cancel ); + if( QMessageBox::Yes != answer ) + return; + std::vector< STRING_MANAGER::TStringInfo >::iterator itr = d_ptr->infos.begin(); itr += r; d_ptr->infos.erase( itr ); From 2c812e90abac322b6c612dd4c670cfed404bb8e0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 17:24:04 +0200 Subject: [PATCH 150/282] Work with translated files, instead of work files. --HG-- branch : gsoc2014-dfighter --- .../translation_manager_main_window.cpp | 25 ++++++++++++---- .../translation_manager_main_window.h | 3 +- .../translation_manager/uxt_editor.cpp | 30 ++++++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index aafc6f473..b439edce6 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -54,6 +54,7 @@ CMainWindow::CMainWindow(QWidget *parent) _ui.mdiArea->closeAllSubWindows(); windowMapper = new QSignalMapper(this); + m_UXTMapper = new QSignalMapper(this); connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveSubWindow(QWidget *))); initialize_settings["georges"] = false; @@ -87,8 +88,20 @@ void CMainWindow::createMenus() { windowMenu = m->addMenu("Window"); - QAction *a = m->addAction( "Uxt" ); - connect( a, SIGNAL( triggered() ), this, SLOT( onUxtClicked() ) ); + QMenu *mm = m->addMenu( "UI translation" ); + if( mm != NULL ) + { + QStringListIterator itr( languages ); + while( itr.hasNext() ) + { + QString lang = itr.next(); + QAction *a = mm->addAction( lang ); + connect( a, SIGNAL( triggered() ), m_UXTMapper, SLOT( map() ) ); + m_UXTMapper->setMapping( a, lang ); + } + + connect( m_UXTMapper, SIGNAL( mapped( QString ) ), this, SLOT( onUxtMapped( QString ) ) ); + } menu = m; } @@ -550,14 +563,14 @@ void CMainWindow::mergeSingleFile() } } -void CMainWindow::onUxtClicked() +void CMainWindow::onUxtMapped( QString lang ) { - QString path = work_path + "/" + QString( Constants::WK_UXT ); + QString path = translation_path + "/" + lang + ".uxt"; path.replace( "\\", "/" ); - + if( getEditorByWindowFilePath( path ) != NULL ) return; - + UXTEditor *e = new UXTEditor(); e->open( path ); e->setCurrentFile( path ); diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h index ba6ce8746..34f60ff19 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h @@ -71,6 +71,7 @@ private: QAction *saveAsAct; QMenu *windowMenu; QSignalMapper *windowMapper; + QSignalMapper *m_UXTMapper; // config QMap initialize_settings; QList filters; @@ -90,7 +91,7 @@ private Q_SLOTS: void setActiveSubWindow(QWidget *window); void updateWindowsList(); void mergeSingleFile(); - void onUxtClicked(); + void onUxtMapped( QString lang ); private: void openWorkFile(QString file); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 4004c05e4..9f8cc56f4 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -29,6 +29,7 @@ #include #include "nel/misc/diff_tool.h" +#include "nel/misc/i18n.h" namespace TranslationManager { @@ -120,23 +121,36 @@ void UXTEditor::saveAs( QString filename ) QTextStream out( &f ); + int idx = 0; std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); while( itr != d_ptr->infos.end() ) { - QString line = ""; + QString hashLine = "// HASH_VALUE "; + hashLine += QString( NLMISC::CI18N::hashToString( itr->HashValue ).c_str() ).toUpper(); + hashLine += "\r\n"; - line += itr->Identifier.c_str(); - line += "\t"; + QString idxLine = "// INDEX "; + idxLine += QString::number( idx ); + idxLine += "\r\n"; - line += "["; - line += itr->Text.toUtf8().c_str(); - line += "]"; + + QString trLine = ""; + trLine += itr->Identifier.c_str(); + trLine += "\t"; + trLine += "["; + trLine += itr->Text.toUtf8().c_str(); + trLine += "]"; + trLine += "\r\n"; - line += "\r\n"; + QString newLine = "\r\n"; - out << line; + out << hashLine; + out << idxLine; + out << trLine; + out << newLine; ++itr; + idx++; } f.close(); From 76d3e0df20505b1107e9cfbaae9706ea6afa28ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 19:52:23 +0200 Subject: [PATCH 151/282] Set header text according to the language. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 9f8cc56f4..dc453b57f 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -31,6 +31,27 @@ #include "nel/misc/diff_tool.h" #include "nel/misc/i18n.h" +namespace +{ + +QString getLang( const QString &fn ) +{ + QString lang = fn; + int idx = lang.lastIndexOf( '/' ); + if( idx == -1 ) + return ""; + + lang = lang.mid( idx + 1 ); + idx = lang.lastIndexOf( '.' ); + if( idx == -1 ) + return ""; + + lang = lang.left( idx ); + return lang; +} + +} + namespace TranslationManager { @@ -68,12 +89,30 @@ UXTEditor::~UXTEditor() void UXTEditor::open( QString filename ) { std::vector< STRING_MANAGER::TStringInfo > &infos = d_ptr->infos; + QString lang = getLang( filename ); infos.clear(); STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) - return; + { + // The work file cannot be found, cannot proceed + if( filename.endsWith( "wk.uxt" ) ) + { + return; + } + + int l = filename.lastIndexOf( "/" ); + if( l == -1 ) + return; + filename = filename.left( l ); + filename += "/wk.uxt"; + + // The work file cannot be found, cannot proceed + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + if( d_ptr->infos.size() == 0 ) + return; + } blockTableSignals( true ); @@ -81,7 +120,7 @@ void UXTEditor::open( QString filename ) d_ptr->t->setColumnCount( 2 ); d_ptr->t->setRowCount( infos.size() ); - setHeaderText( "Id", "Text" ); + setHeaderText( "Id", lang.toUpper() + " Text" ); int i = 0; From 0bd4b565898443aca4cb9cbac7e65e730e119935 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 20:03:16 +0200 Subject: [PATCH 152/282] Save to the right file. --HG-- branch : gsoc2014-dfighter --- .../translation_manager_main_window.cpp | 1 - .../src/plugins/translation_manager/uxt_editor.cpp | 12 ++++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index b439edce6..c5228fae6 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -573,7 +573,6 @@ void CMainWindow::onUxtMapped( QString lang ) UXTEditor *e = new UXTEditor(); e->open( path ); - e->setCurrentFile( path ); _ui.mdiArea->addSubWindow( e ); e->activateWindow(); } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index dc453b57f..38f8fa76d 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -105,11 +105,12 @@ void UXTEditor::open( QString filename ) int l = filename.lastIndexOf( "/" ); if( l == -1 ) return; - filename = filename.left( l ); - filename += "/wk.uxt"; + + QString fn = filename.left( l ); + fn += "/wk.uxt"; // The work file cannot be found, cannot proceed - STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) return; } @@ -144,7 +145,10 @@ void UXTEditor::open( QString filename ) blockTableSignals( false ); setWidget( d_ptr->t ); - setCurrentFile( filename ); + + current_file = filename; + setWindowTitle( filename + "[*]" ); + setWindowFilePath( filename ); } void UXTEditor::save() From 2fea6f45f56445ba0dfb09ab070e1e9615c5b9f1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 03:24:18 +0200 Subject: [PATCH 153/282] Make sure a correct hash is not used for untranslated strings. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 38f8fa76d..1ea22870d 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -62,10 +62,12 @@ public: UXTEditorPvt() { t = new QTableWidget(); + loadedFromWK = false; } QTableWidget *t; std::vector< STRING_MANAGER::TStringInfo > infos; + bool loadedFromWK; }; @@ -92,7 +94,7 @@ void UXTEditor::open( QString filename ) QString lang = getLang( filename ); infos.clear(); - STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, false ); if( d_ptr->infos.size() == 0 ) { @@ -113,6 +115,8 @@ void UXTEditor::open( QString filename ) STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) return; + + d_ptr->loadedFromWK = true; } blockTableSignals( true ); @@ -168,8 +172,25 @@ void UXTEditor::saveAs( QString filename ) std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); while( itr != d_ptr->infos.end() ) { + uint64 hash = 0; + + // If text2 is not empty we can assume the string was translated, so we store with the correct hash + // If text2 is empty, it wasn't translated so we can just use the old hash. + // Additionally, if the strings were loaded from the wk.uxt file, we use a hash of 0 so we know it was not translated + if( itr->Text2.empty() ) + { + if( d_ptr->loadedFromWK ) + hash = 0; + else + hash = itr->HashValue; + } + else + { + hash = NLMISC::CI18N::makeHash( itr->Text2 ); + } + QString hashLine = "// HASH_VALUE "; - hashLine += QString( NLMISC::CI18N::hashToString( itr->HashValue ).c_str() ).toUpper(); + hashLine += QString( NLMISC::CI18N::hashToString( hash ).c_str() ).toUpper(); hashLine += "\r\n"; QString idxLine = "// INDEX "; @@ -181,7 +202,12 @@ void UXTEditor::saveAs( QString filename ) trLine += itr->Identifier.c_str(); trLine += "\t"; trLine += "["; - trLine += itr->Text.toUtf8().c_str(); + + if( itr->Text2.empty() ) + trLine += itr->Text.toUtf8().c_str(); + else + trLine += itr->Text2.toUtf8().c_str(); + trLine += "]"; trLine += "\r\n"; @@ -282,7 +308,7 @@ void UXTEditor::onCellChanged( int row, int column ) info.Identifier = item->text().toUtf8().constData(); else if( column == 1 ) - info.Text = item->text().toUtf8().constData(); + info.Text2 = item->text().toUtf8().constData(); setWindowModified( true ); } From e92a07db33dc46af13976ba3c8ef70f53a8d7ba3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 03:51:03 +0200 Subject: [PATCH 154/282] New context menu options: mark / unmark translated. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 37 ++++++++++++++++++- .../plugins/translation_manager/uxt_editor.h | 2 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 1ea22870d..fcd6e74cf 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -290,12 +290,18 @@ void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) QMenu *menu = new QMenu( this ); QAction *insertAction = new QAction( "Insert row", menu ); QAction *deleteAction = new QAction( "Delete row", menu ); + QAction *markAction = new QAction( "Mark translated", menu ); + QAction *unmarkAction = new QAction( "Mark not-translated", menu ); connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); - connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + connect( markAction, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) ); + connect( unmarkAction, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) ); menu->addAction( insertAction ); menu->addAction( deleteAction ); + menu->addAction( markAction ); + menu->addAction( unmarkAction ); menu->exec( e->globalPos() ); } @@ -313,6 +319,35 @@ void UXTEditor::onCellChanged( int row, int column ) setWindowModified( true ); } +void UXTEditor::markTranslated() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; + if( !info.Text2.empty() ) + return; + + info.Text2 = info.Text; + + setWindowModified( true ); +} + +void UXTEditor::markUntranslated() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; + + info.Text2.clear(); + info.HashValue = 0; + + setWindowModified( true ); +} + void UXTEditor::setHeaderText( const QString &id, const QString &text ) { QTableWidgetItem *h1 = new QTableWidgetItem( id ); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 7499df44c..00716ee2f 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -47,6 +47,8 @@ protected: private Q_SLOTS: void onCellChanged( int row, int column ); + void markTranslated(); + void markUntranslated(); private: void setHeaderText( const QString &id, const QString &text ); From 26b120f664ed58ac6fd9ad8ac55239dd1786f5df Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 04:11:53 +0200 Subject: [PATCH 155/282] Mark translated item with green, untranslated ones with red. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 51 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 2 + 2 files changed, 53 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index fcd6e74cf..d6e7c5fa0 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -55,6 +55,16 @@ QString getLang( const QString &fn ) namespace TranslationManager { +void markItemTranslated( QTableWidgetItem *item ) +{ + item->setBackground( QColor::fromRgb( 126, 247, 134 ) ); +} + +void markItemUntranslated( QTableWidgetItem *item ) +{ + item->setBackground( QColor::fromRgb( 247, 126, 126 ) ); +} + class UXTEditorPvt { public: @@ -139,6 +149,17 @@ void UXTEditor::open( QString filename ) d_ptr->t->setItem( i, 0, name ); d_ptr->t->setItem( i, 1, text1 ); + + if( ( info.HashValue != 0 ) && !d_ptr->loadedFromWK ) + { + markItemTranslated( name ); + markItemTranslated( text1 ); + } + else + { + markItemUntranslated( name ); + markItemUntranslated( text1 ); + } ++itr; i++; @@ -317,6 +338,8 @@ void UXTEditor::onCellChanged( int row, int column ) info.Text2 = item->text().toUtf8().constData(); setWindowModified( true ); + + markRowTranslated( row ); } void UXTEditor::markTranslated() @@ -332,6 +355,8 @@ void UXTEditor::markTranslated() info.Text2 = info.Text; setWindowModified( true ); + + markRowTranslated( r ); } void UXTEditor::markUntranslated() @@ -346,6 +371,8 @@ void UXTEditor::markUntranslated() info.HashValue = 0; setWindowModified( true ); + + markRowUntranslated( r ); } void UXTEditor::setHeaderText( const QString &id, const QString &text ) @@ -366,4 +393,28 @@ void UXTEditor::blockTableSignals( bool block ) connect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); } +void UXTEditor::markRowTranslated( int row ) +{ + blockTableSignals( true ); + + QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); + QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); + markItemTranslated( item1 ); + markItemTranslated( item2 ); + + blockTableSignals( false ); +} + +void UXTEditor::markRowUntranslated( int row ) +{ + blockTableSignals( true ); + + QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); + QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); + markItemUntranslated( item1 ); + markItemUntranslated( item2 ); + + blockTableSignals( false ); +} + } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 00716ee2f..b0f977709 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -53,6 +53,8 @@ private Q_SLOTS: private: void setHeaderText( const QString &id, const QString &text ); void blockTableSignals( bool block = false ); + void markRowTranslated( int row ); + void markRowUntranslated( int row ); UXTEditorPvt *d_ptr; }; From ed44cc4823d5c629c367ab107af8c618c79366f0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 17:46:01 +0200 Subject: [PATCH 156/282] Shouldn't crash when adding a new row. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/translation_manager/uxt_editor.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index d6e7c5fa0..6c108b667 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -256,10 +256,22 @@ void UXTEditor::activateWindow() void UXTEditor::insertRow() { + blockTableSignals( true ); + d_ptr->infos.push_back( STRING_MANAGER::TStringInfo() ); d_ptr->t->setRowCount( d_ptr->t->rowCount() + 1 ); + int row = d_ptr->t->rowCount() - 1; + + QTableWidgetItem *item1 = new QTableWidgetItem(); + QTableWidgetItem *item2 = new QTableWidgetItem(); + d_ptr->t->setItem( row, 0, item1 ); + d_ptr->t->setItem( row, 1, item2 ); + + markRowUntranslated( row ); setWindowModified( true ); + + blockTableSignals( false ); } From 32172e0e77bee1ae5ea781602c050feeb7896745 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 23:08:05 +0200 Subject: [PATCH 157/282] Added save and save as items to the context menu. --HG-- branch : gsoc2014-dfighter --- .../translation_manager/uxt_editor.cpp | 32 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 6c108b667..b9548e0b5 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -325,16 +326,22 @@ void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) QAction *deleteAction = new QAction( "Delete row", menu ); QAction *markAction = new QAction( "Mark translated", menu ); QAction *unmarkAction = new QAction( "Mark not-translated", menu ); + QAction *saveAction = new QAction( "Save", menu ); + QAction *saveAsAction = new QAction( "Save as..", menu ); connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); connect( markAction, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) ); connect( unmarkAction, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) ); + connect( saveAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveClicked() ) ); + connect( saveAsAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAsClicked() ) ); menu->addAction( insertAction ); menu->addAction( deleteAction ); menu->addAction( markAction ); menu->addAction( unmarkAction ); + menu->addAction( saveAction ); + menu->addAction( saveAsAction ); menu->exec( e->globalPos() ); } @@ -387,6 +394,31 @@ void UXTEditor::markUntranslated() markRowUntranslated( r ); } +void UXTEditor::onSaveClicked() +{ + save(); +} + +void UXTEditor::onSaveAsClicked() +{ + QString path = current_file; + int idx = path.lastIndexOf( '/' ); + if( idx < 0 ) + path = ""; + else + path = path.left( idx + 1 ); + + QString file = QFileDialog::getSaveFileName( this, + tr( "Save Uxt as.." ), + path, + tr( "Uxt files ( *.uxt)" ) ); + + if( file.isEmpty() ) + return; + + saveAs( file ); +} + void UXTEditor::setHeaderText( const QString &id, const QString &text ) { QTableWidgetItem *h1 = new QTableWidgetItem( id ); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index b0f977709..b749e65e3 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -49,6 +49,8 @@ private Q_SLOTS: void onCellChanged( int row, int column ); void markTranslated(); void markUntranslated(); + void onSaveClicked(); + void onSaveAsClicked(); private: void setHeaderText( const QString &id, const QString &text ); From 3940e656e3d334842ef4269ac9fb972f768e3dc5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 23:25:35 +0200 Subject: [PATCH 158/282] Error message when files can't be opened. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/translation_manager/uxt_editor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index b9548e0b5..99b0b200c 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -112,6 +112,9 @@ void UXTEditor::open( QString filename ) // The work file cannot be found, cannot proceed if( filename.endsWith( "wk.uxt" ) ) { + QMessageBox::critical( this, + tr( "Error opening file.." ), + tr( "There was an error opening wk.uxt" ) ); return; } @@ -125,7 +128,12 @@ void UXTEditor::open( QString filename ) // The work file cannot be found, cannot proceed STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) + { + QMessageBox::critical( this, + tr( "Error opening Uxt file" ), + tr( "Neither the specified file nor wk.uxt could be opened." ) ); return; + } d_ptr->loadedFromWK = true; } From dcc072ba189093135b5cff89b24fea8c69ba90c0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 14:44:31 +0200 Subject: [PATCH 159/282] Update qrc location. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/tile_editor/tile_editor_main_window.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 66a086179..cfa6c4fa1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -309,7 +309,7 @@ - + :/newPrefix/reset.png:/newPrefix/reset.png @@ -789,7 +789,7 @@ - + From 4d6de3f737114238a1c3c9a86361e33954c94e45 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 15:35:14 +0200 Subject: [PATCH 160/282] Don't allow 2 tilesets to have the same name. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 14 ++++++-------- .../studio/src/plugins/tile_editor/tile_item.h | 2 +- .../src/plugins/tile_editor/tile_model.cpp | 18 ++++++++++++++++++ .../src/plugins/tile_editor/tile_model.h | 2 ++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index d1199ebc9..a4643f7a0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -226,15 +226,13 @@ void TileEditorMainWindow::onTileSetAdd() QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) { - //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) - //{ - // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); - //} - //else - //{ - - //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); TileModel *model = static_cast(m_ui->tileSetLV->model()); + + if( model->hasTileSet( text ) ) + { + QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); + return; + } //if(index.isValid()) //{ diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index f89b20ab7..75108c77e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -67,7 +67,7 @@ public: QVariant data(int column, int role) const; int columnCount() const; - const QString &getTileSetName(); + const QString &getTileSetName(){ return m_tileSetName; } private: QString m_tileSetName; }; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index c167dbd44..7c444606f 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -219,6 +219,24 @@ uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) return 0; } +bool TileModel::hasTileSet( const QString &name ) +{ + for( int i = 0; i < rowCount(); i++ ) + { + QModelIndex idx = index( i, 0 ); + if( !idx.isValid() ) + { + continue; + } + + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + if( n->getTileSetName() == name ) + return true; + } + + return false; +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index bd7d808fb..68d8cfeef 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -87,6 +87,8 @@ public: static TTileZoomFactor CurrentZoomFactor; + bool hasTileSet( const QString &name ); + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); From 5301b00e58abddc2fc52510c20d3c38367a7e56b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 15:38:26 +0200 Subject: [PATCH 161/282] Don't try to delete the same items more than once! --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_item.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 9d9418561..ef80cc302 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -35,6 +35,7 @@ Node::Node(const QVector &data, Node *parent) Node::~Node() { qDeleteAll(m_childItems); + m_childItems.clear(); } void Node::appendChild(Node *item) @@ -164,6 +165,7 @@ TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tile TileSetNode::~TileSetNode() { qDeleteAll(m_childItems); + m_childItems.clear(); } QVariant TileSetNode::data(int column, int role) const @@ -191,6 +193,7 @@ TileTypeNode::TileTypeNode(TileModel::TNodeTileType type, Node *parent) : m_node TileTypeNode::~TileTypeNode() { qDeleteAll(m_childItems); + m_childItems.clear(); } QVariant TileTypeNode::data(int column, int role) const From 71fc4a098b3498b3d997ce472883a32a59bbc2d6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Jul 2014 18:35:26 +0200 Subject: [PATCH 162/282] Implemented tileset removal. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 13 +++++++++++++ .../plugins/tile_editor/tile_editor_main_window.h | 1 + .../tile_editor/tile_editor_main_window.ui | 2 +- .../studio/src/plugins/tile_editor/tile_model.cpp | 15 +++++++++++++++ code/studio/src/plugins/tile_editor/tile_model.h | 2 ++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a4643f7a0..6656ba793 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -88,6 +88,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); + connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -261,6 +262,18 @@ void TileEditorMainWindow::onTileSetAdd() } } +void TileEditorMainWindow::onTileSetDelete() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + bool ok = model->removeRow( idx.row() ); + + //m_ui->tileSetLV->reset(); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 0effbe087..a4f2fe623 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -48,6 +48,7 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); + void onTileSetDelete(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index cfa6c4fa1..ef2061e38 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -505,7 +505,7 @@ - + ... diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 7c444606f..a5527fb56 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -140,6 +140,21 @@ void TileModel::appendRow(Node *item) rootItem->appendRow(item); } +bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) +{ + int c = rootItem->childCount(); + if( row + count > c ) + return false; + + beginRemoveRows( QModelIndex(), row, row + count - 1 ); + + bool ok = rootItem->removeChildren( row, count ); + + endRemoveRows(); + + return ok; +} + TileSetNode *TileModel::createTileSetNode(QString tileSetName) { // Create the new tile set. diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 68d8cfeef..cdf85acc3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -80,6 +80,8 @@ public: void appendRow(const QList &items); void appendRow(Node *item); + bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ); + TileSetNode *createTileSetNode(QString tileSetName); static const char *getTileTypeName(TNodeTileType type); From 9d1fec6ce19bec727ff352928cbef17554562693 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Jul 2014 21:53:09 +0200 Subject: [PATCH 163/282] Implemented tileset rename. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 35 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + .../tile_editor/tile_editor_main_window.ui | 2 +- .../src/plugins/tile_editor/tile_item.h | 2 ++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 6656ba793..8ab499bf8 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -89,6 +89,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); + connect(m_ui->tileSetEditTB, SIGNAL(clicked()), this, SLOT(onTileSetEdit())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -274,6 +275,40 @@ void TileEditorMainWindow::onTileSetDelete() //m_ui->tileSetLV->reset(); } +void TileEditorMainWindow::onTileSetEdit() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + QString name = node->getTileSetName(); + + bool ok = false; + + QString newName = QInputDialog::getText( this, + tr( "Edit tileset" ), + tr( "Enter tileset name" ), + QLineEdit::Normal, + name, + &ok ); + + if( !ok ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + if( model->hasTileSet( newName ) ) + { + QMessageBox::information( this, + tr("Tileset already exists"), + tr("A tileset with that name already exists!") ); + return; + } + + node->setTileSetName( newName ); + m_ui->tileSetLV->reset(); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index a4f2fe623..8719f799a 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -49,6 +49,7 @@ public Q_SLOTS: void onActionDeleteImage(bool triggered); void onTileSetAdd(); void onTileSetDelete(); + void onTileSetEdit(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index ef2061e38..a88c11d0e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -516,7 +516,7 @@ - + ... diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 75108c77e..69fc89d71 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -68,6 +68,8 @@ public: int columnCount() const; const QString &getTileSetName(){ return m_tileSetName; } + void setTileSetName( const QString &name ){ m_tileSetName = name; } + private: QString m_tileSetName; }; From c7ca20c748a69f8a11287af3b36cadc16846d55b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 02:28:19 +0200 Subject: [PATCH 164/282] Implemented tileset move up and move down. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 62 +++++++++++++------ .../tile_editor/tile_editor_main_window.h | 2 + .../tile_editor/tile_editor_main_window.ui | 4 +- .../src/plugins/tile_editor/tile_item.cpp | 7 +++ .../src/plugins/tile_editor/tile_item.h | 2 + .../src/plugins/tile_editor/tile_model.cpp | 5 ++ .../src/plugins/tile_editor/tile_model.h | 2 + 7 files changed, 63 insertions(+), 21 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 8ab499bf8..88090de47 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -87,9 +87,13 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Set up the tile set list view. m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); + connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); connect(m_ui->tileSetEditTB, SIGNAL(clicked()), this, SLOT(onTileSetEdit())); + connect(m_ui->tileSetUpTB, SIGNAL(clicked()), this, SLOT(onTileSetUp())); + connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); + connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -236,23 +240,6 @@ void TileEditorMainWindow::onTileSetAdd() return; } - //if(index.isValid()) - //{ - // if(!model->insertRow(index.row()+1, index.parent())) - // return; - - // //updateActions() - - // for(int column=0; columncolumnCount(index.parent()); column++) - // { - // QModelIndex child = model->index(index.row()+1, column, index.parent()); - // model->setData(child, QVariant(text), Qt::EditRole); - // } - //} - //else - //{ - - // Create and append the new tile set to the model. TileSetNode *tileSet = model->createTileSetNode(text); @@ -271,8 +258,6 @@ void TileEditorMainWindow::onTileSetDelete() TileModel *model = static_cast(m_ui->tileSetLV->model()); bool ok = model->removeRow( idx.row() ); - - //m_ui->tileSetLV->reset(); } void TileEditorMainWindow::onTileSetEdit() @@ -309,6 +294,45 @@ void TileEditorMainWindow::onTileSetEdit() m_ui->tileSetLV->reset(); } +void TileEditorMainWindow::onTileSetUp() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + if( idx.row() == 0 ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + if( model->rowCount() < 2 ) + return; + + int r = idx.row(); + model->swapRows( r, r - 1 ); + + m_ui->tileSetLV->reset(); + m_ui->tileSetLV->setCurrentIndex( model->index( r - 1, 0 ) ); +} + +void TileEditorMainWindow::onTileSetDown() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + if( model->rowCount() < idx.row() ) + return; + if( model->rowCount() < 2 ) + return; + + int r = idx.row(); + model->swapRows( r, r + 1 ); + + m_ui->tileSetLV->reset(); + m_ui->tileSetLV->setCurrentIndex( model->index( r + 1, 0 ) ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 8719f799a..c830666a0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -50,6 +50,8 @@ public Q_SLOTS: void onTileSetAdd(); void onTileSetDelete(); void onTileSetEdit(); + void onTileSetUp(); + void onTileSetDown(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index a88c11d0e..f90ac69fb 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -442,7 +442,7 @@ - + ... @@ -453,7 +453,7 @@ - + ... diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index ef80cc302..230776fbd 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -155,6 +155,13 @@ void Node::appendRow(Node *item) m_childItems.append(item); } +void Node::swapRows( int a, int b ) +{ + Node *temp = m_childItems[ a ]; + m_childItems[ a ] = m_childItems[ b ]; + m_childItems[ b ] = temp; +} + /////////////////////////////////////////////////// TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 69fc89d71..56adfa926 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -53,6 +53,8 @@ public: void appendRow(const QList &items); void appendRow(Node *item); + void swapRows( int a, int b ); + protected: QList m_childItems; QVector m_itemData; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index a5527fb56..4b6d2113d 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -155,6 +155,11 @@ bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) return ok; } +void TileModel::swapRows( int a, int b ) +{ + rootItem->swapRows( a, b ); +} + TileSetNode *TileModel::createTileSetNode(QString tileSetName) { // Create the new tile set. diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index cdf85acc3..239c423cb 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -82,6 +82,8 @@ public: bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ); + void swapRows( int a, int b ); + TileSetNode *createTileSetNode(QString tileSetName); static const char *getTileTypeName(TNodeTileType type); From e9e42701b94e223c2132c11dd007e91117db242b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:09:58 +0200 Subject: [PATCH 165/282] Renamed land related widgets. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.ui | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index f90ac69fb..07fbf08aa 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -352,7 +352,7 @@ - + @@ -370,7 +370,7 @@ - + ... @@ -381,7 +381,7 @@ - + ... @@ -392,7 +392,7 @@ - + ... From 02ccd3b1c16d63ce15ea617176e04810fa502f0c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:18:01 +0200 Subject: [PATCH 166/282] Implemented land adding. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 26 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 4 +++ 2 files changed, 30 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 88090de47..1a7dc164b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -94,6 +94,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->tileSetUpTB, SIGNAL(clicked()), this, SLOT(onTileSetUp())); connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); + connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); + connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -333,6 +335,30 @@ void TileEditorMainWindow::onTileSetDown() m_ui->tileSetLV->setCurrentIndex( model->index( r + 1, 0 ) ); } +void TileEditorMainWindow::onLandAdd() +{ + QString name = QInputDialog::getText( this, + tr("Adding new land"), + tr("Please specify the new land's name") ); + + if( name.isEmpty() ) + return; + + for( int i = 0; i < m_ui->landLW->count(); i++ ) + { + QListWidgetItem *item = m_ui->landLW->item( i ); + if( item->text() == name ) + { + QMessageBox::information( this, + tr( "Error adding new land" ), + tr( "A land with that name already exists." ) ); + return; + } + } + + m_ui->landLW->addItem( name ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index c830666a0..6d1aa82c7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -47,11 +47,15 @@ public Q_SLOTS: void onActionDeleteTile(bool triggered); void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); + void onTileSetAdd(); void onTileSetDelete(); void onTileSetEdit(); void onTileSetUp(); void onTileSetDown(); + + void onLandAdd(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); From 9519c4f0f5c5114e3c738ecb69c59070167319a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:20:44 +0200 Subject: [PATCH 167/282] Implemented land removal. --HG-- branch : gsoc2014-dfighter --- .../plugins/tile_editor/tile_editor_main_window.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 11 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 1a7dc164b..26f92b6ae 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -95,6 +95,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); + connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), @@ -359,6 +360,15 @@ void TileEditorMainWindow::onLandAdd() m_ui->landLW->addItem( name ); } +void TileEditorMainWindow::onLandRemove() +{ + QListWidgetItem *item = m_ui->landLW->currentItem(); + if( item == NULL ) + return; + + delete item; +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 6d1aa82c7..cc7312b7d 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -55,6 +55,7 @@ public Q_SLOTS: void onTileSetDown(); void onLandAdd(); + void onLandRemove(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); From 947782a2c57a5fc37e0f8d76344907685a16e07d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:25:28 +0200 Subject: [PATCH 168/282] Implemented land name changing. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 22 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 23 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 26f92b6ae..11f5d79b0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -96,6 +96,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); + connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), @@ -369,6 +370,27 @@ void TileEditorMainWindow::onLandRemove() delete item; } +void TileEditorMainWindow::onLandEdit() +{ + QListWidgetItem *item = m_ui->landLW->currentItem(); + if( item == NULL ) + return; + + QString name = item->text(); + + QString newName = QInputDialog::getText( this, + tr( "Editing land" ), + tr( "Please specify the new name of the selected land" ), + QLineEdit::Normal, + name ); + + if( newName.isEmpty() ) + return; + if( newName == name ) + return; + item->setText( newName ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index cc7312b7d..31e65df27 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -56,6 +56,7 @@ public Q_SLOTS: void onLandAdd(); void onLandRemove(); + void onLandEdit(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); From 9b403212c04bdc085b5a0e8ff812862878ee1e38 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:31:07 +0200 Subject: [PATCH 169/282] Each land has it's own TilesetModel now. When changing the land the model also changes. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 88 ++++++++++++++++--- .../tile_editor/tile_editor_main_window.h | 6 +- .../src/plugins/tile_editor/tile_model.h | 3 +- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 11f5d79b0..2f3127c8e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -79,13 +79,10 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) core->menuManager()->menuBar()->addMenu(m_tileEditorMenu); // Set up the list views. - QStringList headers; - headers << "Tile Set"; - m_model = new TileModel(headers, this); m_tileItemDelegate = new TileItemDelegate(); // Set up the tile set list view. - m_ui->tileSetLV->setModel(m_model); + //m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); @@ -97,6 +94,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); + connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), @@ -104,7 +102,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); - m_ui->listView128->setModel(m_model); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); m_ui->listView128->addAction(m_ui->actionReplaceImage); @@ -112,7 +109,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // 256x256 List View //m_ui->listView256->setItemDelegate(m_tileItemDelegate); - m_ui->listView256->setModel(m_model); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); m_ui->listView256->addAction(m_ui->actionReplaceImage); @@ -120,13 +116,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Transition List View //m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); - m_ui->listViewTransition->setModel(m_model); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View //m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); - m_ui->listViewDisplacement->setModel(m_model); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -137,9 +131,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); - connect(m_ui->actionTileDisplayFilename, SIGNAL(toggled(bool)), m_model, SLOT(selectFilenameDisplay(bool))); - connect(m_ui->actionTileDisplayIndex, SIGNAL(toggled(bool)), m_model, SLOT(selectIndexDisplay(bool))); - //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); // Connect the zoom buttons. @@ -164,6 +155,9 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_zoomMenu; delete m_zoomActionGroup; delete m_zoomSignalMapper; + + qDeleteAll( m_tileModels ); + m_tileModels.clear(); } void TileEditorMainWindow::onZoomFactor(int level) @@ -232,6 +226,14 @@ void TileEditorMainWindow::onActionDeleteImage(bool triggered) void TileEditorMainWindow::onTileSetAdd() { + if( m_ui->landLW->count() == 0 ) + { + QMessageBox::information( this, + tr( "Error adding tile set" ), + tr( "You need to add a land before adding a tileset!" ) ); + return; + } + bool ok; QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) @@ -260,6 +262,14 @@ void TileEditorMainWindow::onTileSetDelete() if( !idx.isValid() ) return; + int reply = QMessageBox::question( this, + tr( "Removing tile set" ), + tr( "Are you sure you want to remove this tile set?" ), + QMessageBox::Yes | QMessageBox::Cancel ); + + if( reply != QMessageBox::Yes ) + return; + TileModel *model = static_cast(m_ui->tileSetLV->model()); bool ok = model->removeRow( idx.row() ); } @@ -359,6 +369,13 @@ void TileEditorMainWindow::onLandAdd() } m_ui->landLW->addItem( name ); + + TileModel *m = createTileModel(); + + m_tileModels.push_back( m ); + + if( m_tileModels.count() == 1 ) + m_ui->landLW->setCurrentRow( 0 ); } void TileEditorMainWindow::onLandRemove() @@ -367,6 +384,21 @@ void TileEditorMainWindow::onLandRemove() if( item == NULL ) return; + int idx = m_ui->landLW->currentRow(); + + int reply = QMessageBox::question( this, + tr( "Removing land" ), + tr( "Are you sure you want to remove this land?" ), + QMessageBox::Yes | QMessageBox::Cancel ); + + if( reply != QMessageBox::Yes ) + return; + + QList< TileModel* >::iterator itr = m_tileModels.begin() + idx; + delete m_tileModels[ idx ]; + m_tileModels[ idx ] = NULL; + m_tileModels.erase( itr ); + delete item; } @@ -391,6 +423,28 @@ void TileEditorMainWindow::onLandEdit() item->setText( newName ); } +void TileEditorMainWindow::onLandRowChanged( int row ) +{ + if( row == -1 ) + { + m_ui->tileSetLV->setModel( NULL ); + m_ui->listView128->setModel( NULL ); + m_ui->listView256->setModel( NULL ); + m_ui->listViewTransition->setModel( NULL ); + m_ui->listViewDisplacement->setModel( NULL ); + } + else + { + m_ui->tileSetLV->setModel( m_tileModels[ row ] ); + m_ui->listView128->setModel( m_tileModels[ row ] ); + m_ui->listView256->setModel( m_tileModels[ row ] ); + m_ui->listViewTransition->setModel( m_tileModels[ row ] ); + m_ui->listViewDisplacement->setModel( m_tileModels[ row ] ); + } + + m_ui->tileSetLV->reset(); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; @@ -398,6 +452,18 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); } +TileModel* TileEditorMainWindow::createTileModel() +{ + QStringList headers; + headers << "Tile Set"; + TileModel *m = new TileModel( headers ); + + connect( m_ui->actionTileDisplayFilename, SIGNAL( toggled( bool )), m, SLOT( selectFilenameDisplay( bool ) ) ); + connect( m_ui->actionTileDisplayIndex, SIGNAL( toggled( bool )), m, SLOT( selectIndexDisplay( bool ) ) ); + + return m; +} + void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { TileModel *model = static_cast(m_ui->tileSetLV->model()); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 31e65df27..58f546ea9 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -57,6 +57,7 @@ public Q_SLOTS: void onLandAdd(); void onLandRemove(); void onLandEdit(); + void onLandRowChanged( int row ); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); @@ -64,6 +65,8 @@ public Q_SLOTS: private: void onActionAddTile(int tabId); + TileModel* createTileModel(); + Ui::TileEditorMainWindow *m_ui; QUndoStack *m_undoStack; QMenu *m_rotationMenu; @@ -75,8 +78,9 @@ private: QActionGroup *m_zoomActionGroup; QSignalMapper *m_zoomSignalMapper; - TileModel *m_model; TileItemDelegate *m_tileItemDelegate; + + QList< TileModel* > m_tileModels; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 239c423cb..e2be8da57 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -64,8 +64,7 @@ public: static const int TILE_128_BASE_SIZE = 128; static const int TILE_256_BASE_SIZE = 256; - - TileModel(const QStringList &headers, QObject *parent); + TileModel(const QStringList &headers, QObject *parent = NULL); ~TileModel(); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; From f66c1e837e5383439e7d344b86ca92a76419e762 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:39:34 +0200 Subject: [PATCH 170/282] Connect the selection model so the widgets are updated. --HG-- branch : gsoc2014-dfighter --- .../plugins/tile_editor/tile_editor_main_window.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 2f3127c8e..dbd9d6407 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -96,10 +96,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); - connect(m_ui->tileSetLV->selectionModel(), - SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); - // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->addAction(m_ui->actionAddTile); @@ -427,6 +423,9 @@ void TileEditorMainWindow::onLandRowChanged( int row ) { if( row == -1 ) { + disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + m_ui->tileSetLV->setModel( NULL ); m_ui->listView128->setModel( NULL ); m_ui->listView256->setModel( NULL ); @@ -435,11 +434,17 @@ void TileEditorMainWindow::onLandRowChanged( int row ) } else { + //disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + // this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + m_ui->tileSetLV->setModel( m_tileModels[ row ] ); m_ui->listView128->setModel( m_tileModels[ row ] ); m_ui->listView256->setModel( m_tileModels[ row ] ); m_ui->listViewTransition->setModel( m_tileModels[ row ] ); m_ui->listViewDisplacement->setModel( m_tileModels[ row ] ); + + connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); } m_ui->tileSetLV->reset(); From 2993c88a5d3b6056f894149305805142340ccf23 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:44:00 +0200 Subject: [PATCH 171/282] When selecting another land, select the first tile set, if it exists. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index dbd9d6407..5e3127d51 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -445,6 +445,12 @@ void TileEditorMainWindow::onLandRowChanged( int row ) connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + + if( m_ui->tileSetLV->model()->rowCount() != 0 ) + { + QModelIndex idx = m_ui->tileSetLV->model()->index( 0, 0 ); + m_ui->tileSetLV->setCurrentIndex( idx ); + } } m_ui->tileSetLV->reset(); From df7307583b46383f51ad1d8e9924be9329c0d06e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 23:31:37 +0200 Subject: [PATCH 172/282] Implemented choosing / resetting vegetset for tile sets. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 68 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 3 + .../tile_editor/tile_editor_main_window.ui | 4 +- .../src/plugins/tile_editor/tile_item.h | 4 ++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 5e3127d51..40b3b8dfc 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -96,6 +96,9 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); + connect(m_ui->chooseVegetPushButton, SIGNAL(clicked()), this, SLOT(onChooseVegetation())); + connect(m_ui->resetVegetPushButton, SIGNAL(clicked()), this, SLOT(onResetVegetation())); + // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->addAction(m_ui->actionAddTile); @@ -421,6 +424,8 @@ void TileEditorMainWindow::onLandEdit() void TileEditorMainWindow::onLandRowChanged( int row ) { + m_ui->chooseVegetPushButton->setText( "..." ); + if( row == -1 ) { disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), @@ -456,6 +461,47 @@ void TileEditorMainWindow::onLandRowChanged( int row ) m_ui->tileSetLV->reset(); } +void TileEditorMainWindow::onChooseVegetation() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr("Choosing a vegetation set"), + tr("You need to select a tileset before choosing a vegetation set!") ); + return; + } + + QString vegetSet = QFileDialog::getOpenFileName( this, + tr( "Choose vegetation set" ), + "", + tr( "Nel vegetset files (*.vegetset)" ) ); + + if( vegetSet.isEmpty() ) + return; + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + node->setVegetSet( vegetSet ); + + m_ui->chooseVegetPushButton->setText( vegetSet ); +} + +void TileEditorMainWindow::onResetVegetation() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr("Resetting a vegetation set"), + tr("You need to select a tileset before resetting a vegetation set!") ); + return; + } + m_ui->chooseVegetPushButton->setText( "..." ); + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + node->setVegetSet( "" ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; @@ -493,6 +539,28 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->listViewDisplacement->setRootIndex(tileDispIdx); m_ui->listViewDisplacement->setCurrentIndex(m_ui->listViewDisplacement->model()->index(0, 0, m_ui->listViewDisplacement->rootIndex())); + TileSetNode *oldNode = NULL; + TileSetNode *newNode = NULL; + + if( oldIndex.isValid() ) + oldNode = reinterpret_cast< TileSetNode* >( oldIndex.internalPointer() ); + if( newIndex.isValid() ) + newNode = reinterpret_cast< TileSetNode* >( newIndex.internalPointer() ); + + if( newNode != NULL ) + { + QString vegetSet = newNode->vegetSet(); + + if( !vegetSet.isEmpty() ) + m_ui->chooseVegetPushButton->setText( vegetSet ); + else + m_ui->chooseVegetPushButton->setText( "..." ); + } + else + { + m_ui->chooseVegetPushButton->setText( "..." ); + } + //nlinfo("number of rows in displacement: %d", tileDispIdx.model()->rowCount(tileDispIdx)); //m_ui->listView128->reset(); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 58f546ea9..de7f1d0d0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -59,6 +59,9 @@ public Q_SLOTS: void onLandEdit(); void onLandRowChanged( int row ); + void onResetVegetation(); + void onChooseVegetation(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 07fbf08aa..387d0f23e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -18,7 +18,7 @@ - 2 + 4 @@ -306,7 +306,7 @@ - + Reset diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 56adfa926..e99effc62 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -72,8 +72,12 @@ public: const QString &getTileSetName(){ return m_tileSetName; } void setTileSetName( const QString &name ){ m_tileSetName = name; } + void setVegetSet( const QString &s ){ m_vegetSet = s; } + QString vegetSet() const{ return m_vegetSet; } + private: QString m_tileSetName; + QString m_vegetSet; }; class TileTypeNode : public Node From 78f465406372cef8014dbe2df15017f73d7cfcbb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 23:41:42 +0200 Subject: [PATCH 173/282] Implemented tilebank texture path setting. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 23 ++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 4 +++ .../tile_editor/tile_editor_main_window.ui | 27 +++++++------------ 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 40b3b8dfc..7b255ce2d 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -99,6 +99,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->chooseVegetPushButton, SIGNAL(clicked()), this, SLOT(onChooseVegetation())); connect(m_ui->resetVegetPushButton, SIGNAL(clicked()), this, SLOT(onResetVegetation())); + connect(m_ui->tileBankTexturePathPB, SIGNAL(clicked()), this, SLOT(onChooseTexturePath())); + // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->addAction(m_ui->actionAddTile); @@ -502,6 +504,27 @@ void TileEditorMainWindow::onResetVegetation() node->setVegetSet( "" ); } +void TileEditorMainWindow::onChooseTexturePath() +{ + QString path = QFileDialog::getExistingDirectory( this, + tr("Choose tilebank absolute texture path "), + "" ); + + if( path.isEmpty() ) + return; + + int reply = QMessageBox::question( this, + tr("tilebank texture path"), + tr("Are you sure you want to make '%1' the tilebank absolute texture path?").arg( path ), + QMessageBox::Yes | QMessageBox::Cancel ); + + if( reply != QMessageBox::Yes ) + return; + + m_texturePath = path; + m_ui->tileBankTexturePathPB->setText( path ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index de7f1d0d0..a66d6d993 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -62,6 +62,8 @@ public Q_SLOTS: void onResetVegetation(); void onChooseVegetation(); + void onChooseTexturePath(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); @@ -84,6 +86,8 @@ private: TileItemDelegate *m_tileItemDelegate; QList< TileModel* > m_tileModels; + + QString m_texturePath; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 387d0f23e..4297b4848 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -541,6 +541,16 @@ + + + + Tile Bank Texture Path + + + + + + @@ -550,25 +560,8 @@ - - - - ... - - - - - - - Tile Bank Texture Path - - - - - - From 3b3a595903407cc3a1e00b6a4a7e3e817f8d5935 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Sat, 26 Jul 2014 00:27:57 +0530 Subject: [PATCH 174/282] bug fix: added template path option in .info file --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/autoload/plugincache.php | 39 ++++++++++--------- .../www/html/templates/layout_admin.tpl | 2 +- .../www/html/templates/layout_mod.tpl | 1 + .../www/html/templates/layout_plugin.tpl | 4 +- .../www/html/templates/layout_user.tpl | 2 +- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php index ae8f1129c..c90665bc1 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/plugincache.php @@ -1,8 +1,8 @@ - $value ) { $plugin_path = Plugincache :: pluginInfoUsingId( $value['Id'], 'FileName' ); - $pluginName = Plugincache :: pluginInfoUsingId( $value['Id'], 'Name' ); + $template_path = json_decode( Plugincache :: pluginInfoUsingId( $value['Id'], 'Info' ) ) -> TemplatePath; + $plugin_name = explode( '/', $plugin_path )[4]; // calling hooks in the $pluginName.php - include $plugin_path . '/' . strtolower( $pluginName ) . '.php'; + include $plugin_path . '/' . $plugin_name . '.php'; $arr = get_defined_functions(); foreach( $arr['user'] as $key => $value ) { - if ( stristr( $value, strtolower( $pluginName ) ) == true ) + if ( stristr( $value, $plugin_name ) == true ) { - $content['hook_info'][$pluginName] = call_user_func( $value ); + $content['hook_info'][$plugin_name] = call_user_func( $value ); } } - } + // path for the template + $content['hook_info'][$plugin_name]['TemplatePath'] = $template_path; + } + return $content; } - } + } diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl index a0d1e49ef..db83dc8be 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl @@ -10,7 +10,7 @@
  • Support Groups
  • Plugins
  • - {if isset($hook_info)} {foreach from=$hook_info item=element}
  • {$element.menu_display}
  • {/foreach}{/if} + {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Syncing
  • Logout
  • {/block} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl index e0a77d99a..cffdfdb5a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl @@ -6,6 +6,7 @@
  • Settings
  • Users
  • + {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Queues
  • Support Groups
  • diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl index 5bc5938c4..9fb68400a 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl @@ -1,8 +1,8 @@ {block name=content}
    {if isset($hook_info)} -{foreach from=$hook_info item=element} -{if $element.menu_display eq $smarty.get.name} +{foreach from=$hook_info key=arrkey item=element} +{if $arrkey eq $smarty.get.name} {include file=$element.template_path} {/if} {/foreach} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl index 4b452962a..57aad4c8b 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl @@ -5,7 +5,7 @@
  • Settings
  • Create New Ticket
  • - {if isset($hook_info)} {foreach from=$hook_info item=element}
  • {$element.menu_display}
  • {/foreach}{/if} + {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Logout
  • {/block} From d2a414edb41dd70646e60f20e9c58487e5fbce96 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 00:29:37 +0200 Subject: [PATCH 175/282] Implemented Tile addition. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 54 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 12 ++++- .../src/plugins/tile_editor/tile_model.cpp | 5 ++ .../src/plugins/tile_editor/tile_model.h | 1 + 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 7b255ce2d..1ad0e8a45 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -527,9 +527,63 @@ void TileEditorMainWindow::onChooseTexturePath() void TileEditorMainWindow::onActionAddTile(int tabId) { + int land = m_ui->landLW->currentRow(); + if( land == -1 ) + { + QMessageBox::information( this, + tr( "Adding new tile" ), + tr( "You need to have a land and a tileset selected before you can add tiles!" ) ); + return; + } + + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Adding new tiles" ), + tr( "You need to have a tileset selected before you can add tiles!" ) ); + return; + } + + int tileSet = idx.row(); + + TileModel *model = static_cast< TileModel* >( m_tileModels[ land ] ); + idx = model->index( tileSet, 0 ); + if( !idx.isValid() ) + return; + + TileSetNode *tsn = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + + int tabIdx = m_ui->tileViewTabWidget->currentIndex(); + Node *n = tsn->child( tabIdx ); + QFileDialog::Options options; QString selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); + + int c = n->childCount(); + + QStringListIterator itr( fileNames ); + while( itr.hasNext() ) + { + Node *newNode = TileModel::createItemNode( c, TileModel::TileDiffuse, itr.next() ); + n->appendRow( newNode ); + c++; + } + + QModelIndex rootIdx = model->index( tabIdx, 0, m_ui->tileSetLV->currentIndex()); + + QListView *lv = NULL; + + switch( tabIdx ) + { + case TAB_128: lv = m_ui->listView128; break; + case TAB_256: lv = m_ui->listView256; break; + } + + lv->reset(); + lv->setRootIndex( rootIdx ); + lv->setCurrentIndex( lv->model()->index( 0, 0, rootIdx ) ); } TileModel* TileEditorMainWindow::createTileModel() diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index a66d6d993..9dff9fc3e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -42,7 +42,7 @@ public: QUndoStack *getUndoStack() { return m_undoStack; } -public Q_SLOTS: +private Q_SLOTS: void onActionAddTile(bool triggered); void onActionDeleteTile(bool triggered); void onActionReplaceImage(bool triggered); @@ -69,7 +69,6 @@ public Q_SLOTS: private: void onActionAddTile(int tabId); - TileModel* createTileModel(); Ui::TileEditorMainWindow *m_ui; @@ -88,6 +87,15 @@ private: QList< TileModel* > m_tileModels; QString m_texturePath; + + enum Tabs + { + TAB_128 = 0, + TAB_256 = 1, + TAB_TRANSITION = 2, + TAB_DISPLACEMENT = 3, + TAB_DETAILS = 4 + }; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 4b6d2113d..d7ead6ac3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -203,6 +203,11 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) return tileSet; } +Node *TileModel::createItemNode( int id, TTileChannel channel, const QString &fileName ) +{ + return new TileItemNode( id, channel, fileName ); +} + const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) { switch(type) diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index e2be8da57..56d7b792b 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -84,6 +84,7 @@ public: void swapRows( int a, int b ); TileSetNode *createTileSetNode(QString tileSetName); + static Node *createItemNode( int id, TTileChannel channel, const QString &fileName ); static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); From d31dfdb6e4c21199dcd12b8e4454205b42ce716d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 00:32:42 +0200 Subject: [PATCH 176/282] I must be blind... --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 1ad0e8a45..a0397fbda 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -554,8 +554,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) TileSetNode *tsn = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - int tabIdx = m_ui->tileViewTabWidget->currentIndex(); - Node *n = tsn->child( tabIdx ); + Node *n = tsn->child( tabId ); QFileDialog::Options options; QString selectedFilter; @@ -571,11 +570,11 @@ void TileEditorMainWindow::onActionAddTile(int tabId) c++; } - QModelIndex rootIdx = model->index( tabIdx, 0, m_ui->tileSetLV->currentIndex()); + QModelIndex rootIdx = model->index( tabId, 0, m_ui->tileSetLV->currentIndex()); QListView *lv = NULL; - switch( tabIdx ) + switch( tabId ) { case TAB_128: lv = m_ui->listView128; break; case TAB_256: lv = m_ui->listView256; break; From f0a67d0c2e648e92328d1a73b8fdfa7f8583f028 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 01:57:50 +0200 Subject: [PATCH 177/282] Implemented tile deletion. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 27 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + .../src/plugins/tile_editor/tile_item.h | 2 +- .../src/plugins/tile_editor/tile_model.cpp | 16 ++++++++--- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a0397fbda..25406e389 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -215,6 +215,7 @@ void TileEditorMainWindow::onActionAddTile(bool triggered) void TileEditorMainWindow::onActionDeleteTile(bool triggered) { + onActionDeleteTile(m_ui->tileViewTabWidget->currentIndex()); } void TileEditorMainWindow::onActionReplaceImage(bool triggered) @@ -585,6 +586,32 @@ void TileEditorMainWindow::onActionAddTile(int tabId) lv->setCurrentIndex( lv->model()->index( 0, 0, rootIdx ) ); } +void TileEditorMainWindow::onActionDeleteTile( int tabId ) +{ + QListView *lv = NULL; + switch( tabId ) + { + case TAB_128: lv = m_ui->listView128; break; + case TAB_256: lv = m_ui->listView256; break; + } + + QModelIndex idx = lv->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Deleting a tile" ), + tr( "You need to select a tile to delete is!" ) ); + return; + } + + int row = idx.row(); + + QModelIndex parent = idx.parent(); + lv->model()->removeRow( row, parent ); + + //lv->reset(); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 9dff9fc3e..f839e7c32 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -69,6 +69,7 @@ private Q_SLOTS: private: void onActionAddTile(int tabId); + void onActionDeleteTile(int tabId); TileModel* createTileModel(); Ui::TileEditorMainWindow *m_ui; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index e99effc62..5331ef081 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -43,7 +43,7 @@ public: virtual QVariant data(int column, int role) const; bool insertChildren(int position, int count, int columns); - bool removeChildren(int position, int count); + virtual bool removeChildren(int position, int count); bool insertColumns(int position, int columns); int row() const; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d7ead6ac3..d68650b8f 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -142,13 +142,23 @@ void TileModel::appendRow(Node *item) bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) { - int c = rootItem->childCount(); + Node *parentNode = NULL; + + if( !parent.isValid() ) + parentNode = rootItem; + else + parentNode = getItem( parent ); + + if( parentNode == NULL ) + return false; + + int c = parentNode->childCount(); if( row + count > c ) return false; - beginRemoveRows( QModelIndex(), row, row + count - 1 ); + beginRemoveRows( parent, row, row + count - 1 ); - bool ok = rootItem->removeChildren( row, count ); + bool ok = parentNode->removeChildren( row, count ); endRemoveRows(); From e06858f2dfb84f4c4364354dda23dce944437339 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:05:21 +0200 Subject: [PATCH 178/282] Reindex tile item nodes after deleting a node. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_item.cpp | 26 +++++++++++++++++++ .../src/plugins/tile_editor/tile_item.h | 6 +++++ 2 files changed, 32 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 230776fbd..e228a6745 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -224,7 +224,33 @@ TileModel::TNodeTileType TileTypeNode::getTileType() return m_nodeTileType; } +bool TileTypeNode::removeChildren( int position, int count ) +{ + bool ok = Node::removeChildren( position, count ); + if( !ok ) + return false; + reindex(); + + return true; +} + +void TileTypeNode::reindex() +{ + int i = 0; + + QListIterator< Node* > itr( m_childItems ); + while( itr.hasNext() ) + { + TileItemNode *n = dynamic_cast< TileItemNode* >( itr.next() ); + if( n == NULL ) + continue; + + n->setId( i ); + + i++; + } +} /////////////////////////////////////////////////// diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 5331ef081..f232acb4b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -90,7 +90,11 @@ public: int columnCount() const; TileModel::TNodeTileType getTileType(); + + bool removeChildren( int position, int count ); + private: + void reindex(); TileModel::TNodeTileType m_nodeTileType; }; @@ -102,6 +106,8 @@ public: QVariant data(int column, int role) const; int columnCount() const; void setTileFilename(TileModel::TTileChannel channel, QString filename); + void setId( int id ){ m_tileId = id; } + int id() const{ return m_tileId; } private: int m_tileId; QMap m_tileFilename; From 599ba19de21e6a944fc94606f1c64f1a80897c14 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:11:02 +0200 Subject: [PATCH 179/282] A little refactoring. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 33 +++++++++++-------- .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 25406e389..4884ea42b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -573,13 +573,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QModelIndex rootIdx = model->index( tabId, 0, m_ui->tileSetLV->currentIndex()); - QListView *lv = NULL; - - switch( tabId ) - { - case TAB_128: lv = m_ui->listView128; break; - case TAB_256: lv = m_ui->listView256; break; - } + QListView *lv = getListViewByTab( tabId ); lv->reset(); lv->setRootIndex( rootIdx ); @@ -588,12 +582,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) void TileEditorMainWindow::onActionDeleteTile( int tabId ) { - QListView *lv = NULL; - switch( tabId ) - { - case TAB_128: lv = m_ui->listView128; break; - case TAB_256: lv = m_ui->listView256; break; - } + QListView *lv = getListViewByTab( tabId ); QModelIndex idx = lv->currentIndex(); if( !idx.isValid() ) @@ -671,3 +660,21 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons //m_ui->listViewTransition->reset(); //m_ui->listViewDisplacement->reset(); } + + +QListView* TileEditorMainWindow::getListViewByTab( int tab ) const +{ + QListView *lv = NULL; + + switch( tab ) + { + case TAB_128: lv = m_ui->listView128; break; + case TAB_256: lv = m_ui->listView256; break; + case TAB_TRANSITION: lv = m_ui->listViewTransition; break; + case TAB_DISPLACEMENT: lv = m_ui->listViewDisplacement; break; + } + + return lv; +} + + diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index f839e7c32..2eae0b89f 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -71,6 +71,7 @@ private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); TileModel* createTileModel(); + QListView* getListViewByTab( int tab ) const; Ui::TileEditorMainWindow *m_ui; QUndoStack *m_undoStack; From 5866a61cff2bc114a6ab06002f21df0e3961cb1b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:19:13 +0200 Subject: [PATCH 180/282] Implemented tile image deletion. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 20 ++++++++++++++++++- .../tile_editor/tile_editor_main_window.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 4884ea42b..a941de6d7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -130,7 +130,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); connect(m_ui->actionDeleteTile, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteTile(bool))); connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); - connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); + connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteImage(bool))); //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); @@ -224,6 +224,7 @@ void TileEditorMainWindow::onActionReplaceImage(bool triggered) void TileEditorMainWindow::onActionDeleteImage(bool triggered) { + onActionDeleteImage(m_ui->tileViewTabWidget->currentIndex()); } void TileEditorMainWindow::onTileSetAdd() @@ -601,6 +602,23 @@ void TileEditorMainWindow::onActionDeleteTile( int tabId ) //lv->reset(); } +void TileEditorMainWindow::onActionDeleteImage( int tabId ) +{ + QListView *lv = getListViewByTab( tabId ); + + QModelIndex idx = lv->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Deleting tile image" ), + tr( "No tile selected!" ) ); + return; + } + + TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); + n->setTileFilename( TileModel::TileDiffuse, "" ); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 2eae0b89f..117315c25 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -70,6 +70,9 @@ private Q_SLOTS: private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); + void onActionDeleteImage(int tabId); + + TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; From 4326ca1df8250b95c9f09e03756d03734cf9755e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:24:32 +0200 Subject: [PATCH 181/282] Implemented tile image replace. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 25 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 26 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a941de6d7..e272faeee 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -220,6 +220,7 @@ void TileEditorMainWindow::onActionDeleteTile(bool triggered) void TileEditorMainWindow::onActionReplaceImage(bool triggered) { + onActionReplaceImage(m_ui->tileViewTabWidget->currentIndex()); } void TileEditorMainWindow::onActionDeleteImage(bool triggered) @@ -619,6 +620,30 @@ void TileEditorMainWindow::onActionDeleteImage( int tabId ) n->setTileFilename( TileModel::TileDiffuse, "" ); } +void TileEditorMainWindow::onActionReplaceImage( int tabId ) +{ + QListView *lv = getListViewByTab( tabId ); + + QModelIndex idx = lv->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Replacing tile image" ), + tr( "No tile selected!" ) ); + return; + } + + QString fileName = QFileDialog::getOpenFileName( this, + tr( "Select tile image" ), + "", + tr( "PNG files (*.png)" ) ); + if( fileName.isEmpty() ) + return; + + TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); + n->setTileFilename( TileModel::TileDiffuse, fileName ); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 117315c25..14cb7cf75 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -71,6 +71,7 @@ private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); void onActionDeleteImage(int tabId); + void onActionReplaceImage(int tabId); TileModel* createTileModel(); From b004bb9d01566fd51711e0098bb7b591b3441a99 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 27 Jul 2014 18:23:25 +0200 Subject: [PATCH 182/282] 128x128 tab should be shown by default. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_editor_main_window.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 4297b4848..2e936aa8b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -18,7 +18,7 @@ - 4 + 0 From 8a704b7f5fbe647f9e560a3a08eda8dbbbcb81f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 27 Jul 2014 20:38:08 +0200 Subject: [PATCH 183/282] Implemented the GUI part of saving... --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 49 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 6 +++ .../plugins/tile_editor/tile_editor_plugin.h | 10 ++++ .../plugins/tile_editor/tilebank_saver.cpp | 37 ++++++++++++++ .../src/plugins/tile_editor/tilebank_saver.h | 38 ++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 code/studio/src/plugins/tile_editor/tilebank_saver.cpp create mode 100644 code/studio/src/plugins/tile_editor/tilebank_saver.h diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index e272faeee..75d2c31f4 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -32,6 +32,8 @@ #include "tile_item.h" #include "tile_item_delegate.h" +#include "tilebank_saver.h" + TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::TileEditorMainWindow) @@ -142,6 +144,14 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionZoom200, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); m_zoomSignalMapper->setMapping(m_ui->actionZoom200, 2); connect(m_zoomSignalMapper, SIGNAL(mapped(int)), this, SLOT(onZoomFactor(int))); + + QAction *saveAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE ); + saveAction->setEnabled( true ); + QAction *saveAsAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE_AS ); + saveAsAction->setEnabled( true ); + + connect( m_ui->actionSaveTileBank, SIGNAL( triggered() ), this, SLOT( save() ) ); + connect( m_ui->actionSaveTileBankAs, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); } TileEditorMainWindow::~TileEditorMainWindow() @@ -161,6 +171,45 @@ TileEditorMainWindow::~TileEditorMainWindow() m_tileModels.clear(); } +void TileEditorMainWindow::save() +{ + saveAs(); +} + +void TileEditorMainWindow::saveAs() +{ + if( m_fileName.isEmpty() ) + { + m_fileName = QFileDialog::getSaveFileName( this, + tr( "Save TileBank as..." ), + "", + tr( "TileBank files (*.tilebank)" ) ); + + if( m_fileName.isEmpty() ) + return; + + } + + QList< QString > landNames; + + int c = m_ui->landLW->count(); + for( int i = 0; i < c; i++ ) + { + QListWidgetItem *item = m_ui->landLW->item( i ); + landNames.push_back( item->text() ); + } + + TileBankSaver saver; + bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModels, landNames ); + + if( !ok ) + { + QMessageBox::critical( this, + tr( "Saving tilebank" ), + tr( "Failed to save tilebank :(" ) ); + } +} + void TileEditorMainWindow::onZoomFactor(int level) { int tile128Scaled=TileModel::TILE_128_BASE_SIZE; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 14cb7cf75..c1fb662b0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -42,6 +42,10 @@ public: QUndoStack *getUndoStack() { return m_undoStack; } +public Q_SLOTS: + void save(); + void saveAs(); + private Q_SLOTS: void onActionAddTile(bool triggered); void onActionDeleteTile(bool triggered); @@ -102,6 +106,8 @@ private: TAB_DISPLACEMENT = 3, TAB_DETAILS = 4 }; + + QString m_fileName; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h index cb7be7fc1..024e6a6e2 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h @@ -95,6 +95,16 @@ public: { } + void save() + { + m_tileEditorMainWindow->save(); + } + + void saveAs() + { + m_tileEditorMainWindow->saveAs(); + } + virtual QWidget *widget() { return m_tileEditorMainWindow; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp new file mode 100644 index 000000000..d149648ff --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -0,0 +1,37 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "tilebank_saver.h" +#include "tile_model.h" + +#include "nel/3d/tile_bank.h" + +TileBankSaver::TileBankSaver() +{ +} + +TileBankSaver::~TileBankSaver() +{ +} + +bool TileBankSaver::save( const char *fileName, const QList< TileModel* > &models, const QList< QString > &lands ) +{ + NL3D::CTileBank bank; + + return false; +} + diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h new file mode 100644 index 000000000..80fb119d8 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -0,0 +1,38 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TILEBANK_SAVER_H +#define TILEBANK_SAVER_H + +#include +#include + +class TileModel; + +class TileBankSaver +{ +public: + TileBankSaver(); + ~TileBankSaver(); + + bool save( const char *filename, const QList< TileModel* > &models, const QList< QString > &lands ); + +private: +}; + +#endif + From 89c618014467f8a9a001b812ea3e2b69b808cc80 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 28 Jul 2014 17:05:51 +0200 Subject: [PATCH 184/282] As it turns out, tilesets can be assigned to multiple lands... --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/CMakeLists.txt | 6 +- .../plugins/tile_editor/land_edit_dialog.cpp | 77 +++++++++ .../plugins/tile_editor/land_edit_dialog.h | 32 ++++ .../plugins/tile_editor/land_edit_dialog.ui | 99 +++++++++++ .../tile_editor/tile_editor_main_window.cpp | 159 +++++++++--------- .../tile_editor/tile_editor_main_window.h | 12 +- .../plugins/tile_editor/tilebank_saver.cpp | 2 +- .../src/plugins/tile_editor/tilebank_saver.h | 2 +- 8 files changed, 300 insertions(+), 89 deletions(-) create mode 100644 code/studio/src/plugins/tile_editor/land_edit_dialog.cpp create mode 100644 code/studio/src/plugins/tile_editor/land_edit_dialog.h create mode 100644 code/studio/src/plugins/tile_editor/land_edit_dialog.ui diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index d546beba1..396522235 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -11,10 +11,12 @@ SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin. SET(OVQT_TILE_EDITOR_PLUGIN_HDR tile_model.h tile_editor_main_window.h - tile_editor_plugin.h) + tile_editor_plugin.h + land_edit_dialog.h) SET(OVQT_TILE_EDITOR_PLUGIN_UIS - tile_editor_main_window.ui) + tile_editor_main_window.ui + land_edit_dialog.ui) SET(OVQT_PLUG_TILE_EDITOR_RCS tile_editor.qrc) diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp new file mode 100644 index 000000000..f7f5c5ce6 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -0,0 +1,77 @@ +#include "land_edit_dialog.h" + +LandEditDialog::LandEditDialog( QWidget *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); +} + +LandEditDialog::~LandEditDialog() +{ +} + +void LandEditDialog::getSelectedTileSets( QStringList &l ) const +{ + int c = tilesetLV->count(); + for( int i = 0; i < c; i++ ) + { + l.push_back( tilesetLV->item( i )->text() ); + } +} + +void LandEditDialog::setTileSets( const QStringList &l ) +{ + tilesetCB->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetCB->addItem( itr.next() ); + } +} + +void LandEditDialog::setupConnections() +{ + connect( okButton, SIGNAL( clicked( bool ) ), this, SLOT( onOkClicked() ) ); + connect( cancelButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); + connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( onAddClicked() ) ); + connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveClicked() ) ); +} + +void LandEditDialog::onOkClicked() +{ + accept(); +} + +void LandEditDialog::onCancelClicked() +{ + reject(); +} + +void LandEditDialog::onAddClicked() +{ + if( tilesetCB->currentIndex() < 0 ) + return; + + QString text = tilesetCB->currentText(); + + int c = tilesetLV->count(); + for( int i = 0; i < c; i++ ) + { + if( text == tilesetLV->item( i )->text() ) + return; + } + + tilesetLV->addItem( text ); +} + +void LandEditDialog::onRemoveClicked() +{ + if( tilesetLV->currentItem() == NULL ) + return; + + QListWidgetItem *item = tilesetLV->currentItem(); + delete item; +} + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h new file mode 100644 index 000000000..9b86a2d06 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -0,0 +1,32 @@ +#ifndef LAND_EDIT_DLG_H +#define LAND_EDIT_DLG_H + + +#include "ui_land_edit_dialog.h" +#include + +class LandEditDialog : public QDialog, public Ui::LandEditDialog +{ + Q_OBJECT +public: + LandEditDialog( QWidget *parent = NULL ); + ~LandEditDialog(); + + void getSelectedTileSets( QStringList &l ) const; + void setTileSets( const QStringList &l ); + +private: + void setupConnections(); + + +private Q_SLOTS: + void onOkClicked(); + void onCancelClicked(); + void onAddClicked(); + void onRemoveClicked(); + +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.ui b/code/studio/src/plugins/tile_editor/land_edit_dialog.ui new file mode 100644 index 000000000..7eb707528 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.ui @@ -0,0 +1,99 @@ + + + LandEditDialog + + + Qt::WindowModal + + + + 0 + 0 + 402 + 311 + + + + Editing land + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Add + + + + + + + + 0 + 0 + + + + Remove + + + + + + + + 0 + 0 + + + + OK + + + + + + + + 0 + 0 + + + + Cancel + + + + + + + + + + diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 75d2c31f4..0a30da403 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -34,6 +34,8 @@ #include "tilebank_saver.h" +#include "land_edit_dialog.h" + TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::TileEditorMainWindow) @@ -96,15 +98,18 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); - connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); connect(m_ui->chooseVegetPushButton, SIGNAL(clicked()), this, SLOT(onChooseVegetation())); connect(m_ui->resetVegetPushButton, SIGNAL(clicked()), this, SLOT(onResetVegetation())); connect(m_ui->tileBankTexturePathPB, SIGNAL(clicked()), this, SLOT(onChooseTexturePath())); + m_tileModel = createTileModel(); + m_ui->tileSetLV->setModel( m_tileModel ); + // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); + m_ui->listView128->setModel( m_tileModel ); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); m_ui->listView128->addAction(m_ui->actionReplaceImage); @@ -112,6 +117,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // 256x256 List View //m_ui->listView256->setItemDelegate(m_tileItemDelegate); + m_ui->listView256->setModel( m_tileModel ); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); m_ui->listView256->addAction(m_ui->actionReplaceImage); @@ -119,11 +125,13 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Transition List View //m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); + m_ui->listViewTransition->setModel( m_tileModel ); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View //m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); + m_ui->listViewDisplacement->setModel( m_tileModel ); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -135,6 +143,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteImage(bool))); //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); + connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); // Connect the zoom buttons. connect(m_ui->actionZoom50, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); @@ -167,8 +177,8 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_zoomActionGroup; delete m_zoomSignalMapper; - qDeleteAll( m_tileModels ); - m_tileModels.clear(); + delete m_tileModel; + m_tileModel = NULL; } void TileEditorMainWindow::save() @@ -200,7 +210,7 @@ void TileEditorMainWindow::saveAs() } TileBankSaver saver; - bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModels, landNames ); + bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, landNames ); if( !ok ) { @@ -279,14 +289,6 @@ void TileEditorMainWindow::onActionDeleteImage(bool triggered) void TileEditorMainWindow::onTileSetAdd() { - if( m_ui->landLW->count() == 0 ) - { - QMessageBox::information( this, - tr( "Error adding tile set" ), - tr( "You need to add a land before adding a tileset!" ) ); - return; - } - bool ok; QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) @@ -323,8 +325,12 @@ void TileEditorMainWindow::onTileSetDelete() if( reply != QMessageBox::Yes ) return; + QString set = reinterpret_cast< TileSetNode* >( idx.internalPointer() )->getTileSetName(); + TileModel *model = static_cast(m_ui->tileSetLV->model()); bool ok = model->removeRow( idx.row() ); + + onTileSetRemoved( set ); } void TileEditorMainWindow::onTileSetEdit() @@ -357,8 +363,11 @@ void TileEditorMainWindow::onTileSetEdit() return; } + QString oldName = node->getTileSetName(); node->setTileSetName( newName ); m_ui->tileSetLV->reset(); + + onTileSetRenamed( oldName, newName ); } void TileEditorMainWindow::onTileSetUp() @@ -422,13 +431,10 @@ void TileEditorMainWindow::onLandAdd() } m_ui->landLW->addItem( name ); - - TileModel *m = createTileModel(); - - m_tileModels.push_back( m ); - - if( m_tileModels.count() == 1 ) - m_ui->landLW->setCurrentRow( 0 ); + + Land l; + l.name = name; + m_lands.push_back( l ); } void TileEditorMainWindow::onLandRemove() @@ -447,12 +453,10 @@ void TileEditorMainWindow::onLandRemove() if( reply != QMessageBox::Yes ) return; - QList< TileModel* >::iterator itr = m_tileModels.begin() + idx; - delete m_tileModels[ idx ]; - m_tileModels[ idx ] = NULL; - m_tileModels.erase( itr ); - delete item; + + QList< Land >::iterator itr = m_lands.begin() + idx; + m_lands.erase( itr ); } void TileEditorMainWindow::onLandEdit() @@ -461,58 +465,33 @@ void TileEditorMainWindow::onLandEdit() if( item == NULL ) return; - QString name = item->text(); - - QString newName = QInputDialog::getText( this, - tr( "Editing land" ), - tr( "Please specify the new name of the selected land" ), - QLineEdit::Normal, - name ); - - if( newName.isEmpty() ) - return; - if( newName == name ) - return; - item->setText( newName ); -} - -void TileEditorMainWindow::onLandRowChanged( int row ) -{ - m_ui->chooseVegetPushButton->setText( "..." ); - - if( row == -1 ) - { - disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); - - m_ui->tileSetLV->setModel( NULL ); - m_ui->listView128->setModel( NULL ); - m_ui->listView256->setModel( NULL ); - m_ui->listViewTransition->setModel( NULL ); - m_ui->listViewDisplacement->setModel( NULL ); - } - else + QStringList ts; + int c = m_tileModel->rowCount(); + for( int i = 0; i < c; i++ ) { - //disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - // this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + QModelIndex idx = m_tileModel->index( i, 0 ); + if( !idx.isValid() ) + continue; - m_ui->tileSetLV->setModel( m_tileModels[ row ] ); - m_ui->listView128->setModel( m_tileModels[ row ] ); - m_ui->listView256->setModel( m_tileModels[ row ] ); - m_ui->listViewTransition->setModel( m_tileModels[ row ] ); - m_ui->listViewDisplacement->setModel( m_tileModels[ row ] ); + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + ts.push_back( n->getTileSetName() ); + } + + int r = m_ui->landLW->currentRow(); + Land &l = m_lands[ r ]; - connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + LandEditDialog d; + d.setTileSets( ts ); + int result = d.exec(); - if( m_ui->tileSetLV->model()->rowCount() != 0 ) - { - QModelIndex idx = m_ui->tileSetLV->model()->index( 0, 0 ); - m_ui->tileSetLV->setCurrentIndex( idx ); - } - } + if( result != QDialog::Accepted ) + return; - m_ui->tileSetLV->reset(); + // Update the tileset of the land + ts.clear(); + d.getSelectedTileSets( ts ); + l.tilesets.clear(); + l.tilesets = ts; } void TileEditorMainWindow::onChooseVegetation() @@ -579,15 +558,6 @@ void TileEditorMainWindow::onChooseTexturePath() void TileEditorMainWindow::onActionAddTile(int tabId) { - int land = m_ui->landLW->currentRow(); - if( land == -1 ) - { - QMessageBox::information( this, - tr( "Adding new tile" ), - tr( "You need to have a land and a tileset selected before you can add tiles!" ) ); - return; - } - QModelIndex idx = m_ui->tileSetLV->currentIndex(); if( !idx.isValid() ) { @@ -599,8 +569,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) int tileSet = idx.row(); - TileModel *model = static_cast< TileModel* >( m_tileModels[ land ] ); - idx = model->index( tileSet, 0 ); + idx = m_tileModel->index( tileSet, 0 ); if( !idx.isValid() ) return; @@ -622,7 +591,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) c++; } - QModelIndex rootIdx = model->index( tabId, 0, m_ui->tileSetLV->currentIndex()); + QModelIndex rootIdx = m_tileModel->index( tabId, 0, m_ui->tileSetLV->currentIndex()); QListView *lv = getListViewByTab( tabId ); @@ -693,6 +662,30 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) n->setTileFilename( TileModel::TileDiffuse, fileName ); } +void TileEditorMainWindow::onTileSetRemoved( const QString &set ) +{ + int c = m_lands.count(); + for( int i = 0; i < c; i++ ) + { + Land &land = m_lands[ i ]; + land.tilesets.removeAll( set ); + } +} + +void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QString &newname ) +{ + int c = m_lands.count(); + for( int i = 0; i < c; i++ ) + { + Land &land = m_lands[ i ]; + int idx = land.tilesets.indexOf( oldname ); + if( idx < 0 ) + continue; + + land.tilesets[ idx ] = newname; + } +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index c1fb662b0..5f015ad6a 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -61,7 +61,6 @@ private Q_SLOTS: void onLandAdd(); void onLandRemove(); void onLandEdit(); - void onLandRowChanged( int row ); void onResetVegetation(); void onChooseVegetation(); @@ -77,6 +76,8 @@ private: void onActionDeleteImage(int tabId); void onActionReplaceImage(int tabId); + void onTileSetRemoved( const QString &set ); + void onTileSetRenamed( const QString &oldname, const QString &newname ); TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; @@ -94,7 +95,7 @@ private: TileItemDelegate *m_tileItemDelegate; - QList< TileModel* > m_tileModels; + TileModel *m_tileModel; QString m_texturePath; @@ -107,7 +108,14 @@ private: TAB_DETAILS = 4 }; + struct Land + { + QString name; + QStringList tilesets; + }; + QString m_fileName; + QList< Land > m_lands; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index d149648ff..db281d161 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -28,7 +28,7 @@ TileBankSaver::~TileBankSaver() { } -bool TileBankSaver::save( const char *fileName, const QList< TileModel* > &models, const QList< QString > &lands ) +bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< QString > &lands ) { NL3D::CTileBank bank; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index 80fb119d8..f86bfab60 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -29,7 +29,7 @@ public: TileBankSaver(); ~TileBankSaver(); - bool save( const char *filename, const QList< TileModel* > &models, const QList< QString > &lands ); + bool save( const char *filename, const TileModel* model, const QList< QString > &lands ); private: }; From 95b67026bfa3b0e9967bf4200b52af96872bf322 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 01:29:17 +0200 Subject: [PATCH 185/282] Implemented saving of the currently stored tilebank data. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/land.h | 14 ++ .../tile_editor/tile_editor_main_window.cpp | 2 +- .../tile_editor/tile_editor_main_window.h | 8 +- .../src/plugins/tile_editor/tile_item.cpp | 10 + .../src/plugins/tile_editor/tile_item.h | 1 + .../plugins/tile_editor/tilebank_saver.cpp | 204 +++++++++++++++++- .../src/plugins/tile_editor/tilebank_saver.h | 6 +- 7 files changed, 234 insertions(+), 11 deletions(-) create mode 100644 code/studio/src/plugins/tile_editor/land.h diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h new file mode 100644 index 000000000..37b0d83c6 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land.h @@ -0,0 +1,14 @@ +#ifndef LAND_H +#define LAND_H + +#include + +struct Land +{ + QString name; + QStringList tilesets; +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 0a30da403..91d81ea50 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -210,7 +210,7 @@ void TileEditorMainWindow::saveAs() } TileBankSaver saver; - bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, landNames ); + bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, m_lands ); if( !ok ) { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 5f015ad6a..a491fc5f2 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -25,6 +25,8 @@ #include #include +#include "land.h" + namespace Ui { class TileEditorMainWindow; } @@ -108,12 +110,6 @@ private: TAB_DETAILS = 4 }; - struct Land - { - QString name; - QStringList tilesets; - }; - QString m_fileName; QList< Land > m_lands; }; diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index e228a6745..b6bb30ea2 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -272,6 +272,16 @@ void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file m_tileFilename[channel] = filename; } +QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) +{ + QMap< TileModel::TTileChannel, QString >::const_iterator itr + = m_tileFilename.find( channel ); + if( itr == m_tileFilename.end() ) + return ""; + + return itr.value(); +} + QVariant TileItemNode::data(int column, int role) const { // find some way to know which file/bitmap to display diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index f232acb4b..b66a2b6f3 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -106,6 +106,7 @@ public: QVariant data(int column, int role) const; int columnCount() const; void setTileFilename(TileModel::TTileChannel channel, QString filename); + QString getTileFilename(TileModel::TTileChannel channel); void setId( int id ){ m_tileId = id; } int id() const{ return m_tileId; } private: diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index db281d161..6bf13fdfe 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -17,21 +17,219 @@ #include "tilebank_saver.h" #include "tile_model.h" +#include "tile_item.h" #include "nel/3d/tile_bank.h" +#include "nel/misc/file.h" + +class TileBankSaverPvt +{ +public: + NL3D::CTileBank bank; + + static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + { + NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; + + switch( channel ) + { + case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileModel::TileAdditive: b = NL3D::CTile::additive; break; + case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + } + + return b; + } + + NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileModel::TNodeTileType type ) + { + int idx = -1; + int bidx = -1; + + switch( type ) + { + case TileModel::Tile128: + { + set->addTile128( idx, bank ); + bidx = set->getTile128( idx ); + break; + } + + case TileModel::Tile256: + { + set->addTile256( idx, bank ); + bidx = set->getTile256( idx ); + break; + } + } + + if( idx == -1 ) + return NULL; + + return bank.getTile( bidx ); + } + + void addTilesToSet( NL3D::CTileSet *set, TileTypeNode *node ) + { + TileModel::TNodeTileType type = node->getTileType(); + + for( int i = 0; i < node->childCount(); i++ ) + { + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + { + QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); + + NL3D::CTile *tile = addTileToSet( set, type ); + tile->setFileName( channelToTBitmap( TileModel::TTileChannel( j ) ) , fn.toUtf8().constData() ); + } + } + } + + void addTilesToSet( NL3D::CTileSet *set, TileSetNode *node ) + { + for( int i = TileModel::Tile128; i <= TileModel::Tile256; i++ ) + { + TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( i ) ); + + addTilesToSet( set, tn ); + } + } + + void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) + { + NL3D::CTileSetTransition *tr = set->getTransition( idx ); + int tid = tr->getTile(); + NL3D::CTile *tile = bank.getTile( tid ); + + if( tile == NULL ) + return; + + for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + { + QString fn = node->getTileFilename( TileModel::TTileChannel( i ) ); + tile->setFileName( channelToTBitmap( TileModel::TTileChannel( i ) ), fn.toUtf8().constData() ); + } + } + + void setupTransitionTiles( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < node->childCount(); i++ ) + { + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + setupTransitionTile( set, tin, i ); + } + } + + void setupTransitionTiles( NL3D::CTileSet *set, TileSetNode *node ) + { + TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 2 ) ); + setupTransitionTiles( set, tn ); + } + + void setupDisplacementTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) + { + set->setDisplacement( NL3D::CTileSet::TDisplacement( idx ), + node->getTileFilename( TileModel::TileDiffuse ).toUtf8().constData(), + bank ); + } + + void setupDisplacementTiles( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < node->childCount(); i++ ) + { + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + setupDisplacementTile( set, tin, i ); + } + } + + void setupDisplacementTiles( NL3D::CTileSet *set, TileSetNode *node ) + { + TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 3 ) ); + setupDisplacementTiles( set, tn ); + } + + void addLands( const QList< Land > &lands ) + { + QListIterator< Land > itr( lands ); + while( itr.hasNext() ) + { + bank.addLand( itr.next().name.toUtf8().constData() ); + } + } + + + void addTileSets( const TileModel* model, const QList< Land > &lands ) + { + // Add the tilesets + for( int i = 0; i < model->rowCount(); i++ ) + { + QModelIndex idx = model->index( i, 0 ); + if( !idx.isValid() ) + continue; + + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + QString set = n->getTileSetName(); + bank.addTileSet( set.toUtf8().constData() ); + } + + // Set the data to tilesets + for( int i = 0; i < bank.getTileSetCount(); i++ ) + { + NL3D::CTileSet *set = bank.getTileSet( i ); + + QModelIndex idx = model->index( i, 0 ); + if( !idx.isValid() ) + continue; + + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + + addTilesToSet( set, n ); + setupTransitionTiles( set, n ); + setupDisplacementTiles( set, n ); + } + + // Add tilesets to lands + for( int i = 0; i < bank.getLandCount(); i++ ) + { + NL3D::CTileLand *land = bank.getLand( i ); + const Land &l = lands[ i ]; + + for( int j = 0; j < l.tilesets.count(); j++ ) + { + land->addTileSet( l.tilesets[ j ].toUtf8().constData() ); + } + } + } +}; TileBankSaver::TileBankSaver() { + p = new TileBankSaverPvt(); } TileBankSaver::~TileBankSaver() { + delete p; + p = NULL; } -bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< QString > &lands ) +bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< Land > &lands ) { - NL3D::CTileBank bank; + p->addLands( lands ); + p->addTileSets( model, lands ); + + // Save to file + NLMISC::COFile f; + bool b = f.open( fileName, false, false, false ); + if( !b ) + return false; + + p->bank.serial( f ); + + f.flush(); + f.close(); - return false; + return true; } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index f86bfab60..2a2806fe1 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -20,18 +20,22 @@ #include #include +#include "land.h" class TileModel; +class TileBankSaverPvt; + class TileBankSaver { public: TileBankSaver(); ~TileBankSaver(); - bool save( const char *filename, const TileModel* model, const QList< QString > &lands ); + bool save( const char *filename, const TileModel* model, const QList< Land > &lands ); private: + TileBankSaverPvt *p; }; #endif From ddc7961e9ba52122e8b9bde6de379112e640fe92 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 01:50:01 +0200 Subject: [PATCH 186/282] Connected the oriented combobox and now saving it's value to the tilebank. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 16 ++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 2 ++ .../studio/src/plugins/tile_editor/tile_item.cpp | 1 + code/studio/src/plugins/tile_editor/tile_item.h | 4 ++++ .../src/plugins/tile_editor/tilebank_saver.cpp | 2 ++ 5 files changed, 25 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 91d81ea50..a8219f6eb 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -162,6 +162,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect( m_ui->actionSaveTileBank, SIGNAL( triggered() ), this, SLOT( save() ) ); connect( m_ui->actionSaveTileBankAs, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); + + connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); } TileEditorMainWindow::~TileEditorMainWindow() @@ -556,6 +558,20 @@ void TileEditorMainWindow::onChooseTexturePath() m_ui->tileBankTexturePathPB->setText( path ); } +void TileEditorMainWindow::onOrientedStateChanged( int state ) +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + + if( state == Qt::Checked ) + node->setOriented( true ); + else + node->setOriented( false ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QModelIndex idx = m_ui->tileSetLV->currentIndex(); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index a491fc5f2..2d1a9e154 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -69,6 +69,8 @@ private Q_SLOTS: void onChooseTexturePath(); + void onOrientedStateChanged( int state ); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index b6bb30ea2..78c3afae2 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -167,6 +167,7 @@ void Node::swapRows( int a, int b ) TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) { m_parentItem = parent; + m_oriented = false; } TileSetNode::~TileSetNode() diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index b66a2b6f3..9538afa3b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -75,9 +75,13 @@ public: void setVegetSet( const QString &s ){ m_vegetSet = s; } QString vegetSet() const{ return m_vegetSet; } + bool isOriented() const{ return m_oriented; } + void setOriented( bool b ){ m_oriented = b; } + private: QString m_tileSetName; QString m_vegetSet; + bool m_oriented; }; class TileTypeNode : public Node diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 6bf13fdfe..c41673243 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -187,6 +187,8 @@ public: addTilesToSet( set, n ); setupTransitionTiles( set, n ); setupDisplacementTiles( set, n ); + + set->setOriented( n->isOriented() ); } // Add tilesets to lands From c8914248db02721dcbbc621c0de13f907943920d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 07:43:02 +0200 Subject: [PATCH 187/282] Add the already selected tilesets to the land when editing. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/land_edit_dialog.cpp | 11 +++++++++++ .../studio/src/plugins/tile_editor/land_edit_dialog.h | 2 ++ .../plugins/tile_editor/tile_editor_main_window.cpp | 1 + 3 files changed, 14 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp index f7f5c5ce6..87c66aa9c 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -20,6 +20,17 @@ void LandEditDialog::getSelectedTileSets( QStringList &l ) const } } +void LandEditDialog::setSelectedTileSets( QStringList &l ) +{ + tilesetLV->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetLV->addItem( itr.next() ); + } +} + void LandEditDialog::setTileSets( const QStringList &l ) { tilesetCB->clear(); diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h index 9b86a2d06..1ada1c23e 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.h +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -13,6 +13,8 @@ public: ~LandEditDialog(); void getSelectedTileSets( QStringList &l ) const; + void setSelectedTileSets( QStringList &l ); + void setTileSets( const QStringList &l ); private: diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a8219f6eb..1e43fa003 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -483,6 +483,7 @@ void TileEditorMainWindow::onLandEdit() Land &l = m_lands[ r ]; LandEditDialog d; + d.setSelectedTileSets( l.tilesets ); d.setTileSets( ts ); int result = d.exec(); From 431178321f6853087dc73eb015dbebf4f632b032 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 10:54:08 +0200 Subject: [PATCH 188/282] TileBank loading. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/3d/tile_bank.h | 3 + .../tile_editor/tile_editor_main_window.cpp | 45 ++++- .../tile_editor/tile_editor_main_window.h | 2 + .../plugins/tile_editor/tile_editor_plugin.h | 1 + .../src/plugins/tile_editor/tile_item.cpp | 8 + .../src/plugins/tile_editor/tile_item.h | 2 + .../src/plugins/tile_editor/tile_model.cpp | 15 ++ .../src/plugins/tile_editor/tile_model.h | 2 + .../plugins/tile_editor/tilebank_loader.cpp | 168 ++++++++++++++++++ .../src/plugins/tile_editor/tilebank_loader.h | 23 +++ 10 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/tile_editor/tilebank_loader.cpp create mode 100644 code/studio/src/plugins/tile_editor/tilebank_loader.h diff --git a/code/nel/include/nel/3d/tile_bank.h b/code/nel/include/nel/3d/tile_bank.h index 9253c5f45..f391554d3 100644 --- a/code/nel/include/nel/3d/tile_bank.h +++ b/code/nel/include/nel/3d/tile_bank.h @@ -161,6 +161,9 @@ public: { return _Name; }; + + std::set getTileSets() const{ return _TileSet; } + void setName (const std::string& name); void addTileSet (const std::string& name); void removeTileSet (const std::string& name); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 1e43fa003..427494ab4 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -33,6 +33,7 @@ #include "tile_item_delegate.h" #include "tilebank_saver.h" +#include "tilebank_loader.h" #include "land_edit_dialog.h" @@ -159,9 +160,12 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) saveAction->setEnabled( true ); QAction *saveAsAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE_AS ); saveAsAction->setEnabled( true ); + QAction *openAction = Core::ICore::instance()->menuManager()->action( Core::Constants::OPEN ); + openAction->setEnabled( true ); connect( m_ui->actionSaveTileBank, SIGNAL( triggered() ), this, SLOT( save() ) ); connect( m_ui->actionSaveTileBankAs, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); + connect( m_ui->actionOpenTileBank, SIGNAL( triggered() ), this, SLOT( open() ) ); connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); } @@ -222,6 +226,30 @@ void TileEditorMainWindow::saveAs() } } +void TileEditorMainWindow::open() +{ + QString fn = QFileDialog::getOpenFileName( this, + tr( "Loading tilebank" ), + "", + tr( "tilebank files (*.tilebank)" ) ); + + if( fn.isEmpty() ) + return; + + TileBankLoader loader; + bool b = loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); + + if( !b ) + { + QMessageBox::critical( this, + tr( "Loading tilebank" ), + tr( "Failed to load tilebank %1" ).arg( fn ) ); + } + + // Put the loaded data into the GUI + onTileBankLoaded(); +} + void TileEditorMainWindow::onZoomFactor(int level) { int tile128Scaled=TileModel::TILE_128_BASE_SIZE; @@ -307,7 +335,6 @@ void TileEditorMainWindow::onTileSetAdd() TileSetNode *tileSet = model->createTileSetNode(text); // Retrieve how many rows there currently are and set the current index using that. - m_ui->tileSetLV->reset(); uint32 rows = model->rowCount(); m_ui->tileSetLV->setCurrentIndex(model->index(rows-1, 0)); } @@ -703,6 +730,20 @@ void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QStri } } +void TileEditorMainWindow::onTileBankLoaded() +{ + m_ui->landLW->clear(); + QListIterator< Land > itr( m_lands ); + while( itr.hasNext() ) + { + m_ui->landLW->addItem( itr.next().name ); + } + + m_ui->listView128->reset(); + m_ui->listView256->reset(); + m_ui->listViewTransition->reset(); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; @@ -749,6 +790,8 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->chooseVegetPushButton->setText( vegetSet ); else m_ui->chooseVegetPushButton->setText( "..." ); + + m_ui->orientedCheckBox->setChecked( newNode->isOriented() ); } else { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 2d1a9e154..022348ab5 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -47,6 +47,7 @@ public: public Q_SLOTS: void save(); void saveAs(); + void open(); private Q_SLOTS: void onActionAddTile(bool triggered); @@ -82,6 +83,7 @@ private: void onTileSetRemoved( const QString &set ); void onTileSetRenamed( const QString &oldname, const QString &newname ); + void onTileBankLoaded(); TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h index 024e6a6e2..70fb38e77 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h @@ -93,6 +93,7 @@ public: virtual void open() { + m_tileEditorMainWindow->open(); } void save() diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 78c3afae2..76bf7c67e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -40,6 +40,7 @@ Node::~Node() void Node::appendChild(Node *item) { + item->setParent( this ); m_childItems.append(item); } @@ -162,6 +163,13 @@ void Node::swapRows( int a, int b ) m_childItems[ b ] = temp; } +void Node::clear() +{ + qDeleteAll( m_childItems ); + m_childItems.clear(); + m_itemData.clear(); +} + /////////////////////////////////////////////////// TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 9538afa3b..3fad517c3 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -55,6 +55,8 @@ public: void swapRows( int a, int b ); + void clear(); + protected: QList m_childItems; QVector m_itemData; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d68650b8f..99cc557e3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -137,7 +137,13 @@ void TileModel::appendRow(const QList &items) void TileModel::appendRow(Node *item) { + int c = rootItem->childCount(); + + beginInsertRows( QModelIndex(), c, c ); + rootItem->appendRow(item); + + endInsertRows(); } bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) @@ -272,6 +278,15 @@ bool TileModel::hasTileSet( const QString &name ) return false; } +void TileModel::clear() +{ + int c = rootItem->childCount(); + if( c == 0 ) + return; + + removeRows( 0, c ); +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 56d7b792b..f18e60fd3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -93,6 +93,8 @@ public: bool hasTileSet( const QString &name ); + void clear(); + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp new file mode 100644 index 000000000..6b56dcebe --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -0,0 +1,168 @@ +#include "tilebank_loader.h" + +#include "tile_model.h" +#include "tile_item.h" + +#include "nel/3d/tile_bank.h" +#include "nel/misc/file.h" + +class TileBankLoaderPvt +{ +public: + NL3D::CTileBank bank; + + static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + { + NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; + + switch( channel ) + { + case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileModel::TileAdditive: b = NL3D::CTile::additive; break; + case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + } + + return b; + } + + void loadLands( QList< Land > &lands ) + { + lands.clear(); + + Land l; + + int c = bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = bank.getLand( i ); + l.name = land->getName().c_str(); + + + std::set< std::string > sets = land->getTileSets(); + std::set< std::string >::const_iterator itr = sets.begin(); + while( itr != sets.end() ) + { + l.tilesets.push_back( itr->c_str() ); + ++itr; + } + + lands.push_back( l ); + } + } + + void loadTiles128( NL3D::CTileSet *set, TileTypeNode *node ) + { + int c = set->getNumTile128(); + for( int i = 0; i < c; i++ ) + { + int idx = set->getTile128( i ); + NL3D::CTile *tile = bank.getTile( idx ); + + TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + + for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + { + tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + } + + node->appendChild( tin ); + } + } + + void loadTiles256( NL3D::CTileSet *set, TileTypeNode *node ) + { + int c = set->getNumTile256(); + for( int i = 0; i < c; i++ ) + { + int idx = set->getTile256( i ); + NL3D::CTile *tile = bank.getTile( idx ); + + TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + + for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + { + tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + } + + node->appendChild( tin ); + } + } + + void loadTilesTransition( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < NL3D::CTileSet::count; i++ ) + { + const NL3D::CTileSetTransition *tr = set->getTransition( i ); + int idx = tr->getTile(); + NL3D::CTile *tile = bank.getTile( idx ); + + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + + for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + { + tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + } + } + } + + void loadTilesDisplacement( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < NL3D::CTileSet::CountDisplace; i++ ) + { + uint did = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( i ) ); + const char *fn = bank.getDisplacementMap( did ); + + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + tin->setTileFilename( TileModel::TileDiffuse, fn ); + } + } + + void loadTileSet( NL3D::CTileSet *set, TileSetNode *node ) + { + loadTiles128( set, static_cast< TileTypeNode* >( node->child( 0 ) ) ); + loadTiles256( set, static_cast< TileTypeNode* >( node->child( 1 ) ) ); + loadTilesTransition( set, static_cast< TileTypeNode* >( node->child( 2 ) ) ); + loadTilesDisplacement( set, static_cast< TileTypeNode* >( node->child( 3 ) ) ); + + node->setOriented( set->getOriented() ); + } + + void loadTileSets( TileModel *model ) + { + model->clear(); + + int c = bank.getTileSetCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileSet *set = bank.getTileSet( i ); + TileSetNode *node = model->createTileSetNode( set->getName().c_str() ); + loadTileSet( set, node ); + } + } +}; + + +TileBankLoader::TileBankLoader() +{ + p = new TileBankLoaderPvt; +} + +TileBankLoader::~TileBankLoader() +{ + delete p; + p = NULL; +} + +bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > &lands ) +{ + NLMISC::CIFile file; + if( !file.open( filename, false ) ) + return false; + + p->bank.serial( file ); + + p->loadLands( lands ); + p->loadTileSets( model ); + + return false; +} diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h new file mode 100644 index 000000000..b213cb309 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -0,0 +1,23 @@ +#ifndef TILEBANK_LOADER_H +#define TILEBANK_LOADER_H + +#include "land.h" + +class TileModel; +class TileBankLoaderPvt; + +class TileBankLoader +{ +public: + TileBankLoader(); + ~TileBankLoader(); + + bool load( const char *filename, TileModel *model, QList< Land > &lands ); + +private: + TileBankLoaderPvt *p; +}; + + +#endif + From 0f5e475d1c49d9c3c8ecf67e1541010eb17a195f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 10:58:37 +0200 Subject: [PATCH 189/282] Save and load the veget set filename. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 2 ++ code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 6b56dcebe..2c1d15c06 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -125,6 +125,8 @@ public: loadTilesDisplacement( set, static_cast< TileTypeNode* >( node->child( 3 ) ) ); node->setOriented( set->getOriented() ); + + node->setVegetSet( set->getTileVegetableDescFileName().c_str() ); } void loadTileSets( TileModel *model ) diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index c41673243..f650fb0d8 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -189,6 +189,8 @@ public: setupDisplacementTiles( set, n ); set->setOriented( n->isOriented() ); + + set->setTileVegetableDescFileName( n->vegetSet().toUtf8().constData() ); } // Add tilesets to lands From 3e2addc057a1e38a2f85fa53e9f6b5d0860baddc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:10:15 +0200 Subject: [PATCH 190/282] Save and load the tilebank texture path. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 7 +++++++ code/studio/src/plugins/tile_editor/tile_model.h | 5 +++++ code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 2 ++ code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 2 ++ 4 files changed, 16 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 427494ab4..df1194e4b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -584,6 +584,7 @@ void TileEditorMainWindow::onChooseTexturePath() m_texturePath = path; m_ui->tileBankTexturePathPB->setText( path ); + m_tileModel->setTexturePath( path ); } void TileEditorMainWindow::onOrientedStateChanged( int state ) @@ -742,6 +743,12 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->listView128->reset(); m_ui->listView256->reset(); m_ui->listViewTransition->reset(); + + QString path = m_tileModel->texturePath(); + if( path.isEmpty() ) + m_ui->tileBankTexturePathPB->setText( "..." ); + else + m_ui->tileBankTexturePathPB->setText( path ); } TileModel* TileEditorMainWindow::createTileModel() diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index f18e60fd3..f2efdb8d4 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -95,6 +95,9 @@ public: void clear(); + void setTexturePath( const QString &path ){ m_texturePath = path; } + QString texturePath() const{ return m_texturePath; } + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); @@ -109,6 +112,8 @@ private: //QList m_tiles; //int m_activeEditChannel; Node *rootItem; + + QString m_texturePath; }; #endif // TILE_MODEL_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 2c1d15c06..f51413026 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -166,5 +166,7 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > p->loadLands( lands ); p->loadTileSets( model ); + model->setTexturePath( p->bank.getAbsPath().c_str() ); + return false; } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index f650fb0d8..faec90bc4 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -223,6 +223,8 @@ bool TileBankSaver::save( const char *fileName, const TileModel* model, const QL p->addLands( lands ); p->addTileSets( model, lands ); + p->bank.setAbsPath( model->texturePath().toUtf8().constData() ); + // Save to file NLMISC::COFile f; bool b = f.open( fileName, false, false, false ); From ac73999f07511a44124479e203cba825cb2cb820 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:14:41 +0200 Subject: [PATCH 191/282] Set teh current selection to row 0 --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 7 +++++++ code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 1 + 2 files changed, 8 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index df1194e4b..5a77f54e7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -749,6 +749,13 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->tileBankTexturePathPB->setText( "..." ); else m_ui->tileBankTexturePathPB->setText( path ); + + QModelIndex idx = m_tileModel->index( 0, 0 ); + if( idx.isValid() ) + m_ui->tileSetLV->setCurrentIndex( idx ); + + if( m_ui->landLW->count() > 0 ) + m_ui->landLW->setCurrentRow( 0 ); } TileModel* TileEditorMainWindow::createTileModel() diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index f51413026..7be0ebeb7 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -168,5 +168,6 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > model->setTexturePath( p->bank.getAbsPath().c_str() ); + return false; } From ddd687325f1329f39d0fa16c7a0ae25effcd1eb0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:15:14 +0200 Subject: [PATCH 192/282] Close the loaded file and return true... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 7be0ebeb7..eb1e9a589 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -168,6 +168,7 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > model->setTexturePath( p->bank.getAbsPath().c_str() ); + file.close(); - return false; + return true; } From 4d54cca6a01a14587cdb76b40b210ad3260a1756 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:20:29 +0200 Subject: [PATCH 193/282] Copyright headers... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/land.h | 39 +++++++++++++------ .../plugins/tile_editor/land_edit_dialog.cpp | 17 ++++++++ .../plugins/tile_editor/land_edit_dialog.h | 17 ++++++++ .../plugins/tile_editor/tilebank_loader.cpp | 17 ++++++++ .../src/plugins/tile_editor/tilebank_loader.h | 16 ++++++++ 5 files changed, 95 insertions(+), 11 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h index 37b0d83c6..8538d7b08 100644 --- a/code/studio/src/plugins/tile_editor/land.h +++ b/code/studio/src/plugins/tile_editor/land.h @@ -1,14 +1,31 @@ -#ifndef LAND_H -#define LAND_H - -#include - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef LAND_H +#define LAND_H + +#include + struct Land { QString name; - QStringList tilesets; -}; - - -#endif - + QStringList tilesets; +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp index 87c66aa9c..40fbf3024 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "land_edit_dialog.h" LandEditDialog::LandEditDialog( QWidget *parent ) : diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h index 1ada1c23e..ac3762b46 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.h +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef LAND_EDIT_DLG_H #define LAND_EDIT_DLG_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index eb1e9a589..b8ab201e8 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "tilebank_loader.h" #include "tile_model.h" diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h index b213cb309..1f3498d6e 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.h +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -1,3 +1,19 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + #ifndef TILEBANK_LOADER_H #define TILEBANK_LOADER_H From 7b1ee54427e53cc8c658d884028a67206d99fece Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 14:28:17 +0200 Subject: [PATCH 194/282] Show the image that belongs to the channel that is selected. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 53 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 8 +++ .../tile_editor/tile_editor_main_window.ui | 14 ++--- .../src/plugins/tile_editor/tile_item.cpp | 4 +- .../src/plugins/tile_editor/tile_item.h | 5 ++ 5 files changed, 76 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 5a77f54e7..66a73cfd1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -168,6 +168,17 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect( m_ui->actionOpenTileBank, SIGNAL( triggered() ), this, SLOT( open() ) ); connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); + + connect( m_ui->diffuse128BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); + connect( m_ui->diffuse256BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); + connect( m_ui->diffuseTrBT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); + connect( m_ui->additive128BT, SIGNAL( toggled( bool ) ), this, SLOT( onAdditiveToggled( bool ) ) ); + connect( m_ui->additive256BT, SIGNAL( toggled( bool ) ), this, SLOT( onAdditiveToggled( bool ) ) ); + connect( m_ui->additiveTrBT, SIGNAL( toggled( bool ) ), this, SLOT( onAdditiveToggled( bool ) ) ); + connect( m_ui->alphaTrBT, SIGNAL( toggled( bool ) ), this, SLOT( onAlphaToggled( bool ) ) ); + + connect( m_ui->tileViewTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( onTabChanged( int ) ) ); + } TileEditorMainWindow::~TileEditorMainWindow() @@ -601,6 +612,43 @@ void TileEditorMainWindow::onOrientedStateChanged( int state ) node->setOriented( false ); } +void TileEditorMainWindow::onDiffuseToggled( bool b ) +{ + if( !b ) + return; + + TileItemNode::setDisplayChannel( TileModel::TileDiffuse ); + updateTab(); +} + +void TileEditorMainWindow::onAdditiveToggled( bool b ) +{ + if( !b ) + return; + + TileItemNode::setDisplayChannel( TileModel::TileAdditive ); + updateTab(); +} + +void TileEditorMainWindow::onAlphaToggled( bool b ) +{ + if( !b ) + return; + + TileItemNode::setDisplayChannel( TileModel::TileAlpha ); + updateTab(); +} + +void TileEditorMainWindow::onTabChanged( int tab ) +{ + if( tab == -1 ) + return; + + m_ui->diffuse128BT->setChecked( true ); + m_ui->diffuse256BT->setChecked( true ); + m_ui->diffuseTrBT->setChecked( true ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QModelIndex idx = m_ui->tileSetLV->currentIndex(); @@ -758,6 +806,11 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->landLW->setCurrentRow( 0 ); } +void TileEditorMainWindow::updateTab() +{ + m_ui->tileViewTabWidget->currentWidget()->repaint(); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 022348ab5..2c4286377 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -72,6 +72,12 @@ private Q_SLOTS: void onOrientedStateChanged( int state ); + void onDiffuseToggled( bool b ); + void onAdditiveToggled( bool b ); + void onAlphaToggled( bool b ); + + void onTabChanged( int tab ); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); @@ -85,6 +91,8 @@ private: void onTileSetRenamed( const QString &oldname, const QString &newname ); void onTileBankLoaded(); + void updateTab(); + TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 2e936aa8b..f45951aba 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -57,7 +57,7 @@ - + Diffuse @@ -67,7 +67,7 @@ - + Additive @@ -115,7 +115,7 @@ - + Diffuse @@ -128,7 +128,7 @@ - + Additive @@ -185,7 +185,7 @@ - + Diffuse @@ -195,14 +195,14 @@ - + Additive - + Alpha diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 76bf7c67e..7ae177220 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -264,6 +264,8 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// +TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; + TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) { m_tileFilename[channel] = filename; @@ -294,7 +296,7 @@ QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) QVariant TileItemNode::data(int column, int role) const { // find some way to know which file/bitmap to display - QString tileFilename = m_tileFilename[TileModel::TileDiffuse]; + QString tileFilename = m_tileFilename[s_displayChannel]; if(role == TileModel::TilePixmapRole || role == Qt::DecorationRole) { diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 3fad517c3..4e00c12c3 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -115,10 +115,15 @@ public: QString getTileFilename(TileModel::TTileChannel channel); void setId( int id ){ m_tileId = id; } int id() const{ return m_tileId; } + + static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } + private: int m_tileId; QMap m_tileFilename; QMap m_tileWidget; + + static TileModel::TTileChannel s_displayChannel; }; #endif // TILE_ITEM_H From 4bff87ca367e46ad6006982c6d769343871550ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 14:39:19 +0200 Subject: [PATCH 195/282] Replace and delete image should be applied to the correct channel now. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 4 ++-- code/studio/src/plugins/tile_editor/tile_item.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 66a73cfd1..a2b2525ca 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -728,7 +728,7 @@ void TileEditorMainWindow::onActionDeleteImage( int tabId ) } TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileModel::TileDiffuse, "" ); + n->setTileFilename( TileItemNode::displayChannel(), "" ); } void TileEditorMainWindow::onActionReplaceImage( int tabId ) @@ -752,7 +752,7 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) return; TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileModel::TileDiffuse, fileName ); + n->setTileFilename( TileItemNode::displayChannel(), fileName ); } void TileEditorMainWindow::onTileSetRemoved( const QString &set ) diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 4e00c12c3..5c5f8017c 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -117,6 +117,7 @@ public: int id() const{ return m_tileId; } static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } + static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } private: int m_tileId; From eee43ad1ea6a4e88e03372414454fb05c7da691c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:29:50 +0200 Subject: [PATCH 196/282] 128 and 256 tiles don't have alpha, so no need to load/save them. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 4 ++-- code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index b8ab201e8..238a41a52 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -77,7 +77,7 @@ public: TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); } @@ -96,7 +96,7 @@ public: TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index faec90bc4..bca62533d 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -76,7 +76,7 @@ public: for( int i = 0; i < node->childCount(); i++ ) { TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) { QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); From ac643d2bb91009a7ad0587935e0e20ab42d0e16f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:40:02 +0200 Subject: [PATCH 197/282] Should only add 1 tile here... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index bca62533d..fc686c3ad 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -76,11 +76,11 @@ public: for( int i = 0; i < node->childCount(); i++ ) { TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + NL3D::CTile *tile = addTileToSet( set, type ); + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) { QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); - - NL3D::CTile *tile = addTileToSet( set, type ); tile->setFileName( channelToTBitmap( TileModel::TTileChannel( j ) ) , fn.toUtf8().constData() ); } } From 0cef115a74b67eca03f31382472803d8d64ba6ff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:44:02 +0200 Subject: [PATCH 198/282] Should store the filename after opening.. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a2b2525ca..cc4e5e6b0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -259,6 +259,8 @@ void TileEditorMainWindow::open() // Put the loaded data into the GUI onTileBankLoaded(); + + m_fileName = fn; } void TileEditorMainWindow::onZoomFactor(int level) From a994f23948ebc21c20b6a83ce09bbdfadd3898da Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:55:09 +0200 Subject: [PATCH 199/282] When hitting 'save as' ask for a filename even if one is set. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 21 ++++++++++++------- .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index cc4e5e6b0..ee6221229 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -200,23 +200,28 @@ TileEditorMainWindow::~TileEditorMainWindow() void TileEditorMainWindow::save() { - saveAs(); + if( m_fileName.isEmpty() ) + saveAs(); + else + saveAs( m_fileName ); } void TileEditorMainWindow::saveAs() { - if( m_fileName.isEmpty() ) - { - m_fileName = QFileDialog::getSaveFileName( this, + QString fn = QFileDialog::getSaveFileName( this, tr( "Save TileBank as..." ), "", tr( "TileBank files (*.tilebank)" ) ); - if( m_fileName.isEmpty() ) - return; + if( fn.isEmpty() ) + return; - } + saveAs( fn ); +} + +void TileEditorMainWindow::saveAs( const QString &fn ) +{ QList< QString > landNames; int c = m_ui->landLW->count(); @@ -227,7 +232,7 @@ void TileEditorMainWindow::saveAs() } TileBankSaver saver; - bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, m_lands ); + bool ok = saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); if( !ok ) { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 2c4286377..d98ec9651 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -47,6 +47,7 @@ public: public Q_SLOTS: void save(); void saveAs(); + void saveAs( const QString &fn ); void open(); private Q_SLOTS: From f980ff7bee126cc7ef452f6bf499c44cc01584f0 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 31 Jul 2014 19:57:22 +0200 Subject: [PATCH 200/282] Added tag ryzomcore/v0.9.1 for changeset 79776c337176 --- .hgtags | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.hgtags b/.hgtags index cb11e3e8b..106c1e722 100644 --- a/.hgtags +++ b/.hgtags @@ -1,8 +1,4 @@ -a409552f83cb55a5c20f867fd7bcae1d0083d01a ryzomcore_0_8_0 -a409552f83cb55a5c20f867fd7bcae1d0083d01a ryzomcore_0_8_0 -0000000000000000000000000000000000000000 ryzomcore_0_8_0 -0000000000000000000000000000000000000000 ryzomcore_0_8_0 -4eddbaff0c5e5d685db96ee3e8427aa0fd96ac83 ryzomcore_0_8_0 - -950d650ca92e6041611258d7e5131ccf661e4ec2 latest-graft-to-default -950d650ca92e6041611258d7e5131ccf661e4ec2 latest-merge-from-default +950d650ca92e6041611258d7e5131ccf661e4ec2 compatibility-merge +4eddbaff0c5e5d685db96ee3e8427aa0fd96ac83 ryzomcore/v0.8.0 +00d9b6e29e95f56785fbf85abe60afd34674f402 ryzomcore/v0.9.0 +79776c337176dd5b02e1a74fe5dfb703b91747aa ryzomcore/v0.9.1 From 1265d6b064ed1d1ed925d4aad2ae2d16c6ae98f9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 31 Jul 2014 23:23:52 +0200 Subject: [PATCH 201/282] Line endings... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/land.h | 28 +++---- .../src/plugins/tile_editor/tile_item.cpp | 10 +-- .../plugins/tile_editor/tile_item_delegate.h | 82 +++++++++---------- .../src/plugins/tile_editor/tile_model.cpp | 82 +++++++++---------- 4 files changed, 101 insertions(+), 101 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h index 8538d7b08..93d244d9d 100644 --- a/code/studio/src/plugins/tile_editor/land.h +++ b/code/studio/src/plugins/tile_editor/land.h @@ -1,17 +1,17 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 7ae177220..d2fa3793f 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -307,11 +307,11 @@ QVariant TileItemNode::data(int column, int role) const // Retrieve the target tile size. uint32 tileSize = TileModel::getTileTypeSize(parent->getTileType()); - if(tileFilename.isEmpty() || tileFilename == "empty") - tileFilename = ":/placeHolder/images/empty_image.png"; - - QPixmap pixmap;// = new QPixmap(); - if(!pixmap.load(tileFilename)) + if(tileFilename.isEmpty() || tileFilename == "empty") + tileFilename = ":/placeHolder/images/empty_image.png"; + + QPixmap pixmap;// = new QPixmap(); + if(!pixmap.load(tileFilename)) nlinfo("failed to load %s", tileFilename.toAscii().data()); if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) diff --git a/code/studio/src/plugins/tile_editor/tile_item_delegate.h b/code/studio/src/plugins/tile_editor/tile_item_delegate.h index 90c831fb8..015f32021 100644 --- a/code/studio/src/plugins/tile_editor/tile_item_delegate.h +++ b/code/studio/src/plugins/tile_editor/tile_item_delegate.h @@ -12,44 +12,44 @@ // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -#ifndef TILE_ITEM_DELEGATE_H -#define TILE_ITEM_DELEGATE_H - -#include -#include -#include - -#include - -class TileItemDelegate : public QStyledItemDelegate - { - public: - - enum TZoomFactor - { - ZoomSmall = 0, - ZoomNormal = 1, - ZoomLarge = 2 - }; - - static const int PIXMAP_MARGIN = 5; - - TileItemDelegate(); - virtual ~TileItemDelegate(); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const; - - TZoomFactor getZoomFactor(); - void setZoomFactor(TZoomFactor zoomFactor); - -public Q_SLOTS: - void currentTab(int index); - - private: - TZoomFactor m_zoomFactor; - int m_imageHint; - }; - -#endif // TILE_ITEM_DELEGATE_H +// along with this program. If not, see . +#ifndef TILE_ITEM_DELEGATE_H +#define TILE_ITEM_DELEGATE_H + +#include +#include +#include + +#include + +class TileItemDelegate : public QStyledItemDelegate + { + public: + + enum TZoomFactor + { + ZoomSmall = 0, + ZoomNormal = 1, + ZoomLarge = 2 + }; + + static const int PIXMAP_MARGIN = 5; + + TileItemDelegate(); + virtual ~TileItemDelegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const; + + TZoomFactor getZoomFactor(); + void setZoomFactor(TZoomFactor zoomFactor); + +public Q_SLOTS: + void currentTab(int index); + + private: + TZoomFactor m_zoomFactor; + int m_imageHint; + }; + +#endif // TILE_ITEM_DELEGATE_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 99cc557e3..037be65cd 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -24,22 +24,22 @@ // Initialize the static members TileModel::TTileZoomFactor TileModel::CurrentZoomFactor; -TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) -{ - QVector rootData; - Q_FOREACH(QString header, headers) - rootData << header; - - rootItem = new Node(rootData); - - TileModel::CurrentZoomFactor = TileModel::TileZoom100; - m_indexDisplay = true; - m_fileDisplay = true; -} - -TileModel::~TileModel() -{ - delete rootItem; +TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) +{ + QVector rootData; + Q_FOREACH(QString header, headers) + rootData << header; + + rootItem = new Node(rootData); + + TileModel::CurrentZoomFactor = TileModel::TileZoom100; + m_indexDisplay = true; + m_fileDisplay = true; +} + +TileModel::~TileModel() +{ + delete rootItem; } Node *TileModel::getItem(const QModelIndex &index) const @@ -92,33 +92,33 @@ int TileModel::columnCount(const QModelIndex &parent) const return parentItem->columnCount(); } -QVariant TileModel::data(const QModelIndex &index, int role) const -{ - if(!index.isValid()) - return QVariant(); - - Node *item = static_cast(index.internalPointer()); - - // Translate the display role to the settings-specific role. - - if(role == Qt::DisplayRole) - { - if(m_indexDisplay && m_fileDisplay) - role = TileFilenameIndexRole; - else if(m_fileDisplay) - role = TileFilenameRole; - else if(m_indexDisplay) - role = TileIndexRole; - } - return item->data(index.column(), role); +QVariant TileModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + Node *item = static_cast(index.internalPointer()); + + // Translate the display role to the settings-specific role. + + if(role == Qt::DisplayRole) + { + if(m_indexDisplay && m_fileDisplay) + role = TileFilenameIndexRole; + else if(m_fileDisplay) + role = TileFilenameRole; + else if(m_indexDisplay) + role = TileIndexRole; + } + return item->data(index.column(), role); } -Qt::ItemFlags TileModel::flags(const QModelIndex &index) const -{ - if(!index.isValid()) - return Qt::ItemIsEnabled; - - return Qt::ItemIsEnabled|Qt::ItemIsSelectable; +Qt::ItemFlags TileModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return Qt::ItemIsEnabled; + + return Qt::ItemIsEnabled|Qt::ItemIsSelectable; } QVariant TileModel::headerData(int section, Qt::Orientation orientation, int role) const From 851afcf955e71db35eb2ae2b42bb9623e8fa3283 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 1 Aug 2014 02:34:57 +0200 Subject: [PATCH 202/282] Don't reload the pixmaps every time they are displayed... -.- --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_item.cpp | 64 +++++++++++++++---- .../src/plugins/tile_editor/tile_item.h | 6 +- .../src/plugins/tile_editor/tile_model.h | 1 + 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index d2fa3793f..b9064996e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -264,23 +264,71 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// + +class TileItemNodePvt +{ +public: + + bool loadImage( TileModel::TTileChannel channel, const QString &fn ) + { + QPixmap temp; + bool b = temp.load( fn ); + + if( !b ) + return false; + + pixmaps[ channel ] = temp; + + return true; + } + + void clearImage( TileModel::TTileChannel channel ) + { + pixmaps[ channel ] = QPixmap(); + } + + const QPixmap& pixMap( TileModel::TTileChannel channel ) const{ + return pixmaps[ channel ]; + } + +private: + QPixmap pixmaps[ TileModel::TileChannelCount ]; + +}; + TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) { - m_tileFilename[channel] = filename; m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); + + pvt = new TileItemNodePvt(); + + setTileFilename( channel, filename ); } TileItemNode::~TileItemNode() { + delete pvt; + pvt = NULL; + qDeleteAll(m_childItems); } -void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) +bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) { + QString fn = filename; + + if( filename.isEmpty() || ( filename == "empty" ) ) + fn = ":/placeHolder/images/empty_image.png"; + + bool b = pvt->loadImage( channel, fn ); + if( !b ) + return false; + m_tileFilename[channel] = filename; + return true; } QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) @@ -295,8 +343,7 @@ QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) QVariant TileItemNode::data(int column, int role) const { - // find some way to know which file/bitmap to display - QString tileFilename = m_tileFilename[s_displayChannel]; + QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; if(role == TileModel::TilePixmapRole || role == Qt::DecorationRole) { @@ -307,18 +354,13 @@ QVariant TileItemNode::data(int column, int role) const // Retrieve the target tile size. uint32 tileSize = TileModel::getTileTypeSize(parent->getTileType()); - if(tileFilename.isEmpty() || tileFilename == "empty") - tileFilename = ":/placeHolder/images/empty_image.png"; - - QPixmap pixmap;// = new QPixmap(); - if(!pixmap.load(tileFilename)) - nlinfo("failed to load %s", tileFilename.toAscii().data()); - if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) tileSize *= 2; else if(TileModel::CurrentZoomFactor == TileModel::TileZoom50) tileSize /= 2; + QPixmap pixmap = pvt->pixMap( TileItemNode::s_displayChannel ); + pixmap.scaled(tileSize, tileSize); return pixmap; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 5c5f8017c..611059ffa 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -104,6 +104,8 @@ private: TileModel::TNodeTileType m_nodeTileType; }; +class TileItemNodePvt; + class TileItemNode : public Node { public: @@ -111,7 +113,7 @@ public: virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; - void setTileFilename(TileModel::TTileChannel channel, QString filename); + bool setTileFilename(TileModel::TTileChannel channel, QString filename); QString getTileFilename(TileModel::TTileChannel channel); void setId( int id ){ m_tileId = id; } int id() const{ return m_tileId; } @@ -125,6 +127,8 @@ private: QMap m_tileWidget; static TileModel::TTileChannel s_displayChannel; + + TileItemNodePvt *pvt; }; #endif // TILE_ITEM_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index f2efdb8d4..e855f8871 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -34,6 +34,7 @@ public: TileDiffuse = 0, TileAdditive = 1, TileAlpha = 2, + TileChannelCount = 3 }; enum TNodeTileType From 1a49f9fedb30ac1aad8b80567678ec5cdae805d2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 1 Aug 2014 02:38:04 +0200 Subject: [PATCH 203/282] Apply the current zoom factor! --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index b9064996e..20c9492af 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -361,7 +361,7 @@ QVariant TileItemNode::data(int column, int role) const QPixmap pixmap = pvt->pixMap( TileItemNode::s_displayChannel ); - pixmap.scaled(tileSize, tileSize); + pixmap = pixmap.scaled(tileSize, tileSize); return pixmap; } From ce53f5f26c083d828abd60fd4a66d568d3209309 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Fri, 1 Aug 2014 16:01:35 +0530 Subject: [PATCH 204/282] API key management calender --HG-- branch : Gsoc14-ryzomAppImprovements --- .../server/ryzom_ams/www/html/templates/layout.tpl | 11 ++++++++++- .../ryzom_ams/www/html/templates/layout_plugin.tpl | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl index 9cd01cda8..69b99dbac 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout.tpl @@ -235,7 +235,16 @@ _("status").innerHTML = "upload Aborted"; } - + + + + + + diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl index 9fb68400a..1a84ff3bf 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_plugin.tpl @@ -3,7 +3,7 @@ {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element} {if $arrkey eq $smarty.get.name} -{include file=$element.template_path} +{include file=$element.TemplatePath} {/if} {/foreach} {/if} From 9aabaebc3819fc80efcf565eb4b920d06d09a3ca Mon Sep 17 00:00:00 2001 From: kervala Date: Fri, 1 Aug 2014 17:00:08 +0200 Subject: [PATCH 205/282] Fixed: Compilation of PACS tools without NeL 3D --- code/nel/tools/pacs/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/nel/tools/pacs/CMakeLists.txt b/code/nel/tools/pacs/CMakeLists.txt index 405476ed6..c3a5a71f6 100644 --- a/code/nel/tools/pacs/CMakeLists.txt +++ b/code/nel/tools/pacs/CMakeLists.txt @@ -1 +1,9 @@ -SUBDIRS(build_ig_boxes build_indoor_rbank build_rbank) +IF(WITH_3D) + ADD_SUBDIRECTORY(build_ig_boxes) + + IF(WITH_LIGO) + ADD_SUBDIRECTORY(build_rbank) + ENDIF() +ENDIF() + +ADD_SUBDIRECTORY(build_indoor_rbank) From a29f525c9937125fe8c6281e96312e7e7cbbfdbd Mon Sep 17 00:00:00 2001 From: kervala Date: Fri, 1 Aug 2014 17:17:53 +0200 Subject: [PATCH 206/282] Fixed: Some NeL tools in 3d directory don't need NeL 3D --- code/nel/tools/3d/CMakeLists.txt | 66 ++++++++++++++++---------------- code/nel/tools/CMakeLists.txt | 4 +- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/code/nel/tools/3d/CMakeLists.txt b/code/nel/tools/3d/CMakeLists.txt index a07e8c53a..2ac0ac1c5 100644 --- a/code/nel/tools/3d/CMakeLists.txt +++ b/code/nel/tools/3d/CMakeLists.txt @@ -1,40 +1,42 @@ IF(WITH_NEL_TOOLS) - + IF(WITH_3D) + SUBDIRS( + anim_builder + animation_set_builder + build_clod_bank + build_clodtex + build_coarse_mesh + build_far_bank + build_shadow_skin + build_smallbank + cluster_viewer + file_info + ig_add + ig_elevation + ig_info + ig_lighter + lightmap_optimizer + zone_dependencies + zone_ig_lighter + zone_lighter + zone_welder + shapes_exporter + shape2obj + zone_check_bind + zone_dump + zviewer) + ENDIF() + SUBDIRS( - build_coarse_mesh - build_far_bank - build_smallbank - ig_lighter - ig_elevation - lightmap_optimizer - zone_dependencies - zone_ig_lighter - zone_lighter - zone_welder - animation_set_builder - anim_builder - build_clod_bank - build_clodtex build_interface - build_shadow_skin - cluster_viewer - file_info get_neighbors - ig_add - ig_info - shapes_exporter tga_cut - tga_resize - shape2obj - zone_check_bind - zone_dump - zviewer) - -ENDIF(WITH_NEL_TOOLS) + tga_resize) +ENDIF() # For tools selection of only max plugins -IF(WIN32) +IF(WIN32 AND WITH_3D) IF(MFC_FOUND) ADD_SUBDIRECTORY(object_viewer) IF(WITH_NEL_MAXPLUGIN) @@ -44,9 +46,9 @@ IF(WIN32) ENDIF(MAXSDK_FOUND) ENDIF(WITH_NEL_MAXPLUGIN) ENDIF(MFC_FOUND) -ENDIF(WIN32) +ENDIF() -IF(WITH_NEL_TOOLS) +IF(WITH_NEL_TOOLS AND WITH_3D) IF(WIN32) # ADD_SUBDIRECTORY(lightmap_optimizer) IF(MFC_FOUND) @@ -71,5 +73,5 @@ IF(WITH_NEL_TOOLS) #crash_log_analyser #shapes_exporter -ENDIF(WITH_NEL_TOOLS) +ENDIF() diff --git a/code/nel/tools/CMakeLists.txt b/code/nel/tools/CMakeLists.txt index abc5dff02..2c1f641a0 100644 --- a/code/nel/tools/CMakeLists.txt +++ b/code/nel/tools/CMakeLists.txt @@ -6,9 +6,7 @@ IF(WITH_NEL_TOOLS) ENDIF(WITH_NEL_TOOLS) # Max plugins are under the 3d directory as well. -IF(WITH_3D) - ADD_SUBDIRECTORY(3d) -ENDIF(WITH_3D) +ADD_SUBDIRECTORY(3d) # Don't add other subdirectories if only max plugins are selected. IF(WITH_NEL_TOOLS) From ffb7df28fffbbc709b36d7c67b911c70dac687fa Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 2 Aug 2014 10:57:31 +0200 Subject: [PATCH 207/282] Fixed: VC++ 2010 compiler bug in for loop variables reuse --- code/nel/tools/3d/build_interface/main.cpp | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index be39b7d17..da652b0cc 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -113,18 +113,17 @@ void putPixel(uint8 *dst, uint8 *src, bool alphaTransfert) // *************************************************************************** bool putIn (NLMISC::CBitmap *pSrc, NLMISC::CBitmap *pDst, sint32 x, sint32 y, bool alphaTransfert=true) { - uint32 a, b; - uint8 *rSrcPix = &pSrc->getPixels()[0]; uint8 *rDstPix = &pDst->getPixels()[0]; uint wSrc= pSrc->getWidth(); uint hSrc= pSrc->getHeight(); - for (b = 0; b < hSrc; ++b) - for (a = 0; a < wSrc; ++a) + for (uint b = 0; b < hSrc; ++b) + for (uint a = 0; a < wSrc; ++a) { if (rDstPix[4*((x+a)+(y+b)*pDst->getWidth())+3] != 0) return false; + // write putPixel(rDstPix + 4*((x+a)+(y+b)*pDst->getWidth()), rSrcPix+ 4*(a+b*pSrc->getWidth()), alphaTransfert); } @@ -135,9 +134,9 @@ bool putIn (NLMISC::CBitmap *pSrc, NLMISC::CBitmap *pDst, sint32 x, sint32 y, bo // expand on W if(wSrcgetWidth()), rDstPix + 4*((x+wSrc-1)+(y+b)*pDst->getWidth()), alphaTransfert); } @@ -146,9 +145,9 @@ bool putIn (NLMISC::CBitmap *pSrc, NLMISC::CBitmap *pDst, sint32 x, sint32 y, bo // expand on H if(hSrcgetWidth()), rDstPix + 4*((x+a)+(y+hSrc-1)*pDst->getWidth()), alphaTransfert); } @@ -252,12 +251,12 @@ int main(int nNbArg, char **ppArgs) } vector AllMaps; - sint32 i, j; + sint32 j; // Load all maps sint32 mapSize = (sint32)AllMapNames.size(); AllMaps.resize( mapSize ); - for( i = 0; i < mapSize; ++i ) + for(sint i = 0; i < mapSize; ++i ) { try { @@ -275,7 +274,7 @@ int main(int nNbArg, char **ppArgs) } // Sort all maps by decreasing size - for (i = 0; i < mapSize-1; ++i) + for (sint i = 0; i < mapSize-1; ++i) for (j = i+1; j < mapSize; ++j) { NLMISC::CBitmap *pBI = AllMaps[i]; @@ -303,7 +302,7 @@ int main(int nNbArg, char **ppArgs) vector UVMin, UVMax; UVMin.resize (mapSize, NLMISC::CUV(0.0f, 0.0f)); UVMax.resize (mapSize, NLMISC::CUV(0.0f, 0.0f)); - for (i = 0; i < mapSize; ++i) + for (sint i = 0; i < mapSize; ++i) { sint32 x, y; while (!tryAllPos(AllMaps[i], &GlobalMask, x, y)) @@ -349,7 +348,7 @@ int main(int nNbArg, char **ppArgs) } // Convert UV from pixel to ratio - for (i = 0; i < mapSize; ++i) + for (sint i = 0; i < mapSize; ++i) { UVMin[i].U = UVMin[i].U / (float)GlobalTexture.getWidth(); UVMin[i].V = UVMin[i].V / (float)GlobalTexture.getHeight(); @@ -394,7 +393,7 @@ int main(int nNbArg, char **ppArgs) FILE *f = fopen (fmtName.c_str(), "wt"); if (f != NULL) { - for (i = 0; i < mapSize; ++i) + for (sint i = 0; i < mapSize; ++i) { // get the string whitout path string fileName= CFile::getFilename(AllMapNames[i]); @@ -442,6 +441,8 @@ int main(int nNbArg, char **ppArgs) nlwarning("Can't parse %s", bufTmp); continue; } + + sint i; sTGAname = toLower(string(tgaName)); string findTGAName; From b71ec9e7d45d0aaee9233a5f4cb6667f4b7b2fbe Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 2 Aug 2014 10:58:50 +0200 Subject: [PATCH 208/282] Fixed: build_interface currently only works with 32 bits bitmaps --- code/nel/tools/3d/build_interface/main.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/code/nel/tools/3d/build_interface/main.cpp b/code/nel/tools/3d/build_interface/main.cpp index da652b0cc..343673b34 100644 --- a/code/nel/tools/3d/build_interface/main.cpp +++ b/code/nel/tools/3d/build_interface/main.cpp @@ -258,16 +258,24 @@ int main(int nNbArg, char **ppArgs) AllMaps.resize( mapSize ); for(sint i = 0; i < mapSize; ++i ) { + NLMISC::CBitmap *pBtmp = NULL; + try { - NLMISC::CBitmap *pBtmp = new NLMISC::CBitmap; + pBtmp = new NLMISC::CBitmap; NLMISC::CIFile inFile; - inFile.open( AllMapNames[i] ); - pBtmp->load(inFile); + if (!inFile.open( AllMapNames[i] )) throw NLMISC::Exception("Unable to open " + AllMapNames[i]); + + uint8 colors = pBtmp->load(inFile); + + if (colors != 32) throw NLMISC::Exception(AllMapNames[i] + " is using " + toString(colors) + " bits colors, only 32 bit supported!"); + AllMaps[i] = pBtmp; } catch (const NLMISC::Exception &e) { + if (pBtmp) delete pBtmp; + outString (string("ERROR :") + e.what()); return -1; } From 7aedffce9a1fded8ca22dc070b6a35b68fd3f3eb Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 2 Aug 2014 11:18:24 +0200 Subject: [PATCH 209/282] Changed: #172 XML floating point serialization not using neutral culture (for VC++ 2005 and up) --- code/nel/include/nel/misc/o_xml.h | 3 +++ code/nel/src/misc/o_xml.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/code/nel/include/nel/misc/o_xml.h b/code/nel/include/nel/misc/o_xml.h index 5933b7ebc..a532f0342 100644 --- a/code/nel/include/nel/misc/o_xml.h +++ b/code/nel/include/nel/misc/o_xml.h @@ -178,6 +178,9 @@ private: // Error message std::string _ErrorString; + + // System dependant structure for locale + void* _Locale; }; diff --git a/code/nel/src/misc/o_xml.cpp b/code/nel/src/misc/o_xml.cpp index 005ef8000..0fbe3dade 100644 --- a/code/nel/src/misc/o_xml.cpp +++ b/code/nel/src/misc/o_xml.cpp @@ -23,6 +23,11 @@ // Include from libxml2 #include +#if defined(NL_OS_WINDOWS) && defined(NL_COMP_VC_VERSION) && NL_COMP_VC_VERSION >= 80 +#define USE_LOCALE_SPRINTF +#include +#endif + using namespace std; #ifdef DEBUG_NEW @@ -38,11 +43,22 @@ const char SEPARATOR = ' '; // *************************************************************************** +#ifdef USE_LOCALE_SPRINTF + +#define writenumber(src,format,digits) \ + char number_as_cstring [digits+1]; \ + _sprintf_l( number_as_cstring, format, (_locale_t)_Locale, src ); \ + serialSeparatedBufferOut( number_as_cstring ); + +#else + #define writenumber(src,format,digits) \ char number_as_cstring [digits+1]; \ sprintf( number_as_cstring, format, src ); \ serialSeparatedBufferOut( number_as_cstring ); +#endif + // *************************************************************************** // XML callbacks // *************************************************************************** @@ -133,6 +149,13 @@ COXml::COXml () : IStream (false /* Output mode */) // Push begin _PushBegin = false; + +#ifdef USE_LOCALE_SPRINTF + // create C numeric locale + _Locale = _create_locale(LC_NUMERIC, "C"); +#else + _Locale = NULL; +#endif } // *************************************************************************** @@ -192,6 +215,10 @@ COXml::~COXml () { // Flush document to the internal stream flush (); + +#ifdef USE_LOCALE_SPRINTF + if (_Locale) _free_locale((_locale_t)_Locale); +#endif } // *************************************************************************** From 175af2fa749284da560c5b3becd18180800c82d4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 04:15:12 +0200 Subject: [PATCH 210/282] Added checks. Yes it's horrible and needs to be refactored. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 27 +- .../src/plugins/tile_editor/tile_item.cpp | 266 +++++++++++++++++- .../src/plugins/tile_editor/tile_item.h | 13 +- .../src/plugins/tile_editor/tile_model.cpp | 8 +- .../src/plugins/tile_editor/tile_model.h | 6 +- .../plugins/tile_editor/tilebank_loader.cpp | 4 +- 6 files changed, 305 insertions(+), 19 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index ee6221229..7c9ec8f52 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -656,6 +656,14 @@ void TileEditorMainWindow::onTabChanged( int tab ) m_ui->diffuseTrBT->setChecked( true ); } +TileModel::TNodeTileType tabToType( int tabId ) +{ + if( tabId >= TileModel::TileNodeTypeCount ) + return TileModel::TileNodeTypeCount; + + return TileModel::TNodeTileType( tabId ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QModelIndex idx = m_ui->tileSetLV->currentIndex(); @@ -683,10 +691,27 @@ void TileEditorMainWindow::onActionAddTile(int tabId) int c = n->childCount(); + TileModel::TNodeTileType type = tabToType( tabId ); + QStringListIterator itr( fileNames ); while( itr.hasNext() ) { - Node *newNode = TileModel::createItemNode( c, TileModel::TileDiffuse, itr.next() ); + TileItemNode *newNode = TileModel::createItemNode( type, c, TileModel::TileDiffuse, itr.next() ); + if( newNode->hasError() ) + { + QString error = newNode->getLastError(); + error += "\nContinue?"; + + int reply = QMessageBox::question( this, + tr( "Error adding tile" ), + error, + QMessageBox::Yes, QMessageBox::No ); + if( reply != QMessageBox::Yes ) + break; + else + continue; + } + n->appendRow( newNode ); c++; } diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 20c9492af..d60fb4bbb 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -22,6 +22,8 @@ #include +#include + Node::Node() : m_parentItem(0) { } @@ -264,18 +266,230 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// +NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) +{ + NL3D::CTile::TBitmap bm; + + switch( channel ) + { + case TileModel::TileDiffuse: bm = NL3D::CTile::diffuse; break; + case TileModel::TileAdditive: bm = NL3D::CTile::additive; break; + case TileModel::TileAlpha: bm = NL3D::CTile::alpha; break; + } + + return bm; +} class TileItemNodePvt { public: + + TileItemNodePvt() + { + for( int i = 0; i < TileModel::TileChannelCount; i++ ) + m_borderFirst[ i ] = false; + + m_id = -1; + } + + bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) + { + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + + return true; + } + + int getWidthForType( TileModel::TNodeTileType type, TileModel::TTileChannel channel ) + { + int width = -1; + + switch( type ) + { + case TileModel::Tile128: width = 128; break; + case TileModel::Tile256: width = 256; break; + case TileModel::TileTransition: + { + if( channel != TileModel::TileAlpha ) + width = 128; + break; + } + + case TileModel::TileDisplacement: width = 32; break; + } + + return width; + } + + NL3D::CTileSet::TError checkTile( TileModel::TTileChannel channel ) + { + if( m_type == TileModel::TileDisplacement ) + return NL3D::CTileSet::ok; + + if( channel == TileModel::TileAdditive ) + return NL3D::CTileSet::ok; + + int pixel; + int component; + int index; + + NL3D::CTileSet set; + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + + NL3D::CTileSet::TError error = NL3D::CTileSet::ok; + + switch( m_type ) + { + case TileModel::Tile128: + error = set.checkTile128( bm, m_border[ channel ], pixel, component ); + break; + case TileModel::Tile256: + error = set.checkTile256( bm, m_border[ channel ], pixel, component ); + break; + case TileModel::TileTransition: + if( channel != TileModel::TileAlpha ) + error = set.checkTile128( bm, m_border[ channel ], pixel, component ); + else + error = set.checkTileTransition( NL3D::CTileSet::TTransition( m_id ), bm, m_border[ channel ], index, pixel, component ); + break; + } + + if( error == NL3D::CTileSet::ok ) + return NL3D::CTileSet::ok; + if( error == NL3D::CTileSet::addFirstA128128 ) + return NL3D::CTileSet::addFirstA128128; + +/* + enum TError { ok=0, topInterfaceProblem, bottomInterfaceProblem, leftInterfaceProblem, + rightInterfaceProblem, addFirstA128128, topBottomNotTheSame, rightLeftNotTheSame, + sizeInvalide, errorCount }; +*/ + static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; + + if( error != NL3D::CTileSet::ok ) + { + m_lastError = "ERROR: "; + m_lastError += NL3D::CTileSet::getErrorMessage( error ); + m_lastError += "\n"; + + switch( m_type ) + { + case TileModel::Tile128: + case TileModel::Tile256: + m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); + break; + + case TileModel::TileTransition: + if( channel != TileModel::TileAlpha ) + { + m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); + } + else + { + if ((error==NL3D::CTileSet::topInterfaceProblem)||(error==NL3D::CTileSet::bottomInterfaceProblem)|| + (error==NL3D::CTileSet::leftInterfaceProblem)||(error==NL3D::CTileSet::rightInterfaceProblem)|| + (error==NL3D::CTileSet::topBottomNotTheSame)||(error==NL3D::CTileSet::rightLeftNotTheSame) + ||(error==NL3D::CTileSet::topInterfaceProblem)) + { + if( index != -1 ) + { + m_lastError += QString( "tile: %1 pixel: %2 component: %3" ).arg( index ).arg( pixel ).arg( comp[ component ] ); + } + else + { + m_lastError += QString( "incompatible with a 128 tile, pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); + } + } + + } + break; + } + } + + return error; + } + + bool checkPixmap( TileModel::TTileChannel channel, QPixmap &pixmap ) + { + int w = pixmap.width(); + int h = pixmap.height(); + + if( w != h ) + { + m_lastError = QObject::tr( "Not a square texture." ); + return false; + } + + int width = getWidthForType( m_type, channel ); + + if( width != -1 ) + { + if( width != w ) + { + m_lastError = QObject::tr( "Not the proper size." ); + return false; + } + } + + std::vector< NLMISC::CBGRA > pixels; + + pixmapToCBGRA( pixmap, pixels ); + + m_border[ channel ].set( w, h, pixels ); + + NL3D::CTileSet::TError error = checkTile( channel ); + if( error == NL3D::CTileSet::addFirstA128128 ) + { + m_borderFirst[ channel ] = true; + return true; + } + + if( error != NL3D::CTileSet::ok ) + return false; + + return true; + } - bool loadImage( TileModel::TTileChannel channel, const QString &fn ) + bool loadImage( TileModel::TTileChannel channel, const QString &fn, bool empty = false ) { QPixmap temp; bool b = temp.load( fn ); if( !b ) + { + m_lastError = QObject::tr( "Cannot open file %1" ).arg( fn ); return false; + } + + if( !empty ) + { + if( !checkPixmap( channel, temp ) ) + return false; + } pixmaps[ channel ] = temp; @@ -291,19 +505,34 @@ public: return pixmaps[ channel ]; } + void setType( TileModel::TNodeTileType type ){ m_type = type; } + void setId( int id ){ m_id = id; } + int id() const{ return m_id; } + + QString getLastError() const{ return m_lastError; } + bool borderFirst( TileModel::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } + private: QPixmap pixmaps[ TileModel::TileChannelCount ]; - + TileModel::TNodeTileType m_type; + NL3D::CTileBorder m_border[ TileModel::TileChannelCount ]; + int m_id; + QString m_lastError; + bool m_borderFirst[ TileModel::TileChannelCount ]; }; TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; -TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) +TileItemNode::TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) { m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); pvt = new TileItemNodePvt(); + pvt->setType( type ); + pvt->setId( tileId ); + + m_hasError = false; setTileFilename( channel, filename ); } @@ -319,11 +548,16 @@ TileItemNode::~TileItemNode() bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) { QString fn = filename; + bool empty = false; if( filename.isEmpty() || ( filename == "empty" ) ) + { fn = ":/placeHolder/images/empty_image.png"; + empty = true; + } - bool b = pvt->loadImage( channel, fn ); + bool b = pvt->loadImage( channel, fn, empty ); + m_hasError = !b; if( !b ) return false; @@ -341,6 +575,26 @@ QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) return itr.value(); } +void TileItemNode::setId( int id ) +{ + pvt->setId( id ); +} + +int TileItemNode::id() const +{ + return pvt->id(); +} + +QString TileItemNode::getLastError() const +{ + return pvt->getLastError(); +} + +bool TileItemNode::borderFirst() const +{ + return false; +} + QVariant TileItemNode::data(int column, int role) const { QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; @@ -375,11 +629,11 @@ QVariant TileItemNode::data(int column, int role) const } else if(role == TileModel::TileIndexRole) { - return QVariant("("+QString::number(m_tileId)+")"); + return QVariant("("+QString::number(pvt->id())+")"); } else if(role == TileModel::TileFilenameIndexRole) { - return QVariant(tileFilename + " ("+QString::number(m_tileId)+")"); + return QVariant(tileFilename + " ("+QString::number(pvt->id())+")"); } return QVariant(); diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 611059ffa..fc5443037 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -109,26 +109,31 @@ class TileItemNodePvt; class TileItemNode : public Node { public: - TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); + TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; bool setTileFilename(TileModel::TTileChannel channel, QString filename); QString getTileFilename(TileModel::TTileChannel channel); - void setId( int id ){ m_tileId = id; } - int id() const{ return m_tileId; } + void setId( int id ); + int id() const; + QString getLastError() const; + bool borderFirst() const; static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } + bool hasError() const{ return m_hasError; } + private: - int m_tileId; QMap m_tileFilename; QMap m_tileWidget; static TileModel::TTileChannel s_displayChannel; TileItemNodePvt *pvt; + + bool m_hasError; }; #endif // TILE_ITEM_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 037be65cd..d1ab0d238 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -197,7 +197,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode(transPos, TileDiffuse, QString("empty")); + TileItemNode *transTile= new TileItemNode( TileModel::TileTransition, transPos, TileDiffuse, QString("empty")); tileTrans->appendRow(transTile); } @@ -209,7 +209,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode(dispPos, TileDiffuse, QString("empty")); + TileItemNode *dispTile= new TileItemNode( TileModel::TileDisplacement, dispPos, TileDiffuse, QString("empty")); tileDisp->appendRow(dispTile); } @@ -219,9 +219,9 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) return tileSet; } -Node *TileModel::createItemNode( int id, TTileChannel channel, const QString &fileName ) +TileItemNode *TileModel::createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ) { - return new TileItemNode( id, channel, fileName ); + return new TileItemNode( type, id, channel, fileName ); } const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index e855f8871..c22a43091 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -23,6 +23,7 @@ class Node; class TileSetNode; +class TileItemNode; class TileModel : public QAbstractItemModel { @@ -42,7 +43,8 @@ public: Tile128 = 0, Tile256 = 1, TileTransition = 2, - TileDisplacement = 3 + TileDisplacement = 3, + TileNodeTypeCount = 4 }; enum TTileItemRole @@ -85,7 +87,7 @@ public: void swapRows( int a, int b ); TileSetNode *createTileSetNode(QString tileSetName); - static Node *createItemNode( int id, TTileChannel channel, const QString &fileName ); + static TileItemNode *createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ); static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 238a41a52..73c8007d8 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -75,7 +75,7 @@ public: int idx = set->getTile128( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileModel::Tile128, i, TileModel::TileDiffuse, "" ); for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { @@ -94,7 +94,7 @@ public: int idx = set->getTile256( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileModel::Tile256, i, TileModel::TileDiffuse, "" ); for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { From 49deedad7d32395d50c8f3220abc9fe1aa7776fd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 17:58:02 +0200 Subject: [PATCH 211/282] Save the tile border, etc data when saving. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_item.cpp | 23 +++-- .../src/plugins/tile_editor/tile_item.h | 9 +- .../plugins/tile_editor/tilebank_saver.cpp | 89 ++++++++++++++++--- 3 files changed, 101 insertions(+), 20 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index d60fb4bbb..fe1df0ebf 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -383,11 +383,6 @@ public: if( error == NL3D::CTileSet::addFirstA128128 ) return NL3D::CTileSet::addFirstA128128; -/* - enum TError { ok=0, topInterfaceProblem, bottomInterfaceProblem, leftInterfaceProblem, - rightInterfaceProblem, addFirstA128128, topBottomNotTheSame, rightLeftNotTheSame, - sizeInvalide, errorCount }; -*/ static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; if( error != NL3D::CTileSet::ok ) @@ -484,6 +479,8 @@ public: m_lastError = QObject::tr( "Cannot open file %1" ).arg( fn ); return false; } + + m_borderFirst[ channel ] = false; if( !empty ) { @@ -512,6 +509,8 @@ public: QString getLastError() const{ return m_lastError; } bool borderFirst( TileModel::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } + const NL3D::CTileBorder &border( TileModel::TTileChannel channel ){ return m_border[ channel ]; } + private: QPixmap pixmaps[ TileModel::TileChannelCount ]; TileModel::TNodeTileType m_type; @@ -590,9 +589,19 @@ QString TileItemNode::getLastError() const return pvt->getLastError(); } -bool TileItemNode::borderFirst() const +bool TileItemNode::borderFirst( TileModel::TTileChannel channel ) const +{ + return pvt->borderFirst( channel ); +} + +const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) const { - return false; + return pvt->border( channel ); +} + +int TileItemNode::alphaRot() const +{ + return 0; } QVariant TileItemNode::data(int column, int role) const diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index fc5443037..2e374061d 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -24,6 +24,11 @@ #include "tile_model.h" +namespace NL3D +{ + class CTileBorder; +} + class TileWidget; class Node @@ -118,7 +123,9 @@ public: void setId( int id ); int id() const; QString getLastError() const; - bool borderFirst() const; + bool borderFirst( TileModel::TTileChannel channel ) const; + const NL3D::CTileBorder& border( TileModel::TTileChannel channel ) const; + int alphaRot() const; static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index fc686c3ad..65559505a 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -96,19 +96,76 @@ public: } } + void setupTiles128( NL3D::CTileSet *set, TileTypeNode *node ) + { + TileItemNode *tileNode = NULL; + for( int i = 0; i < node->childCount(); i++ ) + { + tileNode = static_cast< TileItemNode* >( node->child( i ) ); + + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + { + TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + const NL3D::CTileBorder &border = tileNode->border( channel ); + + if( tileNode->borderFirst( channel ) ) + set->setBorder( bm, border ); + + set->setTile128( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); + } + } + } + + void setupTiles256( NL3D::CTileSet *set, TileTypeNode *node ) + { + TileItemNode *tileNode = NULL; + for( int i = 0; i < node->childCount(); i++ ) + { + tileNode = static_cast< TileItemNode* >( node->child( i ) ); + + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + { + TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + const NL3D::CTileBorder &border = tileNode->border( channel ); + + if( tileNode->borderFirst( channel ) ) + set->setBorder( bm, border ); + + set->setTile256( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); + } + } + } + void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) { - NL3D::CTileSetTransition *tr = set->getTransition( idx ); - int tid = tr->getTile(); - NL3D::CTile *tile = bank.getTile( tid ); + TileModel::TTileChannel channel; + NL3D::CTile::TBitmap bm; + NL3D::CTileSet::TTransition tr; - if( tile == NULL ) - return; + // Diffuse, Additive + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + { + channel =TileModel::TTileChannel( i ); + bm = channelToTBitmap( channel ); + tr = NL3D::CTileSet::TTransition( idx ); + const NL3D::CTileBorder &border = node->border( channel ); + + if( node->borderFirst( channel ) ) + set->setBorder( bm, border ); + set->setTileTransition( tr, node->getTileFilename( channel ).toUtf8().constData(), bm, bank, border ); + } - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + // Alpha { - QString fn = node->getTileFilename( TileModel::TTileChannel( i ) ); - tile->setFileName( channelToTBitmap( TileModel::TTileChannel( i ) ), fn.toUtf8().constData() ); + channel = TileModel::TileAlpha; + bm = channelToTBitmap( channel ); + tr = NL3D::CTileSet::TTransition( idx ); + const NL3D::CTileBorder &border = node->border( channel ); + int rot = node->alphaRot(); + + set->setTileTransitionAlpha( tr, node->getTileFilename( channel ).toUtf8().constData(), bank, border, rot ); } } @@ -149,6 +206,17 @@ public: setupDisplacementTiles( set, tn ); } + void setupTiles( NL3D::CTileSet *set, TileSetNode *node ) + { + TileTypeNode *tn128 = static_cast< TileTypeNode* >( node->child( 0 ) ); + TileTypeNode *tn256 = static_cast< TileTypeNode* >( node->child( 1 ) ); + + setupTiles128( set, tn128 ); + setupTiles256( set, tn256 ); + setupTransitionTiles( set, node ); + setupDisplacementTiles( set, node ); + } + void addLands( const QList< Land > &lands ) { QListIterator< Land > itr( lands ); @@ -185,11 +253,8 @@ public: TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); addTilesToSet( set, n ); - setupTransitionTiles( set, n ); - setupDisplacementTiles( set, n ); - + setupTiles( set, n ); set->setOriented( n->isOriented() ); - set->setTileVegetableDescFileName( n->vegetSet().toUtf8().constData() ); } From 299629860b20deead987a6c1a56d9bc3c5729919 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 19:04:34 +0200 Subject: [PATCH 212/282] Rotation can now be set. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 24 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 3 +++ .../tile_editor/tile_editor_main_window.ui | 12 ++++++++++ .../src/plugins/tile_editor/tile_item.cpp | 9 ++++++- .../src/plugins/tile_editor/tile_item.h | 2 ++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 7c9ec8f52..aee2002ce 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -58,6 +58,23 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) rotateActions.push_back(m_ui->actionRotateTile270); m_rotationMenu->addActions(rotateActions); m_ui->toolBar->addAction(m_rotationMenu->menuAction()); + m_rotateSM = new QSignalMapper(); + m_rotateAG = new QActionGroup(this); + m_rotateAG->addAction(m_ui->actionRotateTile0); + m_rotateAG->addAction(m_ui->actionRotateTile90); + m_rotateAG->addAction(m_ui->actionRotateTile180); + m_rotateAG->addAction(m_ui->actionRotateTile270); + m_ui->actionRotateTile0->setChecked( true ); + + connect( m_ui->actionRotateTile0, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + connect( m_ui->actionRotateTile90, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + connect( m_ui->actionRotateTile180, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + connect( m_ui->actionRotateTile270, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + m_rotateSM->setMapping( m_ui->actionRotateTile0, 0 ); + m_rotateSM->setMapping( m_ui->actionRotateTile90, 1 ); + m_rotateSM->setMapping( m_ui->actionRotateTile180, 2 ); + m_rotateSM->setMapping( m_ui->actionRotateTile270, 3 ); + connect( m_rotateSM, SIGNAL( mapped( int ) ), this, SLOT( onRotate( int ) ) ); // Create the tile zoom menu. m_zoomMenu = new QMenu(tr("Zoom"), m_ui->toolBar); @@ -186,6 +203,8 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_ui; delete m_undoStack; delete m_rotationMenu; + delete m_rotateSM; + delete m_rotateAG; delete m_tileDisplayMenu; delete m_tileEditorMenu; @@ -315,6 +334,11 @@ void TileEditorMainWindow::onZoomFactor(int level) m_ui->listViewTransition->repaint(); } +void TileEditorMainWindow::onRotate( int id ) +{ + TileItemNode::setAlphaRot( id * 90 ); +} + void TileEditorMainWindow::onActionAddTile(bool triggered) { onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index d98ec9651..44b2c9869 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -81,6 +81,7 @@ private Q_SLOTS: void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); + void onRotate(int id); private: void onActionAddTile(int tabId); @@ -107,6 +108,8 @@ private: QMenu *m_zoomMenu; QActionGroup *m_zoomActionGroup; QSignalMapper *m_zoomSignalMapper; + QActionGroup *m_rotateAG; + QSignalMapper *m_rotateSM; TileItemDelegate *m_tileItemDelegate; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index f45951aba..8974570a1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -581,6 +581,9 @@ + + true + :/tileRotation/images/rotation0.png:/tileRotation/images/rotation0.png @@ -617,6 +620,9 @@ + + true + :/tileRotation/images/rotation90.png:/tileRotation/images/rotation90.png @@ -629,6 +635,9 @@ + + true + :/tileRotation/images/rotation180.png:/tileRotation/images/rotation180.png @@ -641,6 +650,9 @@ + + true + :/tileRotation/images/rotation270.png:/tileRotation/images/rotation270.png diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index fe1df0ebf..1daa3c297 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -290,6 +290,7 @@ public: m_borderFirst[ i ] = false; m_id = -1; + m_alphaRot = 0; } bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) @@ -511,6 +512,9 @@ public: const NL3D::CTileBorder &border( TileModel::TTileChannel channel ){ return m_border[ channel ]; } + int alphaRot() const{ return m_alphaRot; } + void setAlphaRot( int rot ){ m_alphaRot = rot; } + private: QPixmap pixmaps[ TileModel::TileChannelCount ]; TileModel::TNodeTileType m_type; @@ -518,9 +522,11 @@ private: int m_id; QString m_lastError; bool m_borderFirst[ TileModel::TileChannelCount ]; + int m_alphaRot; }; TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; +int TileItemNode::s_alphaRot = 0; TileItemNode::TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) { @@ -555,6 +561,7 @@ bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file empty = true; } + pvt->setAlphaRot( s_alphaRot ); bool b = pvt->loadImage( channel, fn, empty ); m_hasError = !b; if( !b ) @@ -601,7 +608,7 @@ const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) int TileItemNode::alphaRot() const { - return 0; + return pvt->alphaRot(); } QVariant TileItemNode::data(int column, int role) const diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 2e374061d..14bc66fe4 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -129,6 +129,7 @@ public: static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } + static void setAlphaRot( int rot ){ s_alphaRot = rot; } bool hasError() const{ return m_hasError; } @@ -137,6 +138,7 @@ private: QMap m_tileWidget; static TileModel::TTileChannel s_displayChannel; + static int s_alphaRot; TileItemNodePvt *pvt; From 30bae94ac3c6fe78104a87a9cf8079ce3c12352c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 21:33:13 +0200 Subject: [PATCH 213/282] Started to rework tile checks, tile banks loading / saving. A tilebank will now be in the tilemodel, and it will work from there. Also moved some constants into an independent file. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/3d/tile_bank.h | 2 + .../src/plugins/tile_editor/tile_bank.cpp | 110 ++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 29 +++++ .../src/plugins/tile_editor/tile_constants.h | 26 +++++ .../tile_editor/tile_editor_main_window.cpp | 33 ++++-- .../src/plugins/tile_editor/tile_item.cpp | 94 ++++++++------- .../src/plugins/tile_editor/tile_item.h | 28 ++--- .../src/plugins/tile_editor/tile_model.cpp | 62 +++++++--- .../src/plugins/tile_editor/tile_model.h | 32 ++--- .../plugins/tile_editor/tilebank_loader.cpp | 26 ++--- .../plugins/tile_editor/tilebank_saver.cpp | 42 +++---- 11 files changed, 348 insertions(+), 136 deletions(-) create mode 100644 code/studio/src/plugins/tile_editor/tile_bank.cpp create mode 100644 code/studio/src/plugins/tile_editor/tile_bank.h create mode 100644 code/studio/src/plugins/tile_editor/tile_constants.h diff --git a/code/nel/include/nel/3d/tile_bank.h b/code/nel/include/nel/3d/tile_bank.h index f391554d3..89b8e2272 100644 --- a/code/nel/include/nel/3d/tile_bank.h +++ b/code/nel/include/nel/3d/tile_bank.h @@ -172,6 +172,8 @@ public: return _TileSet.find (name)!=_TileSet.end(); } + void clear(){ _TileSet.clear(); } + void serial(class NLMISC::IStream &f) throw(NLMISC::EStream); private: diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp new file mode 100644 index 000000000..f98b4ef38 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -0,0 +1,110 @@ +#include "tile_bank.h" +#include "nel/3d/tile_bank.h" + +#include + +bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) +{ + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +class TileBankPvt +{ +public: + NL3D::CTileBank m_bank; +}; + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TileBank::TileBank() +{ + m_pvt = new TileBankPvt(); +} + +TileBank::~TileBank() +{ + delete m_pvt; +} + +void TileBank::addTileSet( const QString &name ) +{ + m_pvt->m_bank.addTileSet( name.toUtf8().constData() ); + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( 0 ); +} + +void TileBank::addLand( const QString &name ) +{ + m_pvt->m_bank.addLand( name.toUtf8().constData() ); +} + +void TileBank::setLandSets( int idx, const QStringList &l ) +{ + NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); + land->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + land->addTileSet( itr.next().toUtf8().constData() ); + } +} + +bool TileBank::addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return false; + + QPixmap pm = pixmap.value< QPixmap >(); + if( pm.isNull() ) + return false; + + if( pm.width() != pm.height() ) + return false; + + std::vector< NLMISC::CBGRA > pixels; + pixmapToCBGRA( pm, pixels ); + + int tile; + set->addTile128( tile, m_pvt->m_bank ); + + NL3D::CTileBorder border; + border.set( pm.width(), pm.height(), pixels ); + + + + return true; +} \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h new file mode 100644 index 000000000..ab4d28ee8 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -0,0 +1,29 @@ +#ifndef TILE_BANK_H +#define TILE_BANK_H + +#include +#include +#include + +#include "tile_constants.h" + +class TileBankPvt; + +class TileBank +{ +public: + TileBank(); + ~TileBank(); + + void addTileSet( const QString &name ); + void addLand( const QString &name ); + void setLandSets( int idx, const QStringList &l ); + + bool addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + +private: + TileBankPvt *m_pvt; +}; + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_constants.h b/code/studio/src/plugins/tile_editor/tile_constants.h new file mode 100644 index 000000000..e75664d43 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_constants.h @@ -0,0 +1,26 @@ +#ifndef TILE_CONSTANTS_H +#define TILE_CONSTANTS_H + + +namespace TileConstants +{ + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + TileChannelCount = 3 + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3, + TileNodeTypeCount = 4 + }; +} + + +#endif diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index aee2002ce..dd3ece7c7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -648,7 +648,7 @@ void TileEditorMainWindow::onDiffuseToggled( bool b ) if( !b ) return; - TileItemNode::setDisplayChannel( TileModel::TileDiffuse ); + TileItemNode::setDisplayChannel( TileConstants::TileDiffuse ); updateTab(); } @@ -657,7 +657,7 @@ void TileEditorMainWindow::onAdditiveToggled( bool b ) if( !b ) return; - TileItemNode::setDisplayChannel( TileModel::TileAdditive ); + TileItemNode::setDisplayChannel( TileConstants::TileAdditive ); updateTab(); } @@ -666,7 +666,7 @@ void TileEditorMainWindow::onAlphaToggled( bool b ) if( !b ) return; - TileItemNode::setDisplayChannel( TileModel::TileAlpha ); + TileItemNode::setDisplayChannel( TileConstants::TileAlpha ); updateTab(); } @@ -680,12 +680,12 @@ void TileEditorMainWindow::onTabChanged( int tab ) m_ui->diffuseTrBT->setChecked( true ); } -TileModel::TNodeTileType tabToType( int tabId ) +TileConstants::TNodeTileType tabToType( int tabId ) { - if( tabId >= TileModel::TileNodeTypeCount ) - return TileModel::TileNodeTypeCount; + if( tabId >= TileConstants::TileNodeTypeCount ) + return TileConstants::TileNodeTypeCount; - return TileModel::TNodeTileType( tabId ); + return TileConstants::TNodeTileType( tabId ); } void TileEditorMainWindow::onActionAddTile(int tabId) @@ -705,6 +705,8 @@ void TileEditorMainWindow::onActionAddTile(int tabId) if( !idx.isValid() ) return; + int setId = idx.row(); + TileSetNode *tsn = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); Node *n = tsn->child( tabId ); @@ -715,12 +717,25 @@ void TileEditorMainWindow::onActionAddTile(int tabId) int c = n->childCount(); - TileModel::TNodeTileType type = tabToType( tabId ); + TileConstants::TNodeTileType type = tabToType( tabId ); QStringListIterator itr( fileNames ); while( itr.hasNext() ) { - TileItemNode *newNode = TileModel::createItemNode( type, c, TileModel::TileDiffuse, itr.next() ); + TileItemNode *newNode = m_tileModel->createItemNode( setId, type, c, TileConstants::TileDiffuse, itr.next() ); + if( newNode == NULL ) + { + int reply = QMessageBox::question( this, + tr( "Error adding tile" ), + tr( "Failed to create tile!\nContinue?" ), + QMessageBox::Yes, QMessageBox::No ); + if( reply != QMessageBox::Yes ) + break; + else + continue; + } + + if( newNode->hasError() ) { QString error = newNode->getLastError(); diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 1daa3c297..56f621dee 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -203,7 +203,7 @@ int TileSetNode::columnCount() const /////////////////////////////////////////////////// -TileTypeNode::TileTypeNode(TileModel::TNodeTileType type, Node *parent) : m_nodeTileType(type) +TileTypeNode::TileTypeNode(TileConstants::TNodeTileType type, Node *parent) : m_nodeTileType(type) { m_parentItem = parent; } @@ -230,7 +230,7 @@ int TileTypeNode::columnCount() const return 1; } -TileModel::TNodeTileType TileTypeNode::getTileType() +TileConstants::TNodeTileType TileTypeNode::getTileType() { return m_nodeTileType; } @@ -266,15 +266,15 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// -NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) +NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) { NL3D::CTile::TBitmap bm; switch( channel ) { - case TileModel::TileDiffuse: bm = NL3D::CTile::diffuse; break; - case TileModel::TileAdditive: bm = NL3D::CTile::additive; break; - case TileModel::TileAlpha: bm = NL3D::CTile::alpha; break; + case TileConstants::TileDiffuse: bm = NL3D::CTile::diffuse; break; + case TileConstants::TileAdditive: bm = NL3D::CTile::additive; break; + case TileConstants::TileAlpha: bm = NL3D::CTile::alpha; break; } return bm; @@ -286,7 +286,7 @@ public: TileItemNodePvt() { - for( int i = 0; i < TileModel::TileChannelCount; i++ ) + for( int i = 0; i < TileConstants::TileChannelCount; i++ ) m_borderFirst[ i ] = false; m_id = -1; @@ -325,33 +325,33 @@ public: return true; } - int getWidthForType( TileModel::TNodeTileType type, TileModel::TTileChannel channel ) + int getWidthForType( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel ) { int width = -1; switch( type ) { - case TileModel::Tile128: width = 128; break; - case TileModel::Tile256: width = 256; break; - case TileModel::TileTransition: + case TileConstants::Tile128: width = 128; break; + case TileConstants::Tile256: width = 256; break; + case TileConstants::TileTransition: { - if( channel != TileModel::TileAlpha ) + if( channel != TileConstants::TileAlpha ) width = 128; break; } - case TileModel::TileDisplacement: width = 32; break; + case TileConstants::TileDisplacement: width = 32; break; } return width; } - NL3D::CTileSet::TError checkTile( TileModel::TTileChannel channel ) + NL3D::CTileSet::TError checkTile( TileConstants::TTileChannel channel ) { - if( m_type == TileModel::TileDisplacement ) + if( m_type == TileConstants::TileDisplacement ) return NL3D::CTileSet::ok; - if( channel == TileModel::TileAdditive ) + if( channel == TileConstants::TileAdditive ) return NL3D::CTileSet::ok; int pixel; @@ -365,14 +365,14 @@ public: switch( m_type ) { - case TileModel::Tile128: + case TileConstants::Tile128: error = set.checkTile128( bm, m_border[ channel ], pixel, component ); break; - case TileModel::Tile256: + case TileConstants::Tile256: error = set.checkTile256( bm, m_border[ channel ], pixel, component ); break; - case TileModel::TileTransition: - if( channel != TileModel::TileAlpha ) + case TileConstants::TileTransition: + if( channel != TileConstants::TileAlpha ) error = set.checkTile128( bm, m_border[ channel ], pixel, component ); else error = set.checkTileTransition( NL3D::CTileSet::TTransition( m_id ), bm, m_border[ channel ], index, pixel, component ); @@ -394,13 +394,13 @@ public: switch( m_type ) { - case TileModel::Tile128: - case TileModel::Tile256: + case TileConstants::Tile128: + case TileConstants::Tile256: m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); break; - case TileModel::TileTransition: - if( channel != TileModel::TileAlpha ) + case TileConstants::TileTransition: + if( channel != TileConstants::TileAlpha ) { m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); } @@ -429,7 +429,7 @@ public: return error; } - bool checkPixmap( TileModel::TTileChannel channel, QPixmap &pixmap ) + bool checkPixmap( TileConstants::TTileChannel channel, QPixmap &pixmap ) { int w = pixmap.width(); int h = pixmap.height(); @@ -470,7 +470,7 @@ public: return true; } - bool loadImage( TileModel::TTileChannel channel, const QString &fn, bool empty = false ) + bool loadImage( TileConstants::TTileChannel channel, const QString &fn, bool empty = false ) { QPixmap temp; bool b = temp.load( fn ); @@ -483,52 +483,54 @@ public: m_borderFirst[ channel ] = false; + /* if( !empty ) { if( !checkPixmap( channel, temp ) ) return false; } + */ pixmaps[ channel ] = temp; return true; } - void clearImage( TileModel::TTileChannel channel ) + void clearImage( TileConstants::TTileChannel channel ) { pixmaps[ channel ] = QPixmap(); } - const QPixmap& pixMap( TileModel::TTileChannel channel ) const{ + const QPixmap& pixMap( TileConstants::TTileChannel channel ) const{ return pixmaps[ channel ]; } - void setType( TileModel::TNodeTileType type ){ m_type = type; } + void setType( TileConstants::TNodeTileType type ){ m_type = type; } void setId( int id ){ m_id = id; } int id() const{ return m_id; } QString getLastError() const{ return m_lastError; } - bool borderFirst( TileModel::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } + bool borderFirst( TileConstants::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } - const NL3D::CTileBorder &border( TileModel::TTileChannel channel ){ return m_border[ channel ]; } + const NL3D::CTileBorder &border( TileConstants::TTileChannel channel ){ return m_border[ channel ]; } int alphaRot() const{ return m_alphaRot; } void setAlphaRot( int rot ){ m_alphaRot = rot; } private: - QPixmap pixmaps[ TileModel::TileChannelCount ]; - TileModel::TNodeTileType m_type; - NL3D::CTileBorder m_border[ TileModel::TileChannelCount ]; + QPixmap pixmaps[ TileConstants::TileChannelCount ]; + TileConstants::TNodeTileType m_type; + NL3D::CTileBorder m_border[ TileConstants::TileChannelCount ]; int m_id; QString m_lastError; - bool m_borderFirst[ TileModel::TileChannelCount ]; + bool m_borderFirst[ TileConstants::TileChannelCount ]; int m_alphaRot; }; -TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; +TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; int TileItemNode::s_alphaRot = 0; -TileItemNode::TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) +TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent) { m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); @@ -550,7 +552,7 @@ TileItemNode::~TileItemNode() qDeleteAll(m_childItems); } -bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) +bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString filename) { QString fn = filename; bool empty = false; @@ -571,9 +573,9 @@ bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file return true; } -QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) +QString TileItemNode::getTileFilename(TileConstants::TTileChannel channel) { - QMap< TileModel::TTileChannel, QString >::const_iterator itr + QMap< TileConstants::TTileChannel, QString >::const_iterator itr = m_tileFilename.find( channel ); if( itr == m_tileFilename.end() ) return ""; @@ -596,12 +598,12 @@ QString TileItemNode::getLastError() const return pvt->getLastError(); } -bool TileItemNode::borderFirst( TileModel::TTileChannel channel ) const +bool TileItemNode::borderFirst( TileConstants::TTileChannel channel ) const { return pvt->borderFirst( channel ); } -const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) const +const NL3D::CTileBorder& TileItemNode::border( TileConstants::TTileChannel channel ) const { return pvt->border( channel ); } @@ -658,4 +660,10 @@ QVariant TileItemNode::data(int column, int role) const int TileItemNode::columnCount() const { return 1; -} \ No newline at end of file +} + +QVariant TileItemNode::pixmap( TileConstants::TTileChannel channel ) const +{ + return pvt->pixMap( channel ); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 14bc66fe4..342846ab8 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -95,18 +95,18 @@ class TileTypeNode : public Node { public: - TileTypeNode(TileModel::TNodeTileType type, Node *parent=0); + TileTypeNode(TileConstants::TNodeTileType type, Node *parent=0); virtual ~TileTypeNode(); QVariant data(int column, int role) const; int columnCount() const; - TileModel::TNodeTileType getTileType(); + TileConstants::TNodeTileType getTileType(); bool removeChildren( int position, int count ); private: void reindex(); - TileModel::TNodeTileType m_nodeTileType; + TileConstants::TNodeTileType m_nodeTileType; }; class TileItemNodePvt; @@ -114,30 +114,32 @@ class TileItemNodePvt; class TileItemNode : public Node { public: - TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); + TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; - bool setTileFilename(TileModel::TTileChannel channel, QString filename); - QString getTileFilename(TileModel::TTileChannel channel); + bool setTileFilename(TileConstants::TTileChannel channel, QString filename); + QString getTileFilename(TileConstants::TTileChannel channel); void setId( int id ); int id() const; QString getLastError() const; - bool borderFirst( TileModel::TTileChannel channel ) const; - const NL3D::CTileBorder& border( TileModel::TTileChannel channel ) const; + bool borderFirst( TileConstants::TTileChannel channel ) const; + const NL3D::CTileBorder& border( TileConstants::TTileChannel channel ) const; int alphaRot() const; - static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } - static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } + static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } + static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } static void setAlphaRot( int rot ){ s_alphaRot = rot; } bool hasError() const{ return m_hasError; } + QVariant pixmap( TileConstants::TTileChannel channel ) const; + private: - QMap m_tileFilename; - QMap m_tileWidget; + QMap m_tileFilename; + QMap m_tileWidget; - static TileModel::TTileChannel s_displayChannel; + static TileConstants::TTileChannel s_displayChannel; static int s_alphaRot; TileItemNodePvt *pvt; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d1ab0d238..fbdd07223 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -16,6 +16,7 @@ #include "tile_model.h" #include "tile_item.h" +#include "tile_bank.h" #include @@ -35,6 +36,8 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte TileModel::CurrentZoomFactor = TileModel::TileZoom100; m_indexDisplay = true; m_fileDisplay = true; + + m_tileBank = new TileBank(); } TileModel::~TileModel() @@ -182,59 +185,74 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) TileSetNode *tileSet = new TileSetNode(tileSetName); // child for 128x128 tiles - TileTypeNode *tile128= new TileTypeNode(Tile128); + TileTypeNode *tile128= new TileTypeNode( TileConstants::Tile128); tileSet->appendRow(tile128); // child for 256x256 tiles - TileTypeNode *tile256= new TileTypeNode(Tile256); + TileTypeNode *tile256= new TileTypeNode( TileConstants::Tile256); tileSet->appendRow(tile256); // child for transition tiles. - TileTypeNode *tileTrans= new TileTypeNode(TileTransition); + TileTypeNode *tileTrans= new TileTypeNode( TileConstants::TileTransition); tileSet->appendRow(tileTrans); // Add the default transition tiles. // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode( TileModel::TileTransition, transPos, TileDiffuse, QString("empty")); + TileItemNode *transTile= new TileItemNode( TileConstants::TileTransition, transPos, TileConstants::TileDiffuse, QString("empty")); tileTrans->appendRow(transTile); } // child for displacement tiles - TileTypeNode *tileDisp= new TileTypeNode(TileDisplacement); + TileTypeNode *tileDisp= new TileTypeNode( TileConstants::TileDisplacement); tileSet->appendRow(tileDisp); // Add the default displacement tiles. // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode( TileModel::TileDisplacement, dispPos, TileDiffuse, QString("empty")); + TileItemNode *dispTile= new TileItemNode( TileConstants::TileDisplacement, dispPos, TileConstants::TileDiffuse, QString("empty")); tileDisp->appendRow(dispTile); } // Append them in the correct order to the tile set. this->appendRow(tileSet); + m_tileBank->addTileSet(tileSetName); return tileSet; } -TileItemNode *TileModel::createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ) +TileItemNode *TileModel::createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) { return new TileItemNode( type, id, channel, fileName ); } -const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) +TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) +{ + TileItemNode *n = new TileItemNode( type, id, channel, fileName ); + + bool b = m_tileBank->addTileToSet( idx, fileName, n->pixmap( channel ), channel, type ); + if( !b ) + { + delete n; + return NULL; + } + + return n; +} + +const char *TileModel::getTileTypeName(TileConstants::TNodeTileType type) { switch(type) { - case Tile128: + case TileConstants::Tile128: return "128"; - case Tile256: + case TileConstants::Tile256: return "256"; - case TileTransition: + case TileConstants::TileTransition: return "Transition"; - case TileDisplacement: + case TileConstants::TileDisplacement: return "Displacement"; default: break; @@ -242,17 +260,17 @@ const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) return "UNKNOWN"; } -uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) +uint32 TileModel::getTileTypeSize(TileConstants::TNodeTileType type) { switch(type) { - case Tile128: + case TileConstants::Tile128: return 128; - case Tile256: + case TileConstants::Tile256: return 256; - case TileTransition: + case TileConstants::TileTransition: return 64; - case TileDisplacement: + case TileConstants::TileDisplacement: return 32; default: break; @@ -287,6 +305,16 @@ void TileModel::clear() removeRows( 0, c ); } +void TileModel::addLand( const QString &name ) +{ + m_tileBank->addLand( name ); +} + +void TileModel::setLandSets( int idx, const QStringList &l ) +{ + m_tileBank->setLandSets( idx, l ); +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index c22a43091..8472e6978 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -21,32 +21,18 @@ #include +#include "tile_constants.h" + class Node; class TileSetNode; class TileItemNode; +class TileBank; class TileModel : public QAbstractItemModel { Q_OBJECT public: - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - TileChannelCount = 3 - }; - - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3, - TileNodeTypeCount = 4 - }; - enum TTileItemRole { TilePixmapRole = Qt::UserRole+1, @@ -87,10 +73,11 @@ public: void swapRows( int a, int b ); TileSetNode *createTileSetNode(QString tileSetName); - static TileItemNode *createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ); + static TileItemNode *createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); + TileItemNode *createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); - static const char *getTileTypeName(TNodeTileType type); - static uint32 getTileTypeSize(TileModel::TNodeTileType type); + static const char *getTileTypeName(TileConstants::TNodeTileType type); + static uint32 getTileTypeSize(TileConstants::TNodeTileType type); static TTileZoomFactor CurrentZoomFactor; @@ -101,6 +88,9 @@ public: void setTexturePath( const QString &path ){ m_texturePath = path; } QString texturePath() const{ return m_texturePath; } + void addLand( const QString &name ); + void setLandSets( int idx, const QStringList &l ); + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); @@ -117,6 +107,8 @@ private: Node *rootItem; QString m_texturePath; + + TileBank *m_tileBank; }; #endif // TILE_MODEL_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 73c8007d8..019745afd 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -28,15 +28,15 @@ class TileBankLoaderPvt public: NL3D::CTileBank bank; - static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) { NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; switch( channel ) { - case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileModel::TileAdditive: b = NL3D::CTile::additive; break; - case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; + case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; } return b; @@ -75,11 +75,11 @@ public: int idx = set->getTile128( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( TileModel::Tile128, i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileConstants::Tile128, i, TileConstants::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) { - tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); } node->appendChild( tin ); @@ -94,11 +94,11 @@ public: int idx = set->getTile256( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( TileModel::Tile256, i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileConstants::Tile256, i, TileConstants::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) { - tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); } node->appendChild( tin ); @@ -115,9 +115,9 @@ public: TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j <= TileConstants::TileAlpha; j++ ) { - tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); } } } @@ -130,7 +130,7 @@ public: const char *fn = bank.getDisplacementMap( did ); TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - tin->setTileFilename( TileModel::TileDiffuse, fn ); + tin->setTileFilename( TileConstants::TileDiffuse, fn ); } } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 65559505a..10f86eb14 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -27,35 +27,35 @@ class TileBankSaverPvt public: NL3D::CTileBank bank; - static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) { NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; switch( channel ) { - case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileModel::TileAdditive: b = NL3D::CTile::additive; break; - case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; + case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; } return b; } - NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileModel::TNodeTileType type ) + NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileConstants::TNodeTileType type ) { int idx = -1; int bidx = -1; switch( type ) { - case TileModel::Tile128: + case TileConstants::Tile128: { set->addTile128( idx, bank ); bidx = set->getTile128( idx ); break; } - case TileModel::Tile256: + case TileConstants::Tile256: { set->addTile256( idx, bank ); bidx = set->getTile256( idx ); @@ -71,24 +71,24 @@ public: void addTilesToSet( NL3D::CTileSet *set, TileTypeNode *node ) { - TileModel::TNodeTileType type = node->getTileType(); + TileConstants::TNodeTileType type = node->getTileType(); for( int i = 0; i < node->childCount(); i++ ) { TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); NL3D::CTile *tile = addTileToSet( set, type ); - for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) { - QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); - tile->setFileName( channelToTBitmap( TileModel::TTileChannel( j ) ) , fn.toUtf8().constData() ); + QString fn = tin->getTileFilename( TileConstants::TTileChannel( j ) ); + tile->setFileName( channelToTBitmap( TileConstants::TTileChannel( j ) ) , fn.toUtf8().constData() ); } } } void addTilesToSet( NL3D::CTileSet *set, TileSetNode *node ) { - for( int i = TileModel::Tile128; i <= TileModel::Tile256; i++ ) + for( int i = TileConstants::Tile128; i <= TileConstants::Tile256; i++ ) { TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( i ) ); @@ -103,9 +103,9 @@ public: { tileNode = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) { - TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); const NL3D::CTileBorder &border = tileNode->border( channel ); @@ -124,9 +124,9 @@ public: { tileNode = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) { - TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); const NL3D::CTileBorder &border = tileNode->border( channel ); @@ -140,14 +140,14 @@ public: void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) { - TileModel::TTileChannel channel; + TileConstants::TTileChannel channel; NL3D::CTile::TBitmap bm; NL3D::CTileSet::TTransition tr; // Diffuse, Additive - for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) { - channel =TileModel::TTileChannel( i ); + channel =TileConstants::TTileChannel( i ); bm = channelToTBitmap( channel ); tr = NL3D::CTileSet::TTransition( idx ); const NL3D::CTileBorder &border = node->border( channel ); @@ -159,7 +159,7 @@ public: // Alpha { - channel = TileModel::TileAlpha; + channel = TileConstants::TileAlpha; bm = channelToTBitmap( channel ); tr = NL3D::CTileSet::TTransition( idx ); const NL3D::CTileBorder &border = node->border( channel ); @@ -187,7 +187,7 @@ public: void setupDisplacementTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) { set->setDisplacement( NL3D::CTileSet::TDisplacement( idx ), - node->getTileFilename( TileModel::TileDiffuse ).toUtf8().constData(), + node->getTileFilename( TileConstants::TileDiffuse ).toUtf8().constData(), bank ); } From 1c67d6ec0fba1d0ba6275b91e6f19b01a0352b8f Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 3 Aug 2014 22:15:12 +0200 Subject: [PATCH 214/282] GL: Occlusion query bugfix --- code/nel/src/3d/driver/opengl/driver_opengl.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.cpp b/code/nel/src/3d/driver/opengl/driver_opengl.cpp index eb59f2205..6dae9f4fe 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl.cpp @@ -2803,9 +2803,13 @@ IOcclusionQuery::TOcclusionType COcclusionQueryGL::getOcclusionType() else { GLuint result; - nglGetQueryObjectuivARB(ID, GL_QUERY_RESULT, &result); - OcclusionType = result != 0 ? NotOccluded : Occluded; - VisibleCount = (uint) result; + nglGetQueryObjectuivARB(ID, GL_QUERY_RESULT_AVAILABLE, &result); + if (result != GL_FALSE) + { + nglGetQueryObjectuivARB(ID, GL_QUERY_RESULT, &result); + OcclusionType = result != 0 ? NotOccluded : Occluded; + VisibleCount = (uint) result; + } } } #endif From 204a5b8a184e0ee651af48dcdbb52a14859d7708 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 4 Aug 2014 14:05:11 +0530 Subject: [PATCH 215/282] rest api using curl --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/rest_api.php | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php new file mode 100644 index 000000000..8dba944b5 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php @@ -0,0 +1,52 @@ + Date: Mon, 4 Aug 2014 21:22:44 +0200 Subject: [PATCH 216/282] Most of the functionality works with the new code. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 367 ++++++++++++++++-- .../src/plugins/tile_editor/tile_bank.h | 28 +- .../tile_editor/tile_editor_main_window.cpp | 158 +++----- .../tile_editor/tile_editor_main_window.h | 7 - .../tile_editor/tile_editor_main_window.ui | 52 --- .../src/plugins/tile_editor/tile_item.cpp | 268 +------------ .../src/plugins/tile_editor/tile_item.h | 12 +- .../src/plugins/tile_editor/tile_model.cpp | 92 ++++- .../src/plugins/tile_editor/tile_model.h | 10 + .../plugins/tile_editor/tilebank_loader.cpp | 139 +------ .../plugins/tile_editor/tilebank_saver.cpp | 251 +----------- 11 files changed, 511 insertions(+), 873 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index f98b4ef38..a44158259 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -3,38 +3,48 @@ #include -bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) -{ - QImage img = pixmap.toImage(); - if( img.format() != QImage::Format_ARGB32 ) - img = img.convertToFormat( QImage::Format_ARGB32 ); - - if( img.format() != QImage::Format_ARGB32 ) - return false; - - int c = img.width() * img.height(); - - const unsigned char *data = img.bits(); - const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); - - NLMISC::CBGRA bgra; - pixels.clear(); - - int i = 0; - while( i < c ) - { - bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; - bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; - bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; - bgra.B = ( idata[ i ] & 0x000000FF ); - pixels.push_back( bgra ); - - i++; - } - - return true; -} +namespace{ + + bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) + { + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + return true; + } + + + NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) + { + return NL3D::CTile::TBitmap( int( channel ) ); + } + + +} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -42,6 +52,124 @@ bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) class TileBankPvt { public: + + bool checkSize( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel, int w, int h ) + { + int width = -1; + + switch( type ) + { + case TileConstants::Tile128: + width = 128; + break; + + case TileConstants::Tile256: + width = 256; + break; + + case TileConstants::TileTransition: + { + if( channel == TileConstants::TileAlpha ) + width = 64; + else + width = 128; + + } + break; + + case TileConstants::TileDisplacement: + width = 32; + break; + } + + if( width == w ) + return true; + + return false; + } + + NL3D::CTileSet::TError checkTile( NL3D::CTileSet *set, int tile, TileConstants::TNodeTileType type, NL3D::CTileBorder &border, NL3D::CTile::TBitmap bitmap, QString &msg ) + { + NL3D::CTileSet::TError error; + + if( bitmap == NL3D::CTile::additive ) + return NL3D::CTileSet::ok; + + if( type == TileConstants::TileDisplacement ) + return NL3D::CTileSet::ok; + + int component; + int pixel; + int idx; + + switch( type ) + { + case TileConstants::Tile128: + error = set->checkTile128( bitmap, border, pixel, component ); + break; + + case TileConstants::Tile256: + error = set->checkTile256( bitmap, border, pixel, component ); + break; + + case TileConstants::TileTransition: + { + if( bitmap != NL3D::CTile::alpha ) + error = set->checkTile128( bitmap, border, pixel, component ); + else + error = set->checkTileTransition( NL3D::CTileSet::TTransition( tile ), bitmap, border, idx, pixel, component ); + + break; + } + } + + if( ( error != NL3D::CTileSet::ok ) && ( error != NL3D::CTileSet::addFirstA128128 ) ) + { + static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; + + msg = NL3D::CTileSet::getErrorMessage( error ); + msg += "\n"; + msg += " pixel %1 component %2"; + msg = msg.arg( pixel ); + msg = msg.arg( comp[ component ] ); + } + + return error; + } + + void setTile( NL3D::CTileSet *set, int tile, int rotation, const QString &name, NL3D::CTile::TBitmap bm, TileConstants::TNodeTileType type, NL3D::CTileBorder &border ) + { + switch( type ) + { + case TileConstants::Tile128: + set->setTile128( tile, name.toUtf8().constData(), bm, m_bank ); + break; + + case TileConstants::Tile256: + set->setTile256( tile, name.toUtf8().constData(), bm, m_bank ); + break; + + case TileConstants::TileTransition: + if( bm != NL3D::CTile::alpha ) + set->setTileTransition( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), bm, m_bank, border ); + else + set->setTileTransitionAlpha( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), m_bank, border, rotation ); + break; + + case TileConstants::TileDisplacement: + set->setDisplacement( NL3D::CTileSet::TDisplacement( tile ), name.toUtf8().constData(), m_bank ); + break; + } + + } + + void buildBorder( QPixmap &pm, NL3D::CTileBorder &border ) + { + std::vector< NLMISC::CBGRA > pixels; + pixmapToCBGRA( pm, pixels ); + border.set( pm.width(), pm.height(), pixels ); + } + NL3D::CTileBank m_bank; }; @@ -52,6 +180,7 @@ public: TileBank::TileBank() { m_pvt = new TileBankPvt(); + resetError(); } TileBank::~TileBank() @@ -65,11 +194,51 @@ void TileBank::addTileSet( const QString &name ) NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( 0 ); } +void TileBank::removeTileSet( int idx ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return; + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + land->removeTileSet( set->getName() ); + } + + m_pvt->m_bank.removeTileSet( idx ); +} + +void TileBank::renameTileSet( int idx, const QString &newName ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return; + + std::string oldName = set->getName(); + set->setName( newName.toUtf8().constData() ); + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + land->removeTileSet( oldName ); + land->addTileSet( newName.toUtf8().constData() ); + } + +} + void TileBank::addLand( const QString &name ) { m_pvt->m_bank.addLand( name.toUtf8().constData() ); } +void TileBank::removeLand( int idx ) +{ + m_pvt->m_bank.removeLand( idx ); +} + void TileBank::setLandSets( int idx, const QStringList &l ) { NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); @@ -82,29 +251,145 @@ void TileBank::setLandSets( int idx, const QStringList &l ) } } -bool TileBank::addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +void TileBank::getLandSets( int idx, QStringList &l ) { - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); + if( land == NULL ) + return; + + l.clear(); + + std::set< std::string> sets = land->getTileSets(); + std::set< std::string >::const_iterator itr = sets.begin(); + while( itr != sets.end() ) + { + l.push_back( itr->c_str() ); + ++itr; + } +} + +bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + resetError(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( setIdx ); + + int tile; + switch( type ) + { + case TileConstants::Tile128: set->addTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->addTile256( tile, m_pvt->m_bank ); break; + } + + bool b = setTile( setIdx, tile, name, pixmap, channel, type ); + if( b ) + return true; + + // There was an error, roll back + switch( type ) + { + case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile128( tile, m_pvt->m_bank ); break; + } + + return false; +} + +void TileBank::removeTile( int ts, int type, int tile ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); + + switch( type ) + { + case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; + } +} + +bool TileBank::setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + resetError(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileset ); if( set == NULL ) return false; QPixmap pm = pixmap.value< QPixmap >(); if( pm.isNull() ) + { + m_hasError = true; + m_lastError = "Failed to load image."; return false; + } if( pm.width() != pm.height() ) + { + m_hasError = true; + m_lastError = "Image isn't square."; return false; + } - std::vector< NLMISC::CBGRA > pixels; - pixmapToCBGRA( pm, pixels ); - - int tile; - set->addTile128( tile, m_pvt->m_bank ); + if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) ) + { + m_hasError = true; + m_lastError = "Invalid image size."; + return false; + } NL3D::CTileBorder border; - border.set( pm.width(), pm.height(), pixels ); + m_pvt->buildBorder( pm, border ); + + QString msg; + NL3D::CTileSet::TError error = m_pvt->checkTile( set, tile, type, border, channelToTBitmap( channel ), msg ); + + // Tile checks out fine, set it + if( ( error == NL3D::CTileSet::ok ) || ( error == NL3D::CTileSet::addFirstA128128 ) ) + { + if( error == NL3D::CTileSet::addFirstA128128 ) + set->setBorder( channelToTBitmap( channel ), border ); + + m_pvt->setTile( set, tile, 0 /* rotation */, name, channelToTBitmap( channel ), type, border ); + + return true; + } + + setError( msg ); + return false; +} + +void TileBank::replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ) +{ + setTile( ts, tile, name, pixmap, channel, TileConstants::TNodeTileType( type ) ); +} + +void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); + + int tileId; + + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + switch( type ) + { + case TileConstants::Tile128: + set->clearTile128( tile, bm, m_pvt->m_bank ); + break; + + case TileConstants::Tile256: + set->clearTile256( tile, bm, m_pvt->m_bank ); + break; + + case TileConstants::TileTransition: + set->clearTransition( NL3D::CTileSet::TTransition( tile ), bm, m_pvt->m_bank ); + break; + + case TileConstants::TileDisplacement: + set->clearDisplacement( NL3D::CTileSet::TDisplacement( tile ), m_pvt->m_bank ); + break; + } + +} + - return true; -} \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index ab4d28ee8..d81ae694b 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -16,13 +16,37 @@ public: ~TileBank(); void addTileSet( const QString &name ); + void removeTileSet( int idx ); + void renameTileSet( int idx, const QString &newName ); + void addLand( const QString &name ); + void removeLand( int idx ); void setLandSets( int idx, const QStringList &l ); - - bool addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void getLandSets( int idx, QStringList &l ); + + bool addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void removeTile( int ts, int type, int tile ); + bool setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); + void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + bool hasError() const{ return m_hasError; } + QString getLastError() const{ return m_lastError; } + void resetError(){ + m_hasError = false; + m_lastError = ""; + } + + void setError( const QString &msg ) + { + m_hasError = true; + m_lastError = msg; + } private: TileBankPvt *m_pvt; + QString m_lastError; + bool m_hasError; }; #endif diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index dd3ece7c7..dffa7a61a 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -110,8 +110,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); connect(m_ui->tileSetEditTB, SIGNAL(clicked()), this, SLOT(onTileSetEdit())); - connect(m_ui->tileSetUpTB, SIGNAL(clicked()), this, SLOT(onTileSetUp())); - connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); @@ -251,7 +249,8 @@ void TileEditorMainWindow::saveAs( const QString &fn ) } TileBankSaver saver; - bool ok = saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool ok = true; + //saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); if( !ok ) { @@ -272,7 +271,8 @@ void TileEditorMainWindow::open() return; TileBankLoader loader; - bool b = loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool b = true; + //loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); if( !b ) { @@ -398,10 +398,7 @@ void TileEditorMainWindow::onTileSetDelete() QString set = reinterpret_cast< TileSetNode* >( idx.internalPointer() )->getTileSetName(); - TileModel *model = static_cast(m_ui->tileSetLV->model()); - bool ok = model->removeRow( idx.row() ); - - onTileSetRemoved( set ); + m_tileModel->removeTileSet( idx.row() ); } void TileEditorMainWindow::onTileSetEdit() @@ -438,46 +435,7 @@ void TileEditorMainWindow::onTileSetEdit() node->setTileSetName( newName ); m_ui->tileSetLV->reset(); - onTileSetRenamed( oldName, newName ); -} - -void TileEditorMainWindow::onTileSetUp() -{ - QModelIndex idx = m_ui->tileSetLV->currentIndex(); - if( !idx.isValid() ) - return; - - if( idx.row() == 0 ) - return; - - TileModel *model = static_cast(m_ui->tileSetLV->model()); - if( model->rowCount() < 2 ) - return; - - int r = idx.row(); - model->swapRows( r, r - 1 ); - - m_ui->tileSetLV->reset(); - m_ui->tileSetLV->setCurrentIndex( model->index( r - 1, 0 ) ); -} - -void TileEditorMainWindow::onTileSetDown() -{ - QModelIndex idx = m_ui->tileSetLV->currentIndex(); - if( !idx.isValid() ) - return; - - TileModel *model = static_cast(m_ui->tileSetLV->model()); - if( model->rowCount() < idx.row() ) - return; - if( model->rowCount() < 2 ) - return; - - int r = idx.row(); - model->swapRows( r, r + 1 ); - - m_ui->tileSetLV->reset(); - m_ui->tileSetLV->setCurrentIndex( model->index( r + 1, 0 ) ); + m_tileModel->renameTileSet( idx.row(), newName ); } void TileEditorMainWindow::onLandAdd() @@ -503,9 +461,7 @@ void TileEditorMainWindow::onLandAdd() m_ui->landLW->addItem( name ); - Land l; - l.name = name; - m_lands.push_back( l ); + m_tileModel->addLand( name ); } void TileEditorMainWindow::onLandRemove() @@ -526,8 +482,7 @@ void TileEditorMainWindow::onLandRemove() delete item; - QList< Land >::iterator itr = m_lands.begin() + idx; - m_lands.erase( itr ); + m_tileModel->removeLand( idx ); } void TileEditorMainWindow::onLandEdit() @@ -549,10 +504,12 @@ void TileEditorMainWindow::onLandEdit() } int r = m_ui->landLW->currentRow(); - Land &l = m_lands[ r ]; + + QStringList sts; + m_tileModel->getLandSets( r, sts ); LandEditDialog d; - d.setSelectedTileSets( l.tilesets ); + d.setSelectedTileSets( sts ); d.setTileSets( ts ); int result = d.exec(); @@ -560,10 +517,10 @@ void TileEditorMainWindow::onLandEdit() return; // Update the tileset of the land - ts.clear(); - d.getSelectedTileSets( ts ); - l.tilesets.clear(); - l.tilesets = ts; + sts.clear(); + d.getSelectedTileSets( sts ); + + m_tileModel->setLandSets( r, sts ); } void TileEditorMainWindow::onChooseVegetation() @@ -720,37 +677,26 @@ void TileEditorMainWindow::onActionAddTile(int tabId) TileConstants::TNodeTileType type = tabToType( tabId ); QStringListIterator itr( fileNames ); + QString error; + while( itr.hasNext() ) { TileItemNode *newNode = m_tileModel->createItemNode( setId, type, c, TileConstants::TileDiffuse, itr.next() ); if( newNode == NULL ) { - int reply = QMessageBox::question( this, - tr( "Error adding tile" ), - tr( "Failed to create tile!\nContinue?" ), - QMessageBox::Yes, QMessageBox::No ); - if( reply != QMessageBox::Yes ) - break; - else - continue; - } - - - if( newNode->hasError() ) - { - QString error = newNode->getLastError(); - error += "\nContinue?"; + if( m_tileModel->hasError() ) + error = m_tileModel->getLastError(); int reply = QMessageBox::question( this, tr( "Error adding tile" ), - error, + error + "\nContinue?", QMessageBox::Yes, QMessageBox::No ); if( reply != QMessageBox::Yes ) break; else continue; } - + n->appendRow( newNode ); c++; } @@ -777,12 +723,13 @@ void TileEditorMainWindow::onActionDeleteTile( int tabId ) return; } - int row = idx.row(); - - QModelIndex parent = idx.parent(); - lv->model()->removeRow( row, parent ); + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int ts = tsidx.row(); + int tile = idx.row(); - //lv->reset(); + m_tileModel->removeTile( ts, tabId, tile ); } void TileEditorMainWindow::onActionDeleteImage( int tabId ) @@ -798,13 +745,25 @@ void TileEditorMainWindow::onActionDeleteImage( int tabId ) return; } + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int ts = tsidx.row(); + TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileItemNode::displayChannel(), "" ); + int tile = n->id(); + + m_tileModel->clearImage( ts, tabId, tile, TileItemNode::displayChannel() ); } void TileEditorMainWindow::onActionReplaceImage( int tabId ) { QListView *lv = getListViewByTab( tabId ); + + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int set = tsidx.row(); QModelIndex idx = lv->currentIndex(); if( !idx.isValid() ) @@ -823,41 +782,22 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) return; TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileItemNode::displayChannel(), fileName ); -} - -void TileEditorMainWindow::onTileSetRemoved( const QString &set ) -{ - int c = m_lands.count(); - for( int i = 0; i < c; i++ ) - { - Land &land = m_lands[ i ]; - land.tilesets.removeAll( set ); - } -} + int tile = n->id(); -void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QString &newname ) -{ - int c = m_lands.count(); - for( int i = 0; i < c; i++ ) + m_tileModel->replaceImage( set, tabId, tile, TileItemNode::displayChannel(), fileName ); + if( m_tileModel->hasError() ) { - Land &land = m_lands[ i ]; - int idx = land.tilesets.indexOf( oldname ); - if( idx < 0 ) - continue; - - land.tilesets[ idx ] = newname; + QString error = m_tileModel->getLastError(); + QMessageBox::information( this, + tr( "Error replacing tile image" ), + error ); } } void TileEditorMainWindow::onTileBankLoaded() { m_ui->landLW->clear(); - QListIterator< Land > itr( m_lands ); - while( itr.hasNext() ) - { - m_ui->landLW->addItem( itr.next().name ); - } + // load lands m_ui->listView128->reset(); m_ui->listView256->reset(); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 44b2c9869..1ec80cd96 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -25,8 +25,6 @@ #include #include -#include "land.h" - namespace Ui { class TileEditorMainWindow; } @@ -59,8 +57,6 @@ private Q_SLOTS: void onTileSetAdd(); void onTileSetDelete(); void onTileSetEdit(); - void onTileSetUp(); - void onTileSetDown(); void onLandAdd(); void onLandRemove(); @@ -89,8 +85,6 @@ private: void onActionDeleteImage(int tabId); void onActionReplaceImage(int tabId); - void onTileSetRemoved( const QString &set ); - void onTileSetRenamed( const QString &oldname, const QString &newname ); void onTileBankLoaded(); void updateTab(); @@ -127,7 +121,6 @@ private: }; QString m_fileName; - QList< Land > m_lands; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 8974570a1..08d14ca79 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -426,58 +426,6 @@ Tile Sets - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - ... - - - - :/movementIcons/images/up.png:/movementIcons/images/up.png - - - - - - - ... - - - - :/movementIcons/images/down.png:/movementIcons/images/down.png - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 56f621dee..e952d8d20 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -18,12 +18,8 @@ #include "tile_item.h" -//#include "tile_widget.h" - #include -#include - Node::Node() : m_parentItem(0) { } @@ -266,210 +262,14 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// -NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) -{ - NL3D::CTile::TBitmap bm; - - switch( channel ) - { - case TileConstants::TileDiffuse: bm = NL3D::CTile::diffuse; break; - case TileConstants::TileAdditive: bm = NL3D::CTile::additive; break; - case TileConstants::TileAlpha: bm = NL3D::CTile::alpha; break; - } - - return bm; -} - class TileItemNodePvt { public: TileItemNodePvt() { - for( int i = 0; i < TileConstants::TileChannelCount; i++ ) - m_borderFirst[ i ] = false; - - m_id = -1; - m_alphaRot = 0; - } - - bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) - { - QImage img = pixmap.toImage(); - if( img.format() != QImage::Format_ARGB32 ) - img = img.convertToFormat( QImage::Format_ARGB32 ); - - if( img.format() != QImage::Format_ARGB32 ) - return false; - - int c = img.width() * img.height(); - - const unsigned char *data = img.bits(); - const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); - - NLMISC::CBGRA bgra; - pixels.clear(); - - int i = 0; - while( i < c ) - { - bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; - bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; - bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; - bgra.B = ( idata[ i ] & 0x000000FF ); - pixels.push_back( bgra ); - - i++; - } - - return true; - } - - int getWidthForType( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel ) - { - int width = -1; - - switch( type ) - { - case TileConstants::Tile128: width = 128; break; - case TileConstants::Tile256: width = 256; break; - case TileConstants::TileTransition: - { - if( channel != TileConstants::TileAlpha ) - width = 128; - break; - } - - case TileConstants::TileDisplacement: width = 32; break; - } - - return width; - } - - NL3D::CTileSet::TError checkTile( TileConstants::TTileChannel channel ) - { - if( m_type == TileConstants::TileDisplacement ) - return NL3D::CTileSet::ok; - - if( channel == TileConstants::TileAdditive ) - return NL3D::CTileSet::ok; - - int pixel; - int component; - int index; - - NL3D::CTileSet set; - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - - NL3D::CTileSet::TError error = NL3D::CTileSet::ok; - - switch( m_type ) - { - case TileConstants::Tile128: - error = set.checkTile128( bm, m_border[ channel ], pixel, component ); - break; - case TileConstants::Tile256: - error = set.checkTile256( bm, m_border[ channel ], pixel, component ); - break; - case TileConstants::TileTransition: - if( channel != TileConstants::TileAlpha ) - error = set.checkTile128( bm, m_border[ channel ], pixel, component ); - else - error = set.checkTileTransition( NL3D::CTileSet::TTransition( m_id ), bm, m_border[ channel ], index, pixel, component ); - break; - } - - if( error == NL3D::CTileSet::ok ) - return NL3D::CTileSet::ok; - if( error == NL3D::CTileSet::addFirstA128128 ) - return NL3D::CTileSet::addFirstA128128; - - static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; - - if( error != NL3D::CTileSet::ok ) - { - m_lastError = "ERROR: "; - m_lastError += NL3D::CTileSet::getErrorMessage( error ); - m_lastError += "\n"; - - switch( m_type ) - { - case TileConstants::Tile128: - case TileConstants::Tile256: - m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); - break; - - case TileConstants::TileTransition: - if( channel != TileConstants::TileAlpha ) - { - m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); - } - else - { - if ((error==NL3D::CTileSet::topInterfaceProblem)||(error==NL3D::CTileSet::bottomInterfaceProblem)|| - (error==NL3D::CTileSet::leftInterfaceProblem)||(error==NL3D::CTileSet::rightInterfaceProblem)|| - (error==NL3D::CTileSet::topBottomNotTheSame)||(error==NL3D::CTileSet::rightLeftNotTheSame) - ||(error==NL3D::CTileSet::topInterfaceProblem)) - { - if( index != -1 ) - { - m_lastError += QString( "tile: %1 pixel: %2 component: %3" ).arg( index ).arg( pixel ).arg( comp[ component ] ); - } - else - { - m_lastError += QString( "incompatible with a 128 tile, pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); - } - } - - } - break; - } - } - - return error; } - bool checkPixmap( TileConstants::TTileChannel channel, QPixmap &pixmap ) - { - int w = pixmap.width(); - int h = pixmap.height(); - - if( w != h ) - { - m_lastError = QObject::tr( "Not a square texture." ); - return false; - } - - int width = getWidthForType( m_type, channel ); - - if( width != -1 ) - { - if( width != w ) - { - m_lastError = QObject::tr( "Not the proper size." ); - return false; - } - } - - std::vector< NLMISC::CBGRA > pixels; - - pixmapToCBGRA( pixmap, pixels ); - - m_border[ channel ].set( w, h, pixels ); - - NL3D::CTileSet::TError error = checkTile( channel ); - if( error == NL3D::CTileSet::addFirstA128128 ) - { - m_borderFirst[ channel ] = true; - return true; - } - - if( error != NL3D::CTileSet::ok ) - return false; - - return true; - } - bool loadImage( TileConstants::TTileChannel channel, const QString &fn, bool empty = false ) { QPixmap temp; @@ -477,20 +277,9 @@ public: if( !b ) { - m_lastError = QObject::tr( "Cannot open file %1" ).arg( fn ); return false; } - m_borderFirst[ channel ] = false; - - /* - if( !empty ) - { - if( !checkPixmap( channel, temp ) ) - return false; - } - */ - pixmaps[ channel ] = temp; return true; @@ -505,26 +294,8 @@ public: return pixmaps[ channel ]; } - void setType( TileConstants::TNodeTileType type ){ m_type = type; } - void setId( int id ){ m_id = id; } - int id() const{ return m_id; } - - QString getLastError() const{ return m_lastError; } - bool borderFirst( TileConstants::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } - - const NL3D::CTileBorder &border( TileConstants::TTileChannel channel ){ return m_border[ channel ]; } - - int alphaRot() const{ return m_alphaRot; } - void setAlphaRot( int rot ){ m_alphaRot = rot; } - private: QPixmap pixmaps[ TileConstants::TileChannelCount ]; - TileConstants::TNodeTileType m_type; - NL3D::CTileBorder m_border[ TileConstants::TileChannelCount ]; - int m_id; - QString m_lastError; - bool m_borderFirst[ TileConstants::TileChannelCount ]; - int m_alphaRot; }; TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; @@ -532,13 +303,11 @@ int TileItemNode::s_alphaRot = 0; TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent) { + m_id = tileId; m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); pvt = new TileItemNodePvt(); - pvt->setType( type ); - pvt->setId( tileId ); - m_hasError = false; setTileFilename( channel, filename ); @@ -563,7 +332,6 @@ bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString empty = true; } - pvt->setAlphaRot( s_alphaRot ); bool b = pvt->loadImage( channel, fn, empty ); m_hasError = !b; if( !b ) @@ -583,36 +351,6 @@ QString TileItemNode::getTileFilename(TileConstants::TTileChannel channel) return itr.value(); } -void TileItemNode::setId( int id ) -{ - pvt->setId( id ); -} - -int TileItemNode::id() const -{ - return pvt->id(); -} - -QString TileItemNode::getLastError() const -{ - return pvt->getLastError(); -} - -bool TileItemNode::borderFirst( TileConstants::TTileChannel channel ) const -{ - return pvt->borderFirst( channel ); -} - -const NL3D::CTileBorder& TileItemNode::border( TileConstants::TTileChannel channel ) const -{ - return pvt->border( channel ); -} - -int TileItemNode::alphaRot() const -{ - return pvt->alphaRot(); -} - QVariant TileItemNode::data(int column, int role) const { QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; @@ -647,11 +385,11 @@ QVariant TileItemNode::data(int column, int role) const } else if(role == TileModel::TileIndexRole) { - return QVariant("("+QString::number(pvt->id())+")"); + return QVariant("("+QString::number(m_id)+")"); } else if(role == TileModel::TileFilenameIndexRole) { - return QVariant(tileFilename + " ("+QString::number(pvt->id())+")"); + return QVariant(tileFilename + " ("+QString::number(m_id)+")"); } return QVariant(); diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 342846ab8..2600f47d4 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -120,19 +120,13 @@ public: int columnCount() const; bool setTileFilename(TileConstants::TTileChannel channel, QString filename); QString getTileFilename(TileConstants::TTileChannel channel); - void setId( int id ); - int id() const; - QString getLastError() const; - bool borderFirst( TileConstants::TTileChannel channel ) const; - const NL3D::CTileBorder& border( TileConstants::TTileChannel channel ) const; - int alphaRot() const; + void setId( int id ){ m_id = id; } + int id() const{ return m_id; } static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } static void setAlphaRot( int rot ){ s_alphaRot = rot; } - bool hasError() const{ return m_hasError; } - QVariant pixmap( TileConstants::TTileChannel channel ) const; private: @@ -142,6 +136,8 @@ private: static TileConstants::TTileChannel s_displayChannel; static int s_alphaRot; + int m_id; + TileItemNodePvt *pvt; bool m_hasError; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index fbdd07223..862b03bce 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -232,7 +232,7 @@ TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType t { TileItemNode *n = new TileItemNode( type, id, channel, fileName ); - bool b = m_tileBank->addTileToSet( idx, fileName, n->pixmap( channel ), channel, type ); + bool b = m_tileBank->addTile( idx, fileName, n->pixmap( channel ), channel, type ); if( !b ) { delete n; @@ -310,11 +310,101 @@ void TileModel::addLand( const QString &name ) m_tileBank->addLand( name ); } +void TileModel::removeLand( int idx ) +{ + m_tileBank->removeLand( idx ); +} + void TileModel::setLandSets( int idx, const QStringList &l ) { m_tileBank->setLandSets( idx, l ); } +void TileModel::getLandSets( int idx, QStringList &l ) +{ + m_tileBank->getLandSets( idx, l ); +} + +void TileModel::removeTileSet( int idx ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( idx ) ); + if( set == NULL ) + return; + + removeRow( idx ); + + m_tileBank->removeTileSet( idx ); +} + +void TileModel::renameTileSet( int idx, const QString &newName ) +{ + m_tileBank->renameTileSet( idx, newName ); +} + +void TileModel::removeTile( int ts, int type, int tile ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( ts ) ); + if( set == NULL ) + return; + + TileTypeNode *typeNode = static_cast< TileTypeNode* >( set->child( type ) ); + if( typeNode == NULL ) + return; + + TileItemNode *tileNode = static_cast< TileItemNode* >( typeNode->child( tile ) ); + if( tileNode == NULL ) + return; + + QModelIndex tileIdx = createIndex( tile, 0, tileNode ); + removeRow( tile, tileIdx.parent() ); + + m_tileBank->removeTile( ts, type, tile ); +} + +bool TileModel::replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ) +{ + Node *set = rootItem->child( ts ); + Node *tn = set->child( type ); + Node *n = tn->child( tile ); + + TileItemNode *tin = static_cast< TileItemNode* >( n ); + QString old = tin->getTileFilename( channel ); + + bool b = tin->setTileFilename( channel, name ); + if( !b ) + return false; + + m_tileBank->replaceImage( ts, type, tile, channel, name, tin->pixmap( channel ) ); + if( m_tileBank->hasError() ) + { + tin->setTileFilename( channel, old ); + return false; + } + + return true; +} + +void TileModel::clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ) +{ + Node *set = rootItem->child( ts ); + Node *tn = set->child( type ); + Node *n = tn->child( tile ); + + TileItemNode *tin = static_cast< TileItemNode* >( n ); + tin->setTileFilename( channel, "" ); + + m_tileBank->clearImage( ts, type, tile, channel ); +} + +QString TileModel::getLastError() const{ + return m_tileBank->getLastError(); +} + +bool TileModel::hasError() const +{ + return m_tileBank->hasError(); +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 8472e6978..d2776bc86 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -89,7 +89,17 @@ public: QString texturePath() const{ return m_texturePath; } void addLand( const QString &name ); + void removeLand( int idx ); + void removeTileSet( int idx ); + void renameTileSet( int idx, const QString &newName ); void setLandSets( int idx, const QStringList &l ); + void getLandSets( int idx, QStringList &l ); + void removeTile( int ts, int type, int tile ); + bool replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ); + void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + QString getLastError() const; + bool hasError() const; public Q_SLOTS: void selectFilenameDisplay(bool selected); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 019745afd..945fd0908 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -26,138 +26,6 @@ class TileBankLoaderPvt { public: - NL3D::CTileBank bank; - - static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) - { - NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; - - switch( channel ) - { - case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; - case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; - } - - return b; - } - - void loadLands( QList< Land > &lands ) - { - lands.clear(); - - Land l; - - int c = bank.getLandCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileLand *land = bank.getLand( i ); - l.name = land->getName().c_str(); - - - std::set< std::string > sets = land->getTileSets(); - std::set< std::string >::const_iterator itr = sets.begin(); - while( itr != sets.end() ) - { - l.tilesets.push_back( itr->c_str() ); - ++itr; - } - - lands.push_back( l ); - } - } - - void loadTiles128( NL3D::CTileSet *set, TileTypeNode *node ) - { - int c = set->getNumTile128(); - for( int i = 0; i < c; i++ ) - { - int idx = set->getTile128( i ); - NL3D::CTile *tile = bank.getTile( idx ); - - TileItemNode *tin = new TileItemNode( TileConstants::Tile128, i, TileConstants::TileDiffuse, "" ); - - for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) - { - tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); - } - - node->appendChild( tin ); - } - } - - void loadTiles256( NL3D::CTileSet *set, TileTypeNode *node ) - { - int c = set->getNumTile256(); - for( int i = 0; i < c; i++ ) - { - int idx = set->getTile256( i ); - NL3D::CTile *tile = bank.getTile( idx ); - - TileItemNode *tin = new TileItemNode( TileConstants::Tile256, i, TileConstants::TileDiffuse, "" ); - - for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) - { - tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); - } - - node->appendChild( tin ); - } - } - - void loadTilesTransition( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < NL3D::CTileSet::count; i++ ) - { - const NL3D::CTileSetTransition *tr = set->getTransition( i ); - int idx = tr->getTile(); - NL3D::CTile *tile = bank.getTile( idx ); - - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - - for( int j = TileConstants::TileDiffuse; j <= TileConstants::TileAlpha; j++ ) - { - tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); - } - } - } - - void loadTilesDisplacement( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < NL3D::CTileSet::CountDisplace; i++ ) - { - uint did = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( i ) ); - const char *fn = bank.getDisplacementMap( did ); - - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - tin->setTileFilename( TileConstants::TileDiffuse, fn ); - } - } - - void loadTileSet( NL3D::CTileSet *set, TileSetNode *node ) - { - loadTiles128( set, static_cast< TileTypeNode* >( node->child( 0 ) ) ); - loadTiles256( set, static_cast< TileTypeNode* >( node->child( 1 ) ) ); - loadTilesTransition( set, static_cast< TileTypeNode* >( node->child( 2 ) ) ); - loadTilesDisplacement( set, static_cast< TileTypeNode* >( node->child( 3 ) ) ); - - node->setOriented( set->getOriented() ); - - node->setVegetSet( set->getTileVegetableDescFileName().c_str() ); - } - - void loadTileSets( TileModel *model ) - { - model->clear(); - - int c = bank.getTileSetCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileSet *set = bank.getTileSet( i ); - TileSetNode *node = model->createTileSetNode( set->getName().c_str() ); - loadTileSet( set, node ); - } - } }; @@ -178,12 +46,7 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > if( !file.open( filename, false ) ) return false; - p->bank.serial( file ); - - p->loadLands( lands ); - p->loadTileSets( model ); - - model->setTexturePath( p->bank.getAbsPath().c_str() ); + //p->bank.serial( file ); file.close(); diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 10f86eb14..15e31d141 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -25,251 +25,7 @@ class TileBankSaverPvt { public: - NL3D::CTileBank bank; - static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) - { - NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; - - switch( channel ) - { - case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; - case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; - } - - return b; - } - - NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileConstants::TNodeTileType type ) - { - int idx = -1; - int bidx = -1; - - switch( type ) - { - case TileConstants::Tile128: - { - set->addTile128( idx, bank ); - bidx = set->getTile128( idx ); - break; - } - - case TileConstants::Tile256: - { - set->addTile256( idx, bank ); - bidx = set->getTile256( idx ); - break; - } - } - - if( idx == -1 ) - return NULL; - - return bank.getTile( bidx ); - } - - void addTilesToSet( NL3D::CTileSet *set, TileTypeNode *node ) - { - TileConstants::TNodeTileType type = node->getTileType(); - - for( int i = 0; i < node->childCount(); i++ ) - { - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - NL3D::CTile *tile = addTileToSet( set, type ); - - for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) - { - QString fn = tin->getTileFilename( TileConstants::TTileChannel( j ) ); - tile->setFileName( channelToTBitmap( TileConstants::TTileChannel( j ) ) , fn.toUtf8().constData() ); - } - } - } - - void addTilesToSet( NL3D::CTileSet *set, TileSetNode *node ) - { - for( int i = TileConstants::Tile128; i <= TileConstants::Tile256; i++ ) - { - TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( i ) ); - - addTilesToSet( set, tn ); - } - } - - void setupTiles128( NL3D::CTileSet *set, TileTypeNode *node ) - { - TileItemNode *tileNode = NULL; - for( int i = 0; i < node->childCount(); i++ ) - { - tileNode = static_cast< TileItemNode* >( node->child( i ) ); - - for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) - { - TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - const NL3D::CTileBorder &border = tileNode->border( channel ); - - if( tileNode->borderFirst( channel ) ) - set->setBorder( bm, border ); - - set->setTile128( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); - } - } - } - - void setupTiles256( NL3D::CTileSet *set, TileTypeNode *node ) - { - TileItemNode *tileNode = NULL; - for( int i = 0; i < node->childCount(); i++ ) - { - tileNode = static_cast< TileItemNode* >( node->child( i ) ); - - for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) - { - TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - const NL3D::CTileBorder &border = tileNode->border( channel ); - - if( tileNode->borderFirst( channel ) ) - set->setBorder( bm, border ); - - set->setTile256( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); - } - } - } - - void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) - { - TileConstants::TTileChannel channel; - NL3D::CTile::TBitmap bm; - NL3D::CTileSet::TTransition tr; - - // Diffuse, Additive - for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) - { - channel =TileConstants::TTileChannel( i ); - bm = channelToTBitmap( channel ); - tr = NL3D::CTileSet::TTransition( idx ); - const NL3D::CTileBorder &border = node->border( channel ); - - if( node->borderFirst( channel ) ) - set->setBorder( bm, border ); - set->setTileTransition( tr, node->getTileFilename( channel ).toUtf8().constData(), bm, bank, border ); - } - - // Alpha - { - channel = TileConstants::TileAlpha; - bm = channelToTBitmap( channel ); - tr = NL3D::CTileSet::TTransition( idx ); - const NL3D::CTileBorder &border = node->border( channel ); - int rot = node->alphaRot(); - - set->setTileTransitionAlpha( tr, node->getTileFilename( channel ).toUtf8().constData(), bank, border, rot ); - } - } - - void setupTransitionTiles( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < node->childCount(); i++ ) - { - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - setupTransitionTile( set, tin, i ); - } - } - - void setupTransitionTiles( NL3D::CTileSet *set, TileSetNode *node ) - { - TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 2 ) ); - setupTransitionTiles( set, tn ); - } - - void setupDisplacementTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) - { - set->setDisplacement( NL3D::CTileSet::TDisplacement( idx ), - node->getTileFilename( TileConstants::TileDiffuse ).toUtf8().constData(), - bank ); - } - - void setupDisplacementTiles( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < node->childCount(); i++ ) - { - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - setupDisplacementTile( set, tin, i ); - } - } - - void setupDisplacementTiles( NL3D::CTileSet *set, TileSetNode *node ) - { - TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 3 ) ); - setupDisplacementTiles( set, tn ); - } - - void setupTiles( NL3D::CTileSet *set, TileSetNode *node ) - { - TileTypeNode *tn128 = static_cast< TileTypeNode* >( node->child( 0 ) ); - TileTypeNode *tn256 = static_cast< TileTypeNode* >( node->child( 1 ) ); - - setupTiles128( set, tn128 ); - setupTiles256( set, tn256 ); - setupTransitionTiles( set, node ); - setupDisplacementTiles( set, node ); - } - - void addLands( const QList< Land > &lands ) - { - QListIterator< Land > itr( lands ); - while( itr.hasNext() ) - { - bank.addLand( itr.next().name.toUtf8().constData() ); - } - } - - - void addTileSets( const TileModel* model, const QList< Land > &lands ) - { - // Add the tilesets - for( int i = 0; i < model->rowCount(); i++ ) - { - QModelIndex idx = model->index( i, 0 ); - if( !idx.isValid() ) - continue; - - TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - QString set = n->getTileSetName(); - bank.addTileSet( set.toUtf8().constData() ); - } - - // Set the data to tilesets - for( int i = 0; i < bank.getTileSetCount(); i++ ) - { - NL3D::CTileSet *set = bank.getTileSet( i ); - - QModelIndex idx = model->index( i, 0 ); - if( !idx.isValid() ) - continue; - - TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - - addTilesToSet( set, n ); - setupTiles( set, n ); - set->setOriented( n->isOriented() ); - set->setTileVegetableDescFileName( n->vegetSet().toUtf8().constData() ); - } - - // Add tilesets to lands - for( int i = 0; i < bank.getLandCount(); i++ ) - { - NL3D::CTileLand *land = bank.getLand( i ); - const Land &l = lands[ i ]; - - for( int j = 0; j < l.tilesets.count(); j++ ) - { - land->addTileSet( l.tilesets[ j ].toUtf8().constData() ); - } - } - } }; TileBankSaver::TileBankSaver() @@ -285,18 +41,13 @@ TileBankSaver::~TileBankSaver() bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< Land > &lands ) { - p->addLands( lands ); - p->addTileSets( model, lands ); - - p->bank.setAbsPath( model->texturePath().toUtf8().constData() ); - // Save to file NLMISC::COFile f; bool b = f.open( fileName, false, false, false ); if( !b ) return false; - p->bank.serial( f ); + //p->bank.serial( f ); f.flush(); f.close(); From 688f6de0909cdd8c07ed7a683d4628d8c1bf7917 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:33:11 +0200 Subject: [PATCH 217/282] Vegetation set stuff. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 19 +++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 10 ++++------ .../src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_model.h | 3 +++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index a44158259..8d9c3447c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -393,3 +393,22 @@ void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChann } +void TileBank::setVegetation( int tileSet, const QString &vegetation ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->setTileVegetableDescFileName( vegetation.toUtf8().constData() ); +} + + +QString TileBank::getVegetation( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return ""; + + return set->getTileVegetableDescFileName().c_str(); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index d81ae694b..e29f4564c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -29,6 +29,9 @@ public: bool setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + void setVegetation( int tileSet, const QString &vegetation ); + QString getVegetation( int tileSet ) const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index dffa7a61a..3331857c1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -542,8 +542,7 @@ void TileEditorMainWindow::onChooseVegetation() if( vegetSet.isEmpty() ) return; - TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - node->setVegetSet( vegetSet ); + m_tileModel->setVegetation( idx.row(), vegetSet ); m_ui->chooseVegetPushButton->setText( vegetSet ); } @@ -560,8 +559,7 @@ void TileEditorMainWindow::onResetVegetation() } m_ui->chooseVegetPushButton->setText( "..." ); - TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - node->setVegetSet( "" ); + m_tileModel->setVegetation( idx.row(), "" ); } void TileEditorMainWindow::onChooseTexturePath() @@ -860,9 +858,9 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons if( newIndex.isValid() ) newNode = reinterpret_cast< TileSetNode* >( newIndex.internalPointer() ); - if( newNode != NULL ) + if( newIndex.isValid() ) { - QString vegetSet = newNode->vegetSet(); + QString vegetSet = m_tileModel->getVegetation( newIndex.row() ); if( !vegetSet.isEmpty() ) m_ui->chooseVegetPushButton->setText( vegetSet ); diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 862b03bce..09d50cbef 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -396,6 +396,16 @@ void TileModel::clearImage( int ts, int type, int tile, TileConstants::TTileChan m_tileBank->clearImage( ts, type, tile, channel ); } +void TileModel::setVegetation( int tileSet, const QString &vegetation ) +{ + m_tileBank->setVegetation( tileSet, vegetation ); +} + +QString TileModel::getVegetation( int tileSet ) const +{ + return m_tileBank->getVegetation( tileSet ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index d2776bc86..9d8e00cde 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -98,6 +98,9 @@ public: bool replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + void setVegetation( int tileSet, const QString &vegetation ); + QString getVegetation( int tileSet ) const; + QString getLastError() const; bool hasError() const; From 55c046252f47eee82e29e571c5dbfe1175e412ec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:41:33 +0200 Subject: [PATCH 218/282] Oriented stuff. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 18 ++++++++++++++++++ .../studio/src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 10 +++++----- .../src/plugins/tile_editor/tile_item.cpp | 1 - .../studio/src/plugins/tile_editor/tile_item.h | 8 -------- .../src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_model.h | 3 +++ 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 8d9c3447c..85e69dd49 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -412,3 +412,21 @@ QString TileBank::getVegetation( int tileSet ) const return set->getTileVegetableDescFileName().c_str(); } +void TileBank::setOriented( int tileSet, bool b ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->setOriented( b ); +} + +bool TileBank::getOriented( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return false; + + return set->getOriented(); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index e29f4564c..ce6aa737c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -32,6 +32,9 @@ public: void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; + + void setOriented( int tileSet, bool b ); + bool getOriented( int tileSet ) const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 3331857c1..516db5ce3 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -590,12 +590,12 @@ void TileEditorMainWindow::onOrientedStateChanged( int state ) if( !idx.isValid() ) return; - TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - + int row = idx.row(); + if( state == Qt::Checked ) - node->setOriented( true ); + m_tileModel->setOriented( row, true ); else - node->setOriented( false ); + m_tileModel->setOriented( row, false ); } void TileEditorMainWindow::onDiffuseToggled( bool b ) @@ -867,7 +867,7 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons else m_ui->chooseVegetPushButton->setText( "..." ); - m_ui->orientedCheckBox->setChecked( newNode->isOriented() ); + m_ui->orientedCheckBox->setChecked( m_tileModel->getOriented( newIndex.row() ) ); } else { diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index e952d8d20..7c10ef9dc 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -173,7 +173,6 @@ void Node::clear() TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) { m_parentItem = parent; - m_oriented = false; } TileSetNode::~TileSetNode() diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 2600f47d4..8df33361b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -79,16 +79,8 @@ public: const QString &getTileSetName(){ return m_tileSetName; } void setTileSetName( const QString &name ){ m_tileSetName = name; } - void setVegetSet( const QString &s ){ m_vegetSet = s; } - QString vegetSet() const{ return m_vegetSet; } - - bool isOriented() const{ return m_oriented; } - void setOriented( bool b ){ m_oriented = b; } - private: QString m_tileSetName; - QString m_vegetSet; - bool m_oriented; }; class TileTypeNode : public Node diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 09d50cbef..f1372be80 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -406,6 +406,16 @@ QString TileModel::getVegetation( int tileSet ) const return m_tileBank->getVegetation( tileSet ); } +void TileModel::setOriented( int tileSet, bool b ) +{ + m_tileBank->setOriented( tileSet, b ); +} + +bool TileModel::getOriented( int tileSet ) const +{ + return m_tileBank->getOriented( tileSet ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 9d8e00cde..a58b55ce1 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -101,6 +101,9 @@ public: void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; + void setOriented( int tileSet, bool b ); + bool getOriented( int tileSet ) const; + QString getLastError() const; bool hasError() const; From bdedd145e4b88567fbf9b8c03934c1845dddfb1e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:53:22 +0200 Subject: [PATCH 219/282] Surface data. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 20 +++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 16 +++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + .../src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_model.h | 3 +++ 6 files changed, 53 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 85e69dd49..86c2646f9 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -430,3 +430,23 @@ bool TileBank::getOriented( int tileSet ) const return set->getOriented(); } + +void TileBank::setSurfaceData( int tileSet, unsigned long data ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->SurfaceData = data; +} + +unsigned long TileBank::getSurfaceData( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return 0; + + return set->SurfaceData; +} + + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index ce6aa737c..dddafe032 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -35,6 +35,9 @@ public: void setOriented( int tileSet, bool b ); bool getOriented( int tileSet ) const; + + void setSurfaceData( int tileSet, unsigned long data ); + unsigned long getSurfaceData( int tileSet ) const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 516db5ce3..f673d75c4 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -183,6 +183,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect( m_ui->actionOpenTileBank, SIGNAL( triggered() ), this, SLOT( open() ) ); connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); + connect( m_ui->surfaceDataLineEdit, SIGNAL( textEdited( const QString& ) ), this, SLOT( onSurfaceDataChanged( const QString& ) ) ); connect( m_ui->diffuse128BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); connect( m_ui->diffuse256BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); @@ -598,6 +599,20 @@ void TileEditorMainWindow::onOrientedStateChanged( int state ) m_tileModel->setOriented( row, false ); } +void TileEditorMainWindow::onSurfaceDataChanged( const QString &text ) +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + bool ok = false; + unsigned long data = text.toUInt( &ok ); + if( !ok ) + return; + + m_tileModel->setSurfaceData( idx.row(), data ); +} + void TileEditorMainWindow::onDiffuseToggled( bool b ) { if( !b ) @@ -868,6 +883,7 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->chooseVegetPushButton->setText( "..." ); m_ui->orientedCheckBox->setChecked( m_tileModel->getOriented( newIndex.row() ) ); + m_ui->surfaceDataLineEdit->setText( QString::number( m_tileModel->getSurfaceData( newIndex.row() ) ) ); } else { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 1ec80cd96..c9b96928c 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -68,6 +68,7 @@ private Q_SLOTS: void onChooseTexturePath(); void onOrientedStateChanged( int state ); + void onSurfaceDataChanged( const QString &text ); void onDiffuseToggled( bool b ); void onAdditiveToggled( bool b ); diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index f1372be80..e1d7019b4 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -416,6 +416,16 @@ bool TileModel::getOriented( int tileSet ) const return m_tileBank->getOriented( tileSet ); } +void TileModel::setSurfaceData( int tileSet, unsigned long data ) +{ + m_tileBank->setSurfaceData( tileSet, data ); +} + +unsigned long TileModel::getSurfaceData( int tileSet ) const +{ + return m_tileBank->getSurfaceData( tileSet ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index a58b55ce1..daec140ea 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -104,6 +104,9 @@ public: void setOriented( int tileSet, bool b ); bool getOriented( int tileSet ) const; + void setSurfaceData( int tileSet, unsigned long data ); + unsigned long getSurfaceData( int tileSet ) const; + QString getLastError() const; bool hasError() const; From 92e850d296155eded085a56c4fa1dbf762f61faf Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:59:05 +0200 Subject: [PATCH 220/282] Texture path. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_bank.cpp | 10 ++++++++++ code/studio/src/plugins/tile_editor/tile_bank.h | 3 +++ .../plugins/tile_editor/tile_editor_main_window.cpp | 2 +- code/studio/src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ code/studio/src/plugins/tile_editor/tile_model.h | 8 +++----- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 86c2646f9..a4dd3f358 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -449,4 +449,14 @@ unsigned long TileBank::getSurfaceData( int tileSet ) const return set->SurfaceData; } +void TileBank::setTexturePath( const QString &path ) +{ + m_pvt->m_bank.setAbsPath( path.toUtf8().constData() ); +} + +QString TileBank::getTexturePath() const +{ + return m_pvt->m_bank.getAbsPath().c_str(); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index dddafe032..c42546895 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -38,6 +38,9 @@ public: void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; + + void setTexturePath( const QString &path ); + QString getTexturePath() const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index f673d75c4..e8f19cedc 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -816,7 +816,7 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->listView256->reset(); m_ui->listViewTransition->reset(); - QString path = m_tileModel->texturePath(); + QString path = m_tileModel->getTexturePath(); if( path.isEmpty() ) m_ui->tileBankTexturePathPB->setText( "..." ); else diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index e1d7019b4..e1249cb14 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -426,6 +426,16 @@ unsigned long TileModel::getSurfaceData( int tileSet ) const return m_tileBank->getSurfaceData( tileSet ); } +void TileModel::setTexturePath( const QString &path ) +{ + m_tileBank->setTexturePath( path ); +} + +QString TileModel::getTexturePath() const +{ + return m_tileBank->getTexturePath(); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index daec140ea..96193fd38 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -85,9 +85,6 @@ public: void clear(); - void setTexturePath( const QString &path ){ m_texturePath = path; } - QString texturePath() const{ return m_texturePath; } - void addLand( const QString &name ); void removeLand( int idx ); void removeTileSet( int idx ); @@ -107,6 +104,9 @@ public: void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; + void setTexturePath( const QString &path ); + QString getTexturePath() const; + QString getLastError() const; bool hasError() const; @@ -125,8 +125,6 @@ private: //int m_activeEditChannel; Node *rootItem; - QString m_texturePath; - TileBank *m_tileBank; }; From 8bead3f3fdbe2d9b7ab44ad18e45691f690d5f02 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 22:14:39 +0200 Subject: [PATCH 221/282] Saving tilebank --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_bank.cpp | 5 +++++ code/studio/src/plugins/tile_editor/tile_bank.h | 7 +++++++ .../src/plugins/tile_editor/tile_editor_main_window.cpp | 3 +-- code/studio/src/plugins/tile_editor/tile_model.cpp | 5 +++++ code/studio/src/plugins/tile_editor/tile_model.h | 7 +++++++ code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 4 ++-- code/studio/src/plugins/tile_editor/tilebank_saver.h | 4 +--- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index a4dd3f358..62fcb3565 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -459,4 +459,9 @@ QString TileBank::getTexturePath() const return m_pvt->m_bank.getAbsPath().c_str(); } +void TileBank::serial( NLMISC::IStream &f ) +{ + m_pvt->m_bank.serial( f ); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index c42546895..d267486a8 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -7,6 +7,11 @@ #include "tile_constants.h" +namespace NLMISC +{ + class IStream; +} + class TileBankPvt; class TileBank @@ -41,6 +46,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + + void serial( NLMISC::IStream &f ); bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index e8f19cedc..ed8c1ae54 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -250,8 +250,7 @@ void TileEditorMainWindow::saveAs( const QString &fn ) } TileBankSaver saver; - bool ok = true; - //saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool ok = saver.save( fn.toUtf8().constData(), m_tileModel ); if( !ok ) { diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index e1249cb14..4b14f54fb 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -431,6 +431,11 @@ void TileModel::setTexturePath( const QString &path ) m_tileBank->setTexturePath( path ); } +void TileModel::serial( NLMISC::IStream &f ) +{ + m_tileBank->serial( f ); +} + QString TileModel::getTexturePath() const { return m_tileBank->getTexturePath(); diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 96193fd38..c831daae2 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -23,6 +23,11 @@ #include "tile_constants.h" +namespace NLMISC +{ + class IStream; +} + class Node; class TileSetNode; class TileItemNode; @@ -107,6 +112,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + void serial( NLMISC::IStream &f ); + QString getLastError() const; bool hasError() const; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 15e31d141..a0b8abcfb 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -39,7 +39,7 @@ TileBankSaver::~TileBankSaver() p = NULL; } -bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< Land > &lands ) +bool TileBankSaver::save( const char *fileName, TileModel* model ) { // Save to file NLMISC::COFile f; @@ -47,7 +47,7 @@ bool TileBankSaver::save( const char *fileName, const TileModel* model, const QL if( !b ) return false; - //p->bank.serial( f ); + model->serial( f ); f.flush(); f.close(); diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index 2a2806fe1..ef1e0de94 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -20,10 +20,8 @@ #include #include -#include "land.h" class TileModel; - class TileBankSaverPvt; class TileBankSaver @@ -32,7 +30,7 @@ public: TileBankSaver(); ~TileBankSaver(); - bool save( const char *filename, const TileModel* model, const QList< Land > &lands ); + bool save( const char *filename, TileModel* model ); private: TileBankSaverPvt *p; From d21aa2b678a0da9dd92340fbb20aca364f2b098d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 02:58:31 +0200 Subject: [PATCH 222/282] Tile loading more or less works. TODO: investigate why displacement map lookup causes crashes. --HG-- branch : gsoc2014-dfighter --- code/nel/include/nel/3d/tile_bank.h | 5 + code/studio/src/plugins/tile_editor/land.h | 31 ---- .../src/plugins/tile_editor/tile_bank.cpp | 142 ++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 10 ++ .../tile_editor/tile_editor_main_window.cpp | 26 ++-- .../src/plugins/tile_editor/tile_images.h | 23 +++ .../src/plugins/tile_editor/tile_item.cpp | 8 + .../src/plugins/tile_editor/tile_item.h | 1 + .../src/plugins/tile_editor/tile_model.cpp | 128 +++++++++++++++- .../src/plugins/tile_editor/tile_model.h | 16 +- .../plugins/tile_editor/tilebank_loader.cpp | 16 +- .../src/plugins/tile_editor/tilebank_loader.h | 6 +- .../plugins/tile_editor/tilebank_saver.cpp | 9 -- .../src/plugins/tile_editor/tilebank_saver.h | 3 +- 14 files changed, 342 insertions(+), 82 deletions(-) delete mode 100644 code/studio/src/plugins/tile_editor/land.h create mode 100644 code/studio/src/plugins/tile_editor/tile_images.h diff --git a/code/nel/include/nel/3d/tile_bank.h b/code/nel/include/nel/3d/tile_bank.h index 89b8e2272..00e0f2cae 100644 --- a/code/nel/include/nel/3d/tile_bank.h +++ b/code/nel/include/nel/3d/tile_bank.h @@ -86,6 +86,11 @@ public: _BitmapName[bitmapType]=name; } + std::string getFileName (TBitmap bitmapType) const + { + return _BitmapName[bitmapType]; + } + /// Get the additional orientation (CCW) for alpha texture. uint8 getRotAlpha () { diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h deleted file mode 100644 index 93d244d9d..000000000 --- a/code/studio/src/plugins/tile_editor/land.h +++ /dev/null @@ -1,31 +0,0 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef LAND_H -#define LAND_H - -#include - -struct Land -{ - QString name; - QStringList tilesets; -}; - - -#endif - diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 62fcb3565..3a7b34ca8 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -229,6 +229,16 @@ void TileBank::renameTileSet( int idx, const QString &newName ) } +void TileBank::getTileSets( QStringList &l ) +{ + int c = m_pvt->m_bank.getTileSetCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( i ); + l.push_back( set->getName().c_str() ); + } +} + void TileBank::addLand( const QString &name ) { m_pvt->m_bank.addLand( name.toUtf8().constData() ); @@ -239,6 +249,18 @@ void TileBank::removeLand( int idx ) m_pvt->m_bank.removeLand( idx ); } +void TileBank::getLands( QStringList &l ) +{ + l.clear(); + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + l.push_back( land->getName().c_str() ); + } +} + void TileBank::setLandSets( int idx, const QStringList &l ) { NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); @@ -392,6 +414,126 @@ void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChann } +int TileBank::getTileCount( int tileSet, TileConstants::TNodeTileType type ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return -1; + + int c = 0; + + switch( type ) + { + case TileConstants::Tile128: + c = set->getNumTile128(); + break; + + case TileConstants::Tile256: + c = set->getNumTile256(); + break; + + case TileConstants::TileTransition: + c = NL3D::CTileSet::count; + break; + + case TileConstants::TileDisplacement: + c = NL3D::CTileSet::CountDisplace; + break; + } + + return c; +} + +int TileBank::getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return -1; + + int tile = -1; + + switch( type ) + { + case TileConstants::Tile128: + tile = set->getTile128( tileIdInSet ); + break; + + case TileConstants::Tile256: + tile = set->getTile256( tileIdInSet ); + break; + + case TileConstants::TileTransition: + tile = set->getTransition( tileIdInSet )->getTile(); + break; + + case TileConstants::TileDisplacement: + tile = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( tileIdInSet ) ); + break; + } + + return tile; +} + +void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + switch( type ) + { + case TileConstants::Tile128: + case TileConstants::Tile256: + case TileConstants::TileTransition: + { + NL3D::CTile *t = m_pvt->m_bank.getTile( tileId ); + if( t == NULL ) + return; + + images.diffuse = t->getFileName( channelToTBitmap( TileConstants::TileDiffuse ) ).c_str(); + images.additive = t->getFileName( channelToTBitmap( TileConstants::TileAdditive ) ).c_str(); + images.alpha = t->getFileName( channelToTBitmap( TileConstants::TileAlpha ) ).c_str(); + } + break; + + case TileConstants::TileDisplacement: + { + images.diffuse = m_pvt->m_bank.getDisplacementMap( tileId ); + } + break; + } + +} + +void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ) +{ + l.clear(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + int c = getTileCount( tileSet, type ); + + TileImages images; + + for( int i = 0; i < c; i++ ) + { + images.clear(); + + int id = getRealTileId( tileSet, type, i ); + if( id < 0 ) + { + l.push_back( images ); + continue; + } + + getTileImages( tileSet, type, id, images ); + + l.push_back( images ); + } + +} void TileBank::setVegetation( int tileSet, const QString &vegetation ) { diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index d267486a8..e420fac9c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -4,8 +4,10 @@ #include #include #include +#include #include "tile_constants.h" +#include "tile_images.h" namespace NLMISC { @@ -23,9 +25,11 @@ public: void addTileSet( const QString &name ); void removeTileSet( int idx ); void renameTileSet( int idx, const QString &newName ); + void getTileSets( QStringList &l ); void addLand( const QString &name ); void removeLand( int idx ); + void getLands( QStringList &l ); void setLandSets( int idx, const QStringList &l ); void getLandSets( int idx, QStringList &l ); @@ -35,6 +39,12 @@ public: void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + int getTileCount( int tileSet, TileConstants::TNodeTileType type ); + int getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ); + void getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ); + void getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ); + void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index ed8c1ae54..86953f6a7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -271,8 +271,7 @@ void TileEditorMainWindow::open() return; TileBankLoader loader; - bool b = true; - //loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool b = loader.load( fn.toUtf8().constData(), m_tileModel ); if( !b ) { @@ -374,7 +373,7 @@ void TileEditorMainWindow::onTileSetAdd() } // Create and append the new tile set to the model. - TileSetNode *tileSet = model->createTileSetNode(text); + m_tileModel->addTileSet( text ); // Retrieve how many rows there currently are and set the current index using that. uint32 rows = model->rowCount(); @@ -684,8 +683,6 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QString selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); - int c = n->childCount(); - TileConstants::TNodeTileType type = tabToType( tabId ); QStringListIterator itr( fileNames ); @@ -693,8 +690,9 @@ void TileEditorMainWindow::onActionAddTile(int tabId) while( itr.hasNext() ) { - TileItemNode *newNode = m_tileModel->createItemNode( setId, type, c, TileConstants::TileDiffuse, itr.next() ); - if( newNode == NULL ) + bool b = m_tileModel->addTile( setId, type, itr.next(), TileConstants::TileDiffuse ); + + if( !b ) { if( m_tileModel->hasError() ) error = m_tileModel->getLastError(); @@ -708,9 +706,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) else continue; } - - n->appendRow( newNode ); - c++; + } QModelIndex rootIdx = m_tileModel->index( tabId, 0, m_ui->tileSetLV->currentIndex()); @@ -809,7 +805,15 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) void TileEditorMainWindow::onTileBankLoaded() { m_ui->landLW->clear(); - // load lands + QStringList lands; + m_tileModel->getLands( lands ); + QStringListIterator itr( lands ); + while( itr.hasNext() ) + { + m_ui->landLW->addItem( itr.next() ); + } + + m_tileModel->onTBLoaded(); m_ui->listView128->reset(); m_ui->listView256->reset(); diff --git a/code/studio/src/plugins/tile_editor/tile_images.h b/code/studio/src/plugins/tile_editor/tile_images.h new file mode 100644 index 000000000..699fe3f11 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_images.h @@ -0,0 +1,23 @@ +#ifndef TILE_IMAGES_H +#define TILE_IMAGES_H + +#include + +struct TileImages +{ + QString diffuse; + QString additive; + QString alpha; + + void clear() + { + diffuse.clear(); + additive.clear(); + alpha.clear(); + } +}; + + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 7c10ef9dc..cba20ce2d 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -312,6 +312,14 @@ TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileC setTileFilename( channel, filename ); } +TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) +{ + m_id = tileId; + m_parentItem = parent; + pvt = new TileItemNodePvt(); + m_hasError = false; +} + TileItemNode::~TileItemNode() { delete pvt; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 8df33361b..08de0ec1f 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -107,6 +107,7 @@ class TileItemNode : public Node { public: TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent=0); + TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 4b14f54fb..d9e9b7ef3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -218,16 +218,10 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // Append them in the correct order to the tile set. this->appendRow(tileSet); - m_tileBank->addTileSet(tileSetName); - + return tileSet; } -TileItemNode *TileModel::createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) -{ - return new TileItemNode( type, id, channel, fileName ); -} - TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) { TileItemNode *n = new TileItemNode( type, id, channel, fileName ); @@ -305,6 +299,12 @@ void TileModel::clear() removeRows( 0, c ); } +void TileModel::onTBLoaded() +{ + loadTileSets(); +} + + void TileModel::addLand( const QString &name ) { m_tileBank->addLand( name ); @@ -315,6 +315,11 @@ void TileModel::removeLand( int idx ) m_tileBank->removeLand( idx ); } +void TileModel::getLands( QStringList &l ) +{ + m_tileBank->getLands( l ); +} + void TileModel::setLandSets( int idx, const QStringList &l ) { m_tileBank->setLandSets( idx, l ); @@ -325,6 +330,15 @@ void TileModel::getLandSets( int idx, QStringList &l ) m_tileBank->getLandSets( idx, l ); } + +bool TileModel::addTileSet( const QString &name ) +{ + m_tileBank->addTileSet( name ); + TileSetNode *tsn = createTileSetNode( name ); + + return false; +} + void TileModel::removeTileSet( int idx ) { TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( idx ) ); @@ -341,6 +355,35 @@ void TileModel::renameTileSet( int idx, const QString &newName ) m_tileBank->renameTileSet( idx, newName ); } +bool TileModel::addTile( int ts, int type, const QString &fileName, TileConstants::TTileChannel channel ) +{ + TileSetNode *tsn = static_cast< TileSetNode* >( rootItem->child( ts ) ); + if( tsn == NULL ) + return false; + + TileTypeNode *ttn = static_cast< TileTypeNode* >( tsn->child( type ) ); + if( ttn == NULL ) + return false; + + int tile = ttn->childCount(); + + TileConstants::TNodeTileType t = TileConstants::TNodeTileType( type ); + + TileItemNode *item = new TileItemNode( t, tile, channel, fileName ); + + bool b = m_tileBank->addTile( ts, fileName, item->pixmap( channel ), channel, t ); + if( !b ) + { + delete item; + return false; + } + + item->setParent( ttn ); + ttn->appendRow( item ); + + return true; +} + void TileModel::removeTile( int ts, int type, int tile ) { TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( ts ) ); @@ -458,4 +501,73 @@ void TileModel::selectFilenameDisplay(bool selected) void TileModel::selectIndexDisplay(bool selected) { m_indexDisplay = selected; -} \ No newline at end of file +} + +void TileModel::loadTileSets() +{ + QStringList l; + m_tileBank->getTileSets( l ); + + // Create tile sets + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + createTileSetNode( itr.next() ); + } + + // Loads sets + int c = rootItem->childCount(); + for( int i = 0; i < c; i++ ) + { + loadTileSet( i ); + } +} + + +void TileModel::loadTileSet( int tileSet ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( tileSet ) ); + + QList< TileImages > l; + //for( int i = TileConstants::Tile128; i < TileConstants::TileNodeTypeCount; i++ ) + //for( int i = TileConstants::Tile128; i < TileConstants::TileTransition; i++ ) + for( int i = TileConstants::Tile128; i < TileConstants::TileDisplacement; i++ ) + { + TileConstants::TNodeTileType type = TileConstants::TNodeTileType( i ); + l.clear(); + m_tileBank->getTileImages( tileSet, type, l ); + + loadTileTypeNode( tileSet, type, l ); + } +} + +void TileModel::loadTileTypeNode( int tileSet, int type, const QList< TileImages > &l ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( tileSet ) ); + TileTypeNode *ttn = static_cast< TileTypeNode* >( set->child( type ) ); + + int tile = 0; + + QList< TileImages >::const_iterator itr = l.begin(); + while( itr != l.end() ) + { + const TileImages &images = *itr; + + TileItemNode *item = NULL; + + if( ( type == TileConstants::Tile128 ) || ( type == TileConstants::Tile256 ) ) + item = new TileItemNode( TileConstants::TNodeTileType( type ), tile, ttn ); + else + item = static_cast< TileItemNode* >( ttn->child( tile ) ); + + item->setTileFilename( TileConstants::TileDiffuse, images.diffuse ); + item->setTileFilename( TileConstants::TileAdditive, images.additive ); + item->setTileFilename( TileConstants::TileAlpha, images.alpha ); + + if( ( type == TileConstants::Tile128 ) || ( type == TileConstants::Tile256 ) ) + ttn->appendRow( item ); + + ++itr; + tile++; + } +} diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index c831daae2..b0e3232b9 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -22,6 +22,7 @@ #include #include "tile_constants.h" +#include "tile_images.h" namespace NLMISC { @@ -32,6 +33,7 @@ class Node; class TileSetNode; class TileItemNode; class TileBank; +class TileModelPvt; class TileModel : public QAbstractItemModel { @@ -77,8 +79,6 @@ public: void swapRows( int a, int b ); - TileSetNode *createTileSetNode(QString tileSetName); - static TileItemNode *createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); TileItemNode *createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); static const char *getTileTypeName(TileConstants::TNodeTileType type); @@ -89,13 +89,20 @@ public: bool hasTileSet( const QString &name ); void clear(); + void onTBLoaded(); void addLand( const QString &name ); void removeLand( int idx ); + void getLands( QStringList &l ); + + bool addTileSet( const QString &name ); + void removeTileSet( int idx ); void renameTileSet( int idx, const QString &newName ); void setLandSets( int idx, const QStringList &l ); void getLandSets( int idx, QStringList &l ); + + bool addTile( int ts, int type, const QString &fileName, TileConstants::TTileChannel channel ); void removeTile( int ts, int type, int tile ); bool replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); @@ -122,7 +129,11 @@ public Q_SLOTS: void selectIndexDisplay(bool selected); private: + TileSetNode *createTileSetNode(QString tileSetName); Node *getItem(const QModelIndex &index) const; + void loadTileSets(); + void loadTileSet( int tileSet ); + void loadTileTypeNode( int tileSet, int type, const QList< TileImages > &l ); bool m_fileDisplay; bool m_indexDisplay; @@ -133,6 +144,7 @@ private: Node *rootItem; TileBank *m_tileBank; + TileModelPvt *pvt; }; #endif // TILE_MODEL_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 945fd0908..1aaa055f0 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -18,35 +18,23 @@ #include "tilebank_loader.h" #include "tile_model.h" -#include "tile_item.h" - -#include "nel/3d/tile_bank.h" #include "nel/misc/file.h" -class TileBankLoaderPvt -{ -public: -}; - - TileBankLoader::TileBankLoader() { - p = new TileBankLoaderPvt; } TileBankLoader::~TileBankLoader() { - delete p; - p = NULL; } -bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > &lands ) +bool TileBankLoader::load( const char *filename, TileModel *model ) { NLMISC::CIFile file; if( !file.open( filename, false ) ) return false; - //p->bank.serial( file ); + model->serial( file ); file.close(); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h index 1f3498d6e..643cab67f 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.h +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -17,10 +17,7 @@ #ifndef TILEBANK_LOADER_H #define TILEBANK_LOADER_H -#include "land.h" - class TileModel; -class TileBankLoaderPvt; class TileBankLoader { @@ -28,10 +25,9 @@ public: TileBankLoader(); ~TileBankLoader(); - bool load( const char *filename, TileModel *model, QList< Land > &lands ); + bool load( const char *filename, TileModel *model ); private: - TileBankLoaderPvt *p; }; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index a0b8abcfb..3f087c979 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -22,21 +22,12 @@ #include "nel/3d/tile_bank.h" #include "nel/misc/file.h" -class TileBankSaverPvt -{ -public: - -}; - TileBankSaver::TileBankSaver() { - p = new TileBankSaverPvt(); } TileBankSaver::~TileBankSaver() { - delete p; - p = NULL; } bool TileBankSaver::save( const char *fileName, TileModel* model ) diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index ef1e0de94..0f8983157 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -22,7 +22,6 @@ #include class TileModel; -class TileBankSaverPvt; class TileBankSaver { @@ -33,7 +32,7 @@ public: bool save( const char *filename, TileModel* model ); private: - TileBankSaverPvt *p; + }; #endif From 2a55904b3e77ef10c0d1250249fea234f176bd7e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:17:29 +0200 Subject: [PATCH 223/282] Makes no sense, but doesn't seem to be crashing anymore o.O --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_model.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d9e9b7ef3..46ef27ca0 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -529,9 +529,7 @@ void TileModel::loadTileSet( int tileSet ) TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( tileSet ) ); QList< TileImages > l; - //for( int i = TileConstants::Tile128; i < TileConstants::TileNodeTypeCount; i++ ) - //for( int i = TileConstants::Tile128; i < TileConstants::TileTransition; i++ ) - for( int i = TileConstants::Tile128; i < TileConstants::TileDisplacement; i++ ) + for( int i = TileConstants::Tile128; i < TileConstants::TileNodeTypeCount; i++ ) { TileConstants::TNodeTileType type = TileConstants::TNodeTileType( i ); l.clear(); From 84fc5f27b61e537b730e7bc00e4eade1e85a3099 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:20:30 +0200 Subject: [PATCH 224/282] Clear before loading the model data. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_model.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 46ef27ca0..14016024a 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -301,6 +301,7 @@ void TileModel::clear() void TileModel::onTBLoaded() { + clear(); loadTileSets(); } From e2a579c03e994420d13dd6c120f3de2aa6365bb5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:35:10 +0200 Subject: [PATCH 225/282] Set all images by default. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_item.cpp | 17 +++++---------- .../src/plugins/tile_editor/tile_item.h | 1 - .../src/plugins/tile_editor/tile_model.cpp | 21 ++++--------------- .../src/plugins/tile_editor/tile_model.h | 2 -- 4 files changed, 9 insertions(+), 32 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index cba20ce2d..7d339b1db 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -300,24 +300,17 @@ private: TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; int TileItemNode::s_alphaRot = 0; -TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent) -{ - m_id = tileId; - m_parentItem = parent; - //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); - - pvt = new TileItemNodePvt(); - m_hasError = false; - - setTileFilename( channel, filename ); -} - TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) { m_id = tileId; m_parentItem = parent; pvt = new TileItemNodePvt(); m_hasError = false; + + for( int i = 0; i < TileConstants::TileChannelCount; i++ ) + { + setTileFilename( TileConstants::TTileChannel( i ), "" ); + } } TileItemNode::~TileItemNode() diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 08de0ec1f..85da09c4f 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -106,7 +106,6 @@ class TileItemNodePvt; class TileItemNode : public Node { public: - TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent=0); TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 14016024a..f4b9dfa15 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -200,7 +200,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode( TileConstants::TileTransition, transPos, TileConstants::TileDiffuse, QString("empty")); + TileItemNode *transTile= new TileItemNode( TileConstants::TileTransition, transPos ); tileTrans->appendRow(transTile); } @@ -212,7 +212,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode( TileConstants::TileDisplacement, dispPos, TileConstants::TileDiffuse, QString("empty")); + TileItemNode *dispTile= new TileItemNode( TileConstants::TileDisplacement, dispPos ); tileDisp->appendRow(dispTile); } @@ -222,20 +222,6 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) return tileSet; } -TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) -{ - TileItemNode *n = new TileItemNode( type, id, channel, fileName ); - - bool b = m_tileBank->addTile( idx, fileName, n->pixmap( channel ), channel, type ); - if( !b ) - { - delete n; - return NULL; - } - - return n; -} - const char *TileModel::getTileTypeName(TileConstants::TNodeTileType type) { switch(type) @@ -370,7 +356,8 @@ bool TileModel::addTile( int ts, int type, const QString &fileName, TileConstant TileConstants::TNodeTileType t = TileConstants::TNodeTileType( type ); - TileItemNode *item = new TileItemNode( t, tile, channel, fileName ); + TileItemNode *item = new TileItemNode( t, tile ); + item->setTileFilename( channel, fileName ); bool b = m_tileBank->addTile( ts, fileName, item->pixmap( channel ), channel, t ); if( !b ) diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index b0e3232b9..8a89076bb 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -79,8 +79,6 @@ public: void swapRows( int a, int b ); - TileItemNode *createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); - static const char *getTileTypeName(TileConstants::TNodeTileType type); static uint32 getTileTypeSize(TileConstants::TNodeTileType type); From 99bcb6cf79f66ca8c3e08f0e12f2f454d31bb36e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 13:18:41 +0200 Subject: [PATCH 226/282] Line endings and copyright headers... --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 17 +++++++ .../src/plugins/tile_editor/tile_bank.h | 19 +++++++- .../src/plugins/tile_editor/tile_constants.h | 47 +++++++++++++------ .../src/plugins/tile_editor/tile_images.h | 17 +++++++ .../src/plugins/tile_editor/tile_model.h | 4 +- 5 files changed, 86 insertions(+), 18 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 3a7b34ca8..47e26511f 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "tile_bank.h" #include "nel/3d/tile_bank.h" diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index e420fac9c..55901584a 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef TILE_BANK_H #define TILE_BANK_H @@ -54,7 +71,7 @@ public: void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; - void setTexturePath( const QString &path ); + void setTexturePath( const QString &path ); QString getTexturePath() const; void serial( NLMISC::IStream &f ); diff --git a/code/studio/src/plugins/tile_editor/tile_constants.h b/code/studio/src/plugins/tile_editor/tile_constants.h index e75664d43..bf09f21a5 100644 --- a/code/studio/src/plugins/tile_editor/tile_constants.h +++ b/code/studio/src/plugins/tile_editor/tile_constants.h @@ -1,24 +1,41 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef TILE_CONSTANTS_H #define TILE_CONSTANTS_H namespace TileConstants { - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - TileChannelCount = 3 - }; - - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3, - TileNodeTypeCount = 4 + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + TileChannelCount = 3 + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3, + TileNodeTypeCount = 4 }; } diff --git a/code/studio/src/plugins/tile_editor/tile_images.h b/code/studio/src/plugins/tile_editor/tile_images.h index 699fe3f11..e17267001 100644 --- a/code/studio/src/plugins/tile_editor/tile_images.h +++ b/code/studio/src/plugins/tile_editor/tile_images.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef TILE_IMAGES_H #define TILE_IMAGES_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 8a89076bb..dafbf09f8 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -108,10 +108,10 @@ public: void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; - void setOriented( int tileSet, bool b ); + void setOriented( int tileSet, bool b ); bool getOriented( int tileSet ) const; - void setSurfaceData( int tileSet, unsigned long data ); + void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; void setTexturePath( const QString &path ); From f25d152f4fff5d2bbf3c23bfc0243b9aaeb748d5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 13:42:56 +0200 Subject: [PATCH 227/282] Rotation is now set in the tilebank wrapper and applied when replacing a tile. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 18 +++++++++++++++++- .../studio/src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 2 +- .../src/plugins/tile_editor/tile_item.cpp | 1 - .../studio/src/plugins/tile_editor/tile_item.h | 2 -- .../src/plugins/tile_editor/tile_model.cpp | 5 +++++ .../src/plugins/tile_editor/tile_model.h | 2 ++ 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 47e26511f..9a4d15469 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -198,6 +198,7 @@ TileBank::TileBank() { m_pvt = new TileBankPvt(); resetError(); + m_rotation = 0; } TileBank::~TileBank() @@ -378,6 +379,16 @@ bool TileBank::setTile( int tileset, int tile, const QString &name, const QVaria NL3D::CTileBorder border; m_pvt->buildBorder( pm, border ); + if( ( type == TileConstants::TileTransition ) && ( channel == TileConstants::TileAlpha ) ) + { + int rotBits = m_rotation; + while( rotBits > 0 ) + { + border.rotate(); + rotBits--; + } + } + QString msg; NL3D::CTileSet::TError error = m_pvt->checkTile( set, tile, type, border, channelToTBitmap( channel ), msg ); @@ -387,7 +398,7 @@ bool TileBank::setTile( int tileset, int tile, const QString &name, const QVaria if( error == NL3D::CTileSet::addFirstA128128 ) set->setBorder( channelToTBitmap( channel ), border ); - m_pvt->setTile( set, tile, 0 /* rotation */, name, channelToTBitmap( channel ), type, border ); + m_pvt->setTile( set, tile, m_rotation, name, channelToTBitmap( channel ), type, border ); return true; } @@ -618,6 +629,11 @@ QString TileBank::getTexturePath() const return m_pvt->m_bank.getAbsPath().c_str(); } +void TileBank::setRotation( int rotation ) +{ + m_rotation = rotation; +} + void TileBank::serial( NLMISC::IStream &f ) { m_pvt->m_bank.serial( f ); diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index 55901584a..a4620ad41 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -74,6 +74,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + void setRotation( int rotation ); + void serial( NLMISC::IStream &f ); bool hasError() const{ return m_hasError; } @@ -93,6 +95,7 @@ private: TileBankPvt *m_pvt; QString m_lastError; bool m_hasError; + int m_rotation; }; #endif diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 86953f6a7..0341502d5 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -335,7 +335,7 @@ void TileEditorMainWindow::onZoomFactor(int level) void TileEditorMainWindow::onRotate( int id ) { - TileItemNode::setAlphaRot( id * 90 ); + m_tileModel->setAlphaRot( id ); } void TileEditorMainWindow::onActionAddTile(bool triggered) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 7d339b1db..f39ba87dc 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -298,7 +298,6 @@ private: }; TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; -int TileItemNode::s_alphaRot = 0; TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) { diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 85da09c4f..7af553c8e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -117,7 +117,6 @@ public: static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } - static void setAlphaRot( int rot ){ s_alphaRot = rot; } QVariant pixmap( TileConstants::TTileChannel channel ) const; @@ -126,7 +125,6 @@ private: QMap m_tileWidget; static TileConstants::TTileChannel s_displayChannel; - static int s_alphaRot; int m_id; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index f4b9dfa15..2af4c6a84 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -472,6 +472,11 @@ QString TileModel::getTexturePath() const return m_tileBank->getTexturePath(); } +void TileModel::setAlphaRot( int rotation ) +{ + m_tileBank->setRotation( rotation ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index dafbf09f8..c6bfc8788 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -117,6 +117,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + void setAlphaRot( int rotation ); + void serial( NLMISC::IStream &f ); QString getLastError() const; From 04d17b7a05a094f08106fdd2490dfc7b49def19d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 15:16:25 +0200 Subject: [PATCH 228/282] Save the last directoy where we loaded a tilebank from. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 5 ++++- .../studio/src/plugins/tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 0341502d5..62aea3fcb 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -264,7 +264,7 @@ void TileEditorMainWindow::open() { QString fn = QFileDialog::getOpenFileName( this, tr( "Loading tilebank" ), - "", + m_lastOpenDir, tr( "tilebank files (*.tilebank)" ) ); if( fn.isEmpty() ) @@ -284,6 +284,9 @@ void TileEditorMainWindow::open() onTileBankLoaded(); m_fileName = fn; + + int idx = fn.lastIndexOf( '/' ); + m_lastOpenDir = fn.left( idx ); } void TileEditorMainWindow::onZoomFactor(int level) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index c9b96928c..550c6bb75 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -122,6 +122,7 @@ private: }; QString m_fileName; + QString m_lastOpenDir; }; #endif // TILE_EDITOR_MAIN_WINDOW_H From edf1da1294baf0641122327732d9f106a2789c35 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 15:34:29 +0200 Subject: [PATCH 229/282] Save the last directory where we loaded a tile image from. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 14 ++++++++++++-- .../plugins/tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 62aea3fcb..a6571c3e7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -684,7 +684,9 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QFileDialog::Options options; QString selectedFilter; - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); + QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", m_lastTileDir , "Images (*.png);;All Files (*.*)", &selectedFilter, options); + if( fileNames.empty() ) + return; TileConstants::TNodeTileType type = tabToType( tabId ); @@ -719,6 +721,10 @@ void TileEditorMainWindow::onActionAddTile(int tabId) lv->reset(); lv->setRootIndex( rootIdx ); lv->setCurrentIndex( lv->model()->index( 0, 0, rootIdx ) ); + + QString fn = fileNames[ 0 ].replace( '\\', '/' ); + int slashIdx = fn.lastIndexOf( '/' ); + m_lastTileDir = fn.left( slashIdx ); } void TileEditorMainWindow::onActionDeleteTile( int tabId ) @@ -787,7 +793,7 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) QString fileName = QFileDialog::getOpenFileName( this, tr( "Select tile image" ), - "", + m_lastTileDir, tr( "PNG files (*.png)" ) ); if( fileName.isEmpty() ) return; @@ -803,6 +809,10 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) tr( "Error replacing tile image" ), error ); } + + QString fn = fileName.replace( '\\', '/' ); + int slashIdx = fn.lastIndexOf( '/' ); + m_lastTileDir = fn.left( slashIdx ); } void TileEditorMainWindow::onTileBankLoaded() diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 550c6bb75..9dee6954d 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -123,6 +123,7 @@ private: QString m_fileName; QString m_lastOpenDir; + QString m_lastTileDir; }; #endif // TILE_EDITOR_MAIN_WINDOW_H From 613643b033a5785a20dc97b4e3cfd543dad63740 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 16:01:45 +0200 Subject: [PATCH 230/282] Repaint immediately when the display channel is changed. --HG-- branch : gsoc2014-dfighter --- .../plugins/tile_editor/tile_editor_main_window.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a6571c3e7..9f4851058 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -848,7 +848,15 @@ void TileEditorMainWindow::onTileBankLoaded() void TileEditorMainWindow::updateTab() { - m_ui->tileViewTabWidget->currentWidget()->repaint(); + int idx = m_ui->tileViewTabWidget->currentIndex(); + + switch( idx ) + { + case 0: m_ui->listView128->viewport()->repaint(); break; + case 1: m_ui->listView256->viewport()->repaint(); break; + case 2: m_ui->listViewTransition->viewport()->repaint(); break; + case 3: m_ui->listViewDisplacement->viewport()->repaint(); break; + } } TileModel* TileEditorMainWindow::createTileModel() From e7ded1f82c25ea3ac775844daa51457b82e31f31 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:01:44 +0200 Subject: [PATCH 231/282] Removed unused variable. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_item.cpp | 2 -- code/studio/src/plugins/tile_editor/tile_item.h | 1 - 2 files changed, 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index f39ba87dc..04889e61b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -304,7 +304,6 @@ TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node m_id = tileId; m_parentItem = parent; pvt = new TileItemNodePvt(); - m_hasError = false; for( int i = 0; i < TileConstants::TileChannelCount; i++ ) { @@ -332,7 +331,6 @@ bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString } bool b = pvt->loadImage( channel, fn, empty ); - m_hasError = !b; if( !b ) return false; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 7af553c8e..1af7833dd 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -130,7 +130,6 @@ private: TileItemNodePvt *pvt; - bool m_hasError; }; #endif // TILE_ITEM_H From 669c15eda90966c51ae11735c5fe7edfbefbc6fc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:04:30 +0200 Subject: [PATCH 232/282] Removed yet another unused variable. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_item.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 04889e61b..311b711cc 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -269,7 +269,7 @@ public: { } - bool loadImage( TileConstants::TTileChannel channel, const QString &fn, bool empty = false ) + bool loadImage( TileConstants::TTileChannel channel, const QString &fn ) { QPixmap temp; bool b = temp.load( fn ); @@ -322,15 +322,13 @@ TileItemNode::~TileItemNode() bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString filename) { QString fn = filename; - bool empty = false; if( filename.isEmpty() || ( filename == "empty" ) ) { fn = ":/placeHolder/images/empty_image.png"; - empty = true; } - bool b = pvt->loadImage( channel, fn, empty ); + bool b = pvt->loadImage( channel, fn ); if( !b ) return false; From 9bb62a3ada3719c18aca589dacb50ba4efadf8b9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:25:50 +0200 Subject: [PATCH 233/282] Statically load the empty tile image so that we don't need to have over 9000 instances of it. Also display an error message if loading fails on startup. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 14 ++++++++ .../tile_editor/tile_editor_main_window.h | 2 ++ .../src/plugins/tile_editor/tile_item.cpp | 36 ++++++++++++++----- .../src/plugins/tile_editor/tile_item.h | 1 + 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 9f4851058..90f4c7131 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -37,6 +37,8 @@ #include "land_edit_dialog.h" +#include + TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::TileEditorMainWindow) @@ -44,6 +46,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->setupUi(this); m_undoStack = new QUndoStack(this); + if( !TileItemNode::loadEmptyPixmap() ) + { + QTimer::singleShot( 0, this, SLOT( onEmptyImageLoadFailed() ) ); + } + // Retrieve the menu manager Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); @@ -341,6 +348,13 @@ void TileEditorMainWindow::onRotate( int id ) m_tileModel->setAlphaRot( id ); } +void TileEditorMainWindow::onEmptyImageLoadFailed() +{ + QMessageBox::critical( this, + tr( "Empty image load failed" ), + tr( "Couldn't load the image for empty tiles :(" ) ); +} + void TileEditorMainWindow::onActionAddTile(bool triggered) { onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 9dee6954d..d06d6deca 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -80,6 +80,8 @@ private Q_SLOTS: void onZoomFactor(int level); void onRotate(int id); + void onEmptyImageLoadFailed(); + private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 311b711cc..71fe336a2 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -271,6 +271,12 @@ public: bool loadImage( TileConstants::TTileChannel channel, const QString &fn ) { + if( fn.isEmpty() ) + { + pixmaps[ channel ] = TileItemNodePvt::emptyPm(); + return true; + } + QPixmap temp; bool b = temp.load( fn ); @@ -284,6 +290,17 @@ public: return true; } + static bool loadEmptyImage() + { + bool b = empty.load( ":/placeHolder/images/empty_image.png" ); + if( !b ) + { + empty = QPixmap(); + } + + return b; + } + void clearImage( TileConstants::TTileChannel channel ) { pixmaps[ channel ] = QPixmap(); @@ -293,10 +310,15 @@ public: return pixmaps[ channel ]; } + static QPixmap& emptyPm(){ return empty; } + private: QPixmap pixmaps[ TileConstants::TileChannelCount ]; + static QPixmap empty; + }; +QPixmap TileItemNodePvt::empty = QPixmap(); TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) @@ -321,14 +343,7 @@ TileItemNode::~TileItemNode() bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString filename) { - QString fn = filename; - - if( filename.isEmpty() || ( filename == "empty" ) ) - { - fn = ":/placeHolder/images/empty_image.png"; - } - - bool b = pvt->loadImage( channel, fn ); + bool b = pvt->loadImage( channel, filename ); if( !b ) return false; @@ -346,6 +361,11 @@ QString TileItemNode::getTileFilename(TileConstants::TTileChannel channel) return itr.value(); } +bool TileItemNode::loadEmptyPixmap() +{ + return TileItemNodePvt::loadEmptyImage(); +} + QVariant TileItemNode::data(int column, int role) const { QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 1af7833dd..5387a710d 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -117,6 +117,7 @@ public: static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } + static bool loadEmptyPixmap(); QVariant pixmap( TileConstants::TTileChannel channel ) const; From 20edb57761c9c9de84eaf3172345ec9f2a0e381a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 17:14:59 +0200 Subject: [PATCH 234/282] If I add a 256x256 tile, maybe I should remove it as 256x256, not 128x128... --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_bank.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 9a4d15469..8e4d8f511 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -329,7 +329,7 @@ bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, switch( type ) { case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; - case TileConstants::Tile256: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; } return false; From 50b90f97745de60946ef63afd250445140ab5cf5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 17:40:39 +0200 Subject: [PATCH 235/282] Update the tile list right away if the image is replaced. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 90f4c7131..4b00fb044 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -827,6 +827,8 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) QString fn = fileName.replace( '\\', '/' ); int slashIdx = fn.lastIndexOf( '/' ); m_lastTileDir = fn.left( slashIdx ); + + updateTab(); } void TileEditorMainWindow::onTileBankLoaded() From 48bd3cb38307813e0bc75733913f04eadfd885ff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 19:54:01 +0200 Subject: [PATCH 236/282] Fixed qrc path. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/georges_editor/georges_dirtree_form.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui b/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui index e14857e89..64f8cc57c 100644 --- a/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui +++ b/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui @@ -77,7 +77,7 @@ - + From 475c0201ea04b8fcf0ab887896384a024c3df153 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:10:11 +0200 Subject: [PATCH 237/282] GUI Editor Linux build fix --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/gui_editor/texture_chooser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 57a0e8d51..3f988d4f3 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -20,7 +20,7 @@ #include "nel/misc/file.h" #include #include -#include +#include #include #include From 7f6608b897425f25488e71c77fc616c703464a8d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:12:46 +0200 Subject: [PATCH 238/282] World Editor plugin Linux build fix. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/world_editor/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index ac5231aea..441ff5d02 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -60,6 +60,7 @@ TARGET_LINK_LIBRARIES( studio_plugin_world_editor qt_property_browser ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} + ${LIBXML2_LIBRARIES} ) NL_DEFAULT_PROPS(studio_plugin_world_editor "Tools: Studio Plugin: World Editor") From 033c86e92cb5b009bec080469d321bd5ea53e490 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:59:58 +0200 Subject: [PATCH 239/282] Add the property browser library to the CPack archive when generated. --HG-- branch : gsoc2014-dfighter --- code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt b/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt index f4ed13e0a..fa834dabf 100644 --- a/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt +++ b/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt @@ -96,3 +96,5 @@ ADD_DEFINITIONS(-DQT_SHARED) NL_DEFAULT_PROPS(qt_property_browser "3rdParty: Qt Property Browser 2.5") NL_ADD_RUNTIME_FLAGS(qt_property_browser) NL_ADD_LIB_SUFFIX(qt_property_browser) + +INSTALL(TARGETS qt_property_browser LIBRARY DESTINATION ${NL_LIB_PREFIX} ARCHIVE DESTINATION ${NL_LIB_PREFIX} COMPONENT libraries) From 9315b7229eda1abe0b67f8acb8d66357374188a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 10 Aug 2014 15:25:59 +0200 Subject: [PATCH 240/282] Don't enter edit mode in the treeview. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/georges_editor/georges_treeview_form.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_form.ui b/code/studio/src/plugins/georges_editor/georges_treeview_form.ui index 0bf52a3ea..42d9afcf9 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_form.ui +++ b/code/studio/src/plugins/georges_editor/georges_treeview_form.ui @@ -73,6 +73,9 @@ 0 + + QAbstractItemView::NoEditTriggers + true From 990eae1065ce48c972d1472d29359242aa50140a Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 11 Aug 2014 22:57:08 +0530 Subject: [PATCH 241/282] Adding activated plugins to the main options list --HG-- branch : Gsoc14-ryzomAppImprovements --- .../server/ryzom_ams/www/html/templates/layout_admin.tpl | 2 +- .../tools/server/ryzom_ams/www/html/templates/layout_mod.tpl | 2 +- .../tools/server/ryzom_ams/www/html/templates/layout_user.tpl | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl index db83dc8be..54307b5bc 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_admin.tpl @@ -4,13 +4,13 @@
  • Dashboard
  • Profile
  • Settings
  • + {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Users
  • Queues
  • Support Groups
  • Plugins
  • - {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Syncing
  • Logout
  • {/block} diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl index cffdfdb5a..e4fbdcc69 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_mod.tpl @@ -4,9 +4,9 @@
  • Dashboard
  • Profile
  • Settings
  • + {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Users
  • - {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if}
  • Queues
  • Support Groups
  • diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl index 57aad4c8b..e70b7c164 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/layout_user.tpl @@ -3,9 +3,9 @@
  • Profile
  • Settings
  • - -
  • Create New Ticket
  • {if isset($hook_info)} {foreach from=$hook_info key=arrkey item=element}
  • {$element.menu_display}
  • {/foreach}{/if} + +
  • Create New Ticket
  • Logout
  • {/block} From 70e8310fff9fd8ca01e72f9a087f7ffe5f1c4a71 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Tue, 12 Aug 2014 00:23:48 +0530 Subject: [PATCH 242/282] added API key mangement and Achievements plugin during installation of ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../tools/server/ryzom_ams/www/html/installer/libsetup.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index d020f1644..c93310c55 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -196,6 +196,10 @@ PRIMARY KEY (`Id`) ) ENGINE = InnoDB; + INSERT INTO `plugins` (`Id`, `FileName`, `Name`, `Type`, `Owner`, `Permission`, `Status`, `Weight`, `Info`) VALUES +(1, '../../ams_lib/plugins/API_key_management', 'API_key_management', 'automatic', '', 'admin', 1, 0, '{\"PluginName\":\"API Key Management\",\"Description\":\"Provides public access to the API''s by generating access tokens.\",\"Version\":\"1.0.0\",\"Type\":\"automatic\",\"TemplatePath\":\"..\\/..\\/..\\/ams_lib\\/plugins\\/API_key_management\\/templates\\/index.tpl\",\"\":null}'), +(2, '../../ams_lib/plugins/Achievements', 'Achievements', 'Manual', '', 'admin', 1, 0, '{\"PluginName\":\"Achievements\",\"Description\":\"Returns the achivements of a user with respect to the character =.\",\"Version\":\"1.0.0\",\"TemplatePath\":\"..\\/..\\/..\\/ams_lib\\/plugins\\/Achievements\\/templates\\/index.tpl\",\"Type\":\"Manual\",\"\":null}'); + -- ----------------------------------------------------- -- Table `" . $cfg['db']['lib']['name'] ."`.`updates` @@ -1804,4 +1808,3 @@ print_r($e); } } - From 0d8fe2b7aa92c6b4117ded01177e906d8e9386cf Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Tue, 12 Aug 2014 00:33:11 +0530 Subject: [PATCH 243/282] Achievements plugin integrated with ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/plugins/Achievements/.info | 8 + .../plugins/Achievements/Achievements.php | 142 ++++++++++++++++++ .../plugins/Achievements/templates/index.tpl | 73 +++++++++ 3 files changed, 223 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/.info create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/.info b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/.info new file mode 100644 index 000000000..238e98922 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/.info @@ -0,0 +1,8 @@ +PluginName = Achievements +Description = Returns the achivements of a user with respect to the character =. +Version = 1.0.0 +TemplatePath = ../../../ams_lib/plugins/Achievements/templates/index.tpl +Type = Manual + + + diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php new file mode 100644 index 000000000..943981680 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php @@ -0,0 +1,142 @@ + select( 'ams_api_keys', $data , 'User = :User AND UserCharacter = :UserCharacter' ); + $row = $sth -> fetchAll(); + + return $row; + + } + +/** + * Local Hook to set variables which contains + * the content to use during the plugin functionality. + */ +function hook_variable_set() + { + global $var_set; + $var_set['character'] = $_POST['Character']; + + // get db content for variable set + $row = hook_get_db_content( array( 'User' => $_SESSION['user'], 'UserCharacter' => $var_set['character'] ) ); + + // access key automatically taken from the database wrt user and character + @$var_set['app_key'] = $row['AccessToken']; + + // here you can set the host where this plugin is set + $var_set['host'] = 'localhost'; + + // here you can set what you are looking for + // when you are requesting encoded in json + @$var_set['items'] = json_encode( array( 'Task' => 'Achievements', 'Character' => $var_set['character'] ) ); + + // url where we have to make request for achievements + // it sends get parameter search(what to search) and format(in which format data exchange takes place) + $var_set['url'] = 'app.domain.org?search=' . $var_set['items'] . '&&format=json'; + + } + +/** + * Global Hook to interact with the REST api + * Pass the variables in the REST object to + * make request + * + * variables REST object expects + * url --> on which request is to be made + * appkey --> app key for authentication + * host --> host from which request have been sent + * + * @return $return_set global array returns the template data + */ +function achievements_hook_call_rest() + { + // defined the variables + global $var_set; + global $return_set; + + if ( isset( $_POST['get_data'] ) ) + { + hook_variable_set(); + + $rest_api = new Rest_Api(); + $ach_data = $rest_api -> request( $var_set['url'], $var_set['app_key'], $var_set['host'] ); + print_r( $ach_data ); + + $return_set['char_achievements'] = json_decode( $ach_data ); + } + } + +/** + * Global Hook to return global variables which contains + * the content to use in the smarty templates extracted from + * the database + * + * @return $return_set global array returns the template data + */ +function achievements_hook_get_db() + { + global $return_set; + + $db = new DBLayer( 'lib' ); + + // getting content for selecting characters + $sth = $db -> selectWithParameter( 'UserCharacter', 'ams_api_keys', array( 'User' => $_SESSION['user'] ) , 'User = :User' ); + $row = $sth -> fetchAll(); + $retur_set['Character'] = $row; + + } + +/** + * Global Hook to return global variables which contains + * the content to use in the smarty templates + * + * @return $return_set global array returns the template data + */ +function achievements_hook_return_global() + { + global $return_set; + return $return_set; + + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl new file mode 100644 index 000000000..a83acd359 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl @@ -0,0 +1,73 @@ +{block name=content} + +{if isset($smarty.get.plugin_action) and $smarty.get.plugin_action eq 'get_achievements'} +
    +
    +
    +

    Achievements

    +
    + + + +
    +
    + + {if isset($smarty.get.success) and $smarty.get.success eq '1'}

    Key added successfully

    {/if} + {if isset($smarty.get.success) and $smarty.get.success eq '2'}

    Key deleted successfully

    {/if} +
    +
    + {$hook_info.Achievements.char_achievements} +
    +
    +
    +
    +{else} +
    +
    +
    +

    Achievements

    +
    + + + +
    +
    +
    +
    +

    Select your Character

    +
    + + +
    +
    +
    +
    + + +
    +
    + +
    + +
    +
    + +
    + +
    + +
    +
    + +
    +
    +
    +
    +
    + + {/if} +{/block} From acb4f26f1a29c86c5f430f817bd24c469cebdd47 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Tue, 12 Aug 2014 00:33:58 +0530 Subject: [PATCH 244/282] API key management plugin for ams --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ams_lib/plugins/API_key_management/.info | 8 + .../API_key_management/API_key_management.php | 206 ++++++++++++++++++ .../API_key_management/generate_key.php | 53 +++++ .../API_key_management/templates/gen_key.tpl | 46 ++++ .../API_key_management/templates/index.tpl | 133 +++++++++++ 5 files changed, 446 insertions(+) create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/.info create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/generate_key.php create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/gen_key.tpl create mode 100644 code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/.info b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/.info new file mode 100644 index 000000000..b185a31db --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/.info @@ -0,0 +1,8 @@ +PluginName = API Key Management +Description = Provides public access to the API's by generating access tokens. +Version = 1.0.0 +Type = automatic +TemplatePath = ../../../ams_lib/plugins/API_key_management/templates/index.tpl + + + diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php new file mode 100644 index 000000000..1676f243a --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php @@ -0,0 +1,206 @@ + executeWithoutParams( $sql ); + } + +/** + * Hook to store data to database which is sent as post + * method from the forms in this plugin + * It also calls the local hook + */ +function api_key_management_hook_store_db() + { + global $var_set; + global $return_set; + + // if the form been submited move forward + if ( @hook_validate( $_POST['gen_key'] ) ) { + + // local hook to validate the POST variables + hook_variables(); + + // if validation successfull move forward + if ( $return_set['gen_key_validate'] == 'true' && $_GET['plugin_action'] == 'generate_key' ) + { + // this part generated the access token + include 'generate_key.php'; + $var_set['AccessToken'] = generate_key :: randomToken( 56, false, true, false ); + + // database connection + $db = new DBLayer( 'lib' ); + // insert the form data to the database + $db -> insert( 'ams_api_keys', $var_set ); + + // redirect to the the main page with success code + // 1 refers to the successfull addition of key to the database + header( "Location: index.php?page=layout_plugin&&name=API_key_management&&success=1" ); + exit; + } + } + } + +/** + * Global Hook to load the data from db and set it + * into the global array to return it to the template + */ +function api_key_management_hook_load_db() + { + global $var_set; + global $return_set; + + $db = new DBLayer( 'lib' ); + + // returns the regestered keys + $sth = $db -> select( 'ams_api_keys', array( 'user' => $_SESSION['user'] ), 'User = :user' ); + $row = $sth -> fetchAll(); + $return_set['api_keys'] = $row; + + // returns the characters with respect to the user id in the ring_tool->characters + $db = new DBLayer( 'ring' ); + $sth = $db -> selectWithParameter( 'char_name', 'characters' , array(), '1' ); + $row = $sth -> fetchAll(); + $return_set['characters'] = $row; + + } + +/** + * Global Hook to update or delete the data from db + */ +function api_key_management_hook_update_db() + { + global $var_set; + global $return_set; + + $db = new DBLayer( 'lib' ); + if ( isset( $_GET['delete_id'] ) ) + { + // removes the registered key using get variable which contains the id of the registered key + $db -> delete( 'ams_api_keys', array( 'SNo' => $_GET['delete_id'] ), 'SNo = :SNo' ); + + // redirecting to the API_key_management plugins template with success code + // 2 refers to the succssfull delete condition + header( "Location: index.php?page=layout_plugin&&name=API_key_management&&success=2" ); + exit; + } + + } + +/** + * Global Hook to return global variables which contains + * the content to use in the smarty templates + * + * @return $return_set global array returns the template data + */ +function api_key_management_hook_return_global() + { + global $return_set; + return $return_set; + + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/generate_key.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/generate_key.php new file mode 100644 index 000000000..1ddfab7ed --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/generate_key.php @@ -0,0 +1,53 @@ + 2, 2 => 8, 3 => 10, 4 => 16, 5 => 10 ); + if ( !is_array( $chars ) ) { + $chars = array_unique( str_split( $chars ) ); + } + if ( $standardChars ) { + $chars = array_merge( $chars, range( 48, 57 ), range( 65, 90 ), range( 97, 122 ) ); + } + if ( $specialChars ) { + $chars = array_merge( $chars, range( 33, 47 ), range( 58, 64 ), range( 91, 96 ), range( 123, 126 ) ); + } + array_walk( $chars, function( &$val ) { + if ( !is_int( $val ) ) { + $val = ord( $val ); } + } + ); + if ( is_int( $len ) ) { + while ( $len ) { + $tmp = ord( openssl_random_pseudo_bytes( 1 ) ); + if ( in_array( $tmp, $chars ) ) { + if ( !$output || !in_array( $output, range( 1, 5 ) ) || $output == 3 || $output == 5 ) { + $out .= ( $output == 3 ) ? $tmp : chr( $tmp ); + } + else { + $based = base_convert( $tmp, 10, $outputMap[$output] ); + $out .= ( ( ( $output == 1 ) ? '00' : ( ( $output == 4 ) ? '0x' : '' ) ) . ( ( $output == 2 ) ? sprintf( '%03d', $based ) : $based ) ); + } + $len--; + } + } + } + return ( empty( $out ) ) ? false : $out; + } + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/gen_key.tpl b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/gen_key.tpl new file mode 100644 index 000000000..1ab283449 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/gen_key.tpl @@ -0,0 +1,46 @@ +
    +
    +
    +

    API KEY management

    +
    + + + +
    +
    +
    +
    +

    Generate Access Key

    +
    + + +
    +
    +
    +
    +
    + Generate Key + +
    + +
    +
    + + +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    + + diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl new file mode 100644 index 000000000..eac902aae --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl @@ -0,0 +1,133 @@ +{block name=content} + +{if isset($smarty.get.plugin_action) and $smarty.get.plugin_action eq 'generate_key'} +
    +
    +
    +

    API KEY management

    +
    + + + +
    +
    +
    +
    +

    Generate Access Key

    +
    + + +
    +
    +
    +
    +
    + Generate Key + +
    + +
    +
    + + +
    +
    +
    + +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    + +
    +
    + + +
    +
    +
    + +
    + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +{else} +
    +
    +
    +

    API KEY management

    +
    + + + +
    +
    + + + {if isset($hook_info.API_key_management['gen_key_validate']) and $hook_info.API_key_management['gen_key_validate'] eq 'false' }

    Please enter all the fields

    {/if} + {if isset($smarty.get.success) and $smarty.get.success eq '1'}

    Key added successfully

    {/if} + {if isset($smarty.get.success) and $smarty.get.success eq '2'}

    Key deleted successfully

    {/if} +
    + +
    +
    +
    +

    All the keys you have generated will be shown and you can customize from here.

    + + + + + + + + + + + + + + {foreach from=$hook_info.API_key_management.api_keys item=element} + + + + + + + + {/foreach} + + + +
    NameTypeCharacterAccess KeyExpiresActions
    {$element.FrName}{$element.UserType}{$element.UserCharacter}{$element.AccessToken}{$element.ExpiryDate} +
    +
    +
    +
    +
    + {/if} +{/block} From 0e4b004978aa32504a7a88c15b5ded556b36adb2 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Tue, 12 Aug 2014 12:46:22 +0530 Subject: [PATCH 245/282] Bug Fix: delete plugin option available for inactive plugins --HG-- branch : Gsoc14-ryzomAppImprovements --- .../tools/server/ryzom_ams/www/html/templates/plugins.tpl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl index 73f88d1a2..6d864c818 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl +++ b/code/ryzom/tools/server/ryzom_ams/www/html/templates/plugins.tpl @@ -45,8 +45,10 @@ {$element.plugin_info->Description} {$element.plugin_type} {$element.plugin_permission} - - {if ($element.plugin_status) eq "0"}{/if} + + {if ($element.plugin_status) eq "0"} + + {/if} {if ($element.plugin_status) eq "1"}{/if} {/foreach} From a43c2f0a5ee60aff752faf2dc95995ef000bf77d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 19:26:55 +0200 Subject: [PATCH 246/282] First iteration of the property browser. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/georges_editor/CMakeLists.txt | 3 +- .../plugins/georges_editor/browser_ctrl.cpp | 89 +++++++++++++++++++ .../src/plugins/georges_editor/browser_ctrl.h | 33 +++++++ .../georges_treeview_dialog.cpp | 8 ++ .../georges_editor/georges_treeview_dialog.h | 4 + .../georges_editor/georgesform_model.cpp | 2 +- 6 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl.cpp create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl.h diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index bab12b7e1..679af334e 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -15,7 +15,8 @@ SET(OVQT_PLUG_GEORGES_EDITOR_HDR georges_editor_plugin.h georges_dirtree_dialog.h georges_filesystem_model.h georges_treeview_dialog.h - expandable_headerview.h) + expandable_headerview.h + browser_ctrl.h) SET(OVQT_PLUG_GEORGES_EDITOR_UIS georges_editor_form.ui georges_dirtree_form.ui diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp new file mode 100644 index 000000000..1e9ed2606 --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -0,0 +1,89 @@ +#include "browser_ctrl.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +#include "nel/georges/form.h" + +#include "formitem.h" + +class BrowserCtrlPvt +{ +public: + BrowserCtrlPvt() + { + mgr = new QtVariantPropertyManager(); + factory = new QtVariantEditorFactory(); + } + + ~BrowserCtrlPvt() + { + delete mgr; + mgr = NULL; + delete factory; + factory = NULL; + } + + QtVariantPropertyManager *mgr; + QtVariantEditorFactory *factory; + QtTreePropertyBrowser *m_browser; +}; + +BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : +QObject( browser ) +{ + m_pvt = new BrowserCtrlPvt(); + m_pvt->m_browser = browser; +} + +BrowserCtrl::~BrowserCtrl() +{ + delete m_pvt; + m_pvt = NULL; +} + +void BrowserCtrl::clicked( const QModelIndex &idx ) +{ + m_pvt->m_browser->clear(); + + GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); + NLGEORGES::UFormElm &root = m_form->getRootNode(); + NLGEORGES::UFormElm *node = NULL; + bool b = false; + + b = m_form->getRootNode().getNodeByName( &node, item->formName().c_str() ); + + if( !b || ( node == NULL ) ) + return; + + if( !node->isStruct() ) + return; + + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + for( int i = 0; i < st->Elements.size(); i++ ) + { + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + + QString key = elm.Name.c_str(); + QString value = ""; + + if( elm.Element != NULL ) + { + const NLGEORGES::UType *typ = elm.Element->getType(); + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); + std::string v; + atom->getValue( v, NLGEORGES::UFormElm::NoEval ); + value = v.c_str(); + } + + QtVariantProperty *p = m_pvt->mgr->addProperty( QVariant::String, key ); + p->setValue( value ); + m_pvt->m_browser->addProperty( p ); + } + +} + diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h new file mode 100644 index 000000000..52655c141 --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -0,0 +1,33 @@ +#ifndef BROWSER_CTRL_H +#define BROWSER_CTRL_H + +#include + +namespace NLGEORGES +{ + class UForm; +} + +class QtTreePropertyBrowser; +class QModelIndex; + +class BrowserCtrlPvt; + +class BrowserCtrl : public QObject +{ + Q_OBJECT +public: + BrowserCtrl( QtTreePropertyBrowser *browser ); + ~BrowserCtrl(); + void setForm( NLGEORGES::UForm *form ){ m_form = form; } + +public Q_SLOTS: + void clicked( const QModelIndex &idx ); + +private: + BrowserCtrlPvt *m_pvt; + + NLGEORGES::UForm *m_form; +}; + +#endif diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp index f1819f52a..a8e7e7451 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -43,6 +43,7 @@ #include "formitem.h" #include "formdelegate.h" #include "expandable_headerview.h" +#include "browser_ctrl.h" using namespace NLMISC; using namespace NLGEORGES; @@ -76,16 +77,22 @@ namespace GeorgesQt m_ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); + m_browserCtrl = new BrowserCtrl( m_ui.propertiesBrowser ); + connect(m_ui.treeView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); connect(m_ui.treeView, SIGNAL(doubleClicked (QModelIndex)), this, SLOT(doubleClicked (QModelIndex))); + connect(m_ui.treeView, SIGNAL(clicked(const QModelIndex&)), + m_browserCtrl, SLOT(clicked(const QModelIndex&))); connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); } CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog() { + m_browserCtrl = NULL; + delete m_form; qDebug() << "DTOR"; } @@ -104,6 +111,7 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::setForm(const CForm *form) { m_form = (UForm*)form; + m_browserCtrl->setForm( (UForm*)form ); } NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByName(const QString formName) diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h index 6f7b57acc..b2171cf03 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h @@ -32,6 +32,8 @@ // Project includes +class BrowserCtrl; + namespace NLGEORGES { class UForm; @@ -113,6 +115,8 @@ namespace GeorgesQt bool m_modified; + BrowserCtrl *m_browserCtrl; + }; /* CGeorgesTreeViewDialog */ } /* namespace GeorgesQt */ diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_model.cpp index 387bc8917..2cc5c1280 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/studio/src/plugins/georges_editor/georgesform_model.cpp @@ -307,7 +307,7 @@ namespace GeorgesQt // Is a struct ? if ( (entry.getType () == NLGEORGES::UFormDfn::EntryDfn) || (entry.getType () == NLGEORGES::UFormDfn::EntryVirtualDfn) ) - { + { // Is an array of struct ? if (entry.getArrayFlag ()) { From 1b7b081c60a13ff22c22858b8eea95060c590564 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 20:17:10 +0200 Subject: [PATCH 247/282] Shown properties can now be edited. --HG-- branch : gsoc2014-dfighter --- .../plugins/georges_editor/browser_ctrl.cpp | 93 +++++++++++++------ 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 1e9ed2606..b82c7733c 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -7,6 +7,26 @@ #include "formitem.h" +QVariant::Type getValueType( const NLGEORGES::UType *typ ) +{ + QVariant::Type t = QVariant::String; + + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + switch( ttyp ) + { + case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; + case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; + case NLGEORGES::UType::Double: t = QVariant::Double; break; + case NLGEORGES::UType::Color: t = QVariant::Color; break; + case NLGEORGES::UType::String: t = QVariant::String; break; + } + + return t; +} + class BrowserCtrlPvt { public: @@ -22,8 +42,52 @@ public: mgr = NULL; delete factory; factory = NULL; + m_browser = NULL; + } + + void setupElement( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) + { + QString key = elm.Name.c_str(); + QString value = ""; + QVariant::Type t = QVariant::String; + + if( elm.Element != NULL ) + { + t = getValueType( elm.Element->getType() ); + + NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); + std::string v; + atom->getValue( v, NLGEORGES::UFormElm::NoEval ); + value = v.c_str(); + } + + QtVariantProperty *p = mgr->addProperty( t, key ); + p->setValue( value ); + m_browser->addProperty( p ); } + void setupForm( NLGEORGES::CFormElmStruct *st ) + { + for( int i = 0; i < st->Elements.size(); i++ ) + { + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + setupElement( elm ); + } + + m_browser->setFactoryForManager( mgr, factory ); + } + + void clear() + { + m_browser->clear(); + } + + void setBrowser( QtTreePropertyBrowser *browser ) + { + m_browser = browser; + } + +private: QtVariantPropertyManager *mgr; QtVariantEditorFactory *factory; QtTreePropertyBrowser *m_browser; @@ -33,7 +97,7 @@ BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : QObject( browser ) { m_pvt = new BrowserCtrlPvt(); - m_pvt->m_browser = browser; + m_pvt->setBrowser( browser ); } BrowserCtrl::~BrowserCtrl() @@ -44,7 +108,7 @@ BrowserCtrl::~BrowserCtrl() void BrowserCtrl::clicked( const QModelIndex &idx ) { - m_pvt->m_browser->clear(); + m_pvt->clear(); GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); NLGEORGES::UFormElm &root = m_form->getRootNode(); @@ -60,30 +124,7 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) return; NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - for( int i = 0; i < st->Elements.size(); i++ ) - { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - - QString key = elm.Name.c_str(); - QString value = ""; - - if( elm.Element != NULL ) - { - const NLGEORGES::UType *typ = elm.Element->getType(); - NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; - if( typ != NULL ) - ttyp = typ->getType(); - - NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); - std::string v; - atom->getValue( v, NLGEORGES::UFormElm::NoEval ); - value = v.c_str(); - } - - QtVariantProperty *p = m_pvt->mgr->addProperty( QVariant::String, key ); - p->setValue( value ); - m_pvt->m_browser->addProperty( p ); - } + m_pvt->setupForm( st ); } From aa95cc3c4ba056b3f0b1b7f542f44ea9eb43ec40 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 21:00:33 +0200 Subject: [PATCH 248/282] Apply changes. --HG-- branch : gsoc2014-dfighter --- .../plugins/georges_editor/browser_ctrl.cpp | 42 +++++++++++++++++++ .../src/plugins/georges_editor/browser_ctrl.h | 10 ++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index b82c7733c..207c665a9 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -34,6 +34,7 @@ public: { mgr = new QtVariantPropertyManager(); factory = new QtVariantEditorFactory(); + m_currentNode = NULL; } ~BrowserCtrlPvt() @@ -74,12 +75,14 @@ public: setupElement( elm ); } + m_currentNode = st; m_browser->setFactoryForManager( mgr, factory ); } void clear() { m_browser->clear(); + m_currentNode = NULL; } void setBrowser( QtTreePropertyBrowser *browser ) @@ -87,10 +90,25 @@ public: m_browser = browser; } + void onValueChanged( QtProperty *p, const QVariant &value ) + { + if( m_currentNode == NULL ) + return; + + std::string k = p->propertyName().toUtf8().constData(); + std::string v = value.toString().toUtf8().constData(); + + m_currentNode->setValueByName( v.c_str(), k.c_str() ); + } + + QtVariantPropertyManager* manager() const{ return mgr; } + private: QtVariantPropertyManager *mgr; QtVariantEditorFactory *factory; QtTreePropertyBrowser *m_browser; + + NLGEORGES::UFormElm *m_currentNode; }; BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : @@ -108,6 +126,7 @@ BrowserCtrl::~BrowserCtrl() void BrowserCtrl::clicked( const QModelIndex &idx ) { + disableMgrConnections(); m_pvt->clear(); GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); @@ -126,5 +145,28 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); m_pvt->setupForm( st ); + enableMgrConnections(); + +} + +void BrowserCtrl::onValueChanged( QtProperty *p, const QVariant &value ) +{ + m_pvt->onValueChanged( p, value ); +} + +void BrowserCtrl::enableMgrConnections() +{ + QtVariantPropertyManager *mgr = m_pvt->manager(); + + connect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), + this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); +} + +void BrowserCtrl::disableMgrConnections() +{ + QtVariantPropertyManager *mgr = m_pvt->manager(); + + disconnect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), + this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); } diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h index 52655c141..da14e14c9 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -10,6 +10,8 @@ namespace NLGEORGES class QtTreePropertyBrowser; class QModelIndex; +class QVariant; +class QtProperty; class BrowserCtrlPvt; @@ -24,9 +26,15 @@ public: public Q_SLOTS: void clicked( const QModelIndex &idx ); +private Q_SLOTS: + void onValueChanged( QtProperty *p, const QVariant &value ); + private: - BrowserCtrlPvt *m_pvt; + void enableMgrConnections(); + void disableMgrConnections(); + + BrowserCtrlPvt *m_pvt; NLGEORGES::UForm *m_form; }; From ac980adcc70cede5f806df693ae502d8b495e052 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Wed, 13 Aug 2014 12:57:30 +0530 Subject: [PATCH 249/282] Added few more options in REST api --HG-- branch : Gsoc14-ryzomAppImprovements --- .../ryzom_ams/ams_lib/autoload/rest_api.php | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php index 8dba944b5..91607292c 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php @@ -43,10 +43,27 @@ class Rest_Api { // Execute cURL on the session handle $response = curl_exec( $session ); - return $response; + if ( curl_errno( $session ) ) { + // if request is not sent + die( 'Couldn\'t send request: ' . curl_error( $session ) ); + } else { + // check the HTTP status code of the request + $resultStatus = curl_getinfo( $session, CURLINFO_HTTP_CODE ); + if ( $resultStatus == 200 ) { + // everything went fine return response + return $response; + + } else { + // the request did not complete as expected. common errors are 4xx + // (not found, bad request, etc.) and 5xx (usually concerning + // errors/exceptions in the remote script execution) + die( 'Request failed: HTTP status code: ' . $resultStatus ); + } + } + curl_close( $session ); } else { return null; } } - } + } From 5fd2615f0e07ee2d205dcb968752d6dffa873ef2 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Wed, 13 Aug 2014 18:32:13 +0530 Subject: [PATCH 250/282] small bug fix: support group missing brackets at end --HG-- branch : Gsoc14-ryzomAppImprovements --- .../server/ryzom_ams/ams_lib/autoload/support_group.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php index 7b8a864d4..d482a842f 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php @@ -305,7 +305,7 @@ class Support_Group{ */ public function create() { $dbl = new DBLayer("lib"); - $dbl->insert("support_group", Array('Name' => $this->getName(), 'Tag' => $this->getTag(), 'GroupEmail' => $this->getGroupEmail(), 'IMAP_MailServer' => $this->getIMAP_MailServer(), 'IMAP_Username' => $this->getIMAP_Username(), 'IMAP_Password' => $this->getIMAP_Password()); + $dbl->insert("support_group", Array('Name' => $this->getName(), 'Tag' => $this->getTag(), 'GroupEmail' => $this->getGroupEmail(), 'IMAP_MailServer' => $this->getIMAP_MailServer(), 'IMAP_Username' => $this->getIMAP_Username(), 'IMAP_Password' => $this->getIMAP_Password())); } @@ -327,7 +327,7 @@ class Support_Group{ */ public function update(){ $dbl = new DBLayer("lib"); - $dbl->update("`support_group`", Array('Name' => $this->getName(), 'Tag' => $this->getTag(), 'GroupEmail' => $this->getGroupEmail(), 'IMAP_MailServer' => $this->getIMAP_MailServer(), 'IMAP_Username' => $this->getIMAP_Username(), 'IMAP_password' => $this->getIMAP_Password(), "`SGroupId` = $this->getSGroupId()"); + $dbl->update("`support_group`", Array('Name' => $this->getName(), 'Tag' => $this->getTag(), 'GroupEmail' => $this->getGroupEmail(), 'IMAP_MailServer' => $this->getIMAP_MailServer(), 'IMAP_Username' => $this->getIMAP_Username(), 'IMAP_password' => $this->getIMAP_Password(), "`SGroupId` = $this->getSGroupId()")); } @@ -337,7 +337,7 @@ class Support_Group{ */ public function delete(){ $dbl = new DBLayer("lib"); - $dbl->delete("`support_group`", Array('id' => $this->getSGroupId(), "`SGroupId` = :id"); + $dbl->delete("`support_group`", Array('id' => $this->getSGroupId(), "`SGroupId` = :id")); } ////////////////////////////////////////////Getters//////////////////////////////////////////////////// From f8a92326edc0b3a4c885523c8c2929db367a0511 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Thu, 14 Aug 2014 22:20:05 +0530 Subject: [PATCH 251/282] BugFixes: achievements and API key management plugins --HG-- branch : Gsoc14-ryzomAppImprovements --- .../API_key_management/API_key_management.php | 47 +++--- .../API_key_management/templates/index.tpl | 2 +- .../plugins/Achievements/Achievements.php | 146 ++++++++++++------ .../plugins/Achievements/templates/index.tpl | 8 +- .../ryzom_ams/www/html/installer/libsetup.php | 2 +- 5 files changed, 134 insertions(+), 71 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php index 1676f243a..27613e18b 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/API_key_management.php @@ -11,11 +11,13 @@ * @author shubham meena mentored by Matthew Lagoe */ - -// Global variables to store the data +// Global variable to store the data which is +// returned to the templates $return_set = array(); -$var_set = array(); +// Local variable to store data during +// functionalities of the hooks +$var_set = array(); /** * Display hook for api key management @@ -28,7 +30,7 @@ function api_key_management_hook_display() } /** - * Hook to validate the posted data + * Local Hook to validate the posted data */ function hook_validate( $var ) { @@ -70,9 +72,9 @@ function hook_variables() /** * Global Hook to create table of the API_key_management - * if not created.Contains the sql code + * if not created. + * Contains the sql code */ - function api_key_management_hook_create_tb() { $dbl = new DBLayer( "lib" ); @@ -157,18 +159,25 @@ function api_key_management_hook_load_db() $db = new DBLayer( 'lib' ); - // returns the regestered keys - $sth = $db -> select( 'ams_api_keys', array( 'user' => $_SESSION['user'] ), 'User = :user' ); - $row = $sth -> fetchAll(); - $return_set['api_keys'] = $row; - - // returns the characters with respect to the user id in the ring_tool->characters - $db = new DBLayer( 'ring' ); - $sth = $db -> selectWithParameter( 'char_name', 'characters' , array(), '1' ); - $row = $sth -> fetchAll(); - $return_set['characters'] = $row; - - } + if ( isset( $_SESSION['user'] ) ) + { + // returns the registered keys + $sth = $db -> select( 'ams_api_keys', array( 'user' => $_SESSION['user'] ), 'User = :user' ); + $row = $sth -> fetchAll(); + $return_set['api_keys'] = $row; + + // fetch the character from the array to compare + $com = array_column( $return_set['api_keys'], 'UserCharacter' ); + + // returns the characters with respect to the user id in the ring_tool->characters + $db = new DBLayer( 'ring' ); + $sth = $db -> selectWithParameter( 'char_name', 'characters' , array(), '1' ); + $row = $sth -> fetch(); + + // loop through the character list and remove the character if already have an api key + $return_set['characters'] = array_diff( $row, $com ); + } + } /** * Global Hook to update or delete the data from db @@ -189,7 +198,6 @@ function api_key_management_hook_update_db() header( "Location: index.php?page=layout_plugin&&name=API_key_management&&success=2" ); exit; } - } /** @@ -202,5 +210,4 @@ function api_key_management_hook_return_global() { global $return_set; return $return_set; - } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl index eac902aae..1f6fea336 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/API_key_management/templates/index.tpl @@ -48,7 +48,7 @@
    diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php index 943981680..79c117893 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/Achievements.php @@ -15,10 +15,13 @@ */ -// Global variables to store the data +// Global variable to store the data which is +// returned to the templates $return_set = array(); -$var_set = array(); +// Local variable to store data during +// functionalities of the hooks +$var_set = array(); /** * Display hook for Achievements plugin @@ -28,26 +31,64 @@ function achievements_hook_display() global $return_set; // to display plugin name in menu bar $return_set['menu_display'] = 'Achievements'; - } + } /** * Local Hook to get database content * which is called by the global hook * by passing a parameter * + * This hook returns the api keys registerd with + * the logged in user + * * @param $data array with respective information * @return $row extracted db content wrt $data */ function hook_get_db_content( $data ) { - $db = new DBLayer( 'lib' ); - $sth = $db -> select( 'ams_api_keys', $data , 'User = :User AND UserCharacter = :UserCharacter' ); $row = $sth -> fetchAll(); - return $row; - + } + +/** + * Local Hook to get database content + * which is called by the global hook + * by passing a parameter + * + * This hook returns the id of the character + * whose achivements we have to get + * + * @param $data array with respective information + * @return $row extracted db content wrt $data + */ +function hook_get_char_id( $data ) + { + // returns the character id with respect to the character name in the ring_tool->characters + $db = new DBLayer( 'ring' ); + $sth = $db -> selectWithParameter( 'char_id', 'characters' , array( 'char_name' => $data ), 'char_name=:char_name' ); + $row = $sth -> fetch(); + return $row['char_id']; + } + +/** + * Local Hook to get database content + * which is called by the global hook + * by passing a parameter + * + * Hook to get the player stats of the character + * + * @param $data array with respective information + * @return $row extracted db content wrt $data + */ +function hook_get_player_stat( $data ) + { + // returns the character id with respect to the character name in the ring_tool->characters + $db = new DBLayer( 'webig' ); + $sth = $db -> select( 'players' , array( 'name' => $data ), 'name=:name' ); + $row = $sth -> fetch(); + return $row; } /** @@ -56,27 +97,44 @@ function hook_get_db_content( $data ) */ function hook_variable_set() { - global $var_set; - $var_set['character'] = $_POST['Character']; - - // get db content for variable set - $row = hook_get_db_content( array( 'User' => $_SESSION['user'], 'UserCharacter' => $var_set['character'] ) ); - - // access key automatically taken from the database wrt user and character - @$var_set['app_key'] = $row['AccessToken']; - - // here you can set the host where this plugin is set - $var_set['host'] = 'localhost'; - - // here you can set what you are looking for - // when you are requesting encoded in json - @$var_set['items'] = json_encode( array( 'Task' => 'Achievements', 'Character' => $var_set['character'] ) ); - - // url where we have to make request for achievements - // it sends get parameter search(what to search) and format(in which format data exchange takes place) - $var_set['url'] = 'app.domain.org?search=' . $var_set['items'] . '&&format=json'; - - } + global $return_set; + global $var_set; + if ( isset( $_POST['Character'] ) && !empty( $_POST['Character'] ) ) + { + $var_set['character'] = $_POST['Character']; + + // get char id from ring_open table + if ( $var_set['character'] != 'All Characters' ) + { + $var_set['char_id'] = hook_get_char_id( $var_set['character'] ); + + } + + // get db content for variable set + $row = hook_get_db_content( array( 'User' => $_SESSION['user'], 'UserCharacter' => $var_set['character'] ) ); + + // access key automatically taken from the database wrt user and character + @$var_set['app_key'] = $row['AccessToken']; + + // here you can set the host where this plugin is set + $var_set['host'] = 'localhost'; + + // here we get the stats of the character + $ref_set = hook_get_player_stat( $var_set['character'] ); + + // here we have set items that are required to get the achivements + // these are player stats from webig->players table + @$var_set['items'] = json_encode( array( 'dev_shard' => $ref_set['dev_shard'] , 'name' => $ref_set['name'] , 'cid' => $ref_set['cid'] , 'lang' => 'en' , 'translater_mode' => '', 'last_played_date' => $ref_set['last_login'] ) ); + + // url where we have to make request for achievements + // it sends get parameter search(what to search) and format(in which format data exchange takes place) + $var_set['url'] = 'http://localhost6/?search=achievements&&format=json'; + } + else + { + $return_set['no_char'] = "Please Generate key for a character before requesting for achievements"; + } + } /** * Global Hook to interact with the REST api @@ -99,12 +157,11 @@ function achievements_hook_call_rest() if ( isset( $_POST['get_data'] ) ) { hook_variable_set(); - - $rest_api = new Rest_Api(); - $ach_data = $rest_api -> request( $var_set['url'], $var_set['app_key'], $var_set['host'] ); - print_r( $ach_data ); - - $return_set['char_achievements'] = json_decode( $ach_data ); + // here we make the REST connection + $rest_api = new Rest_Api(); + $ach_data = $rest_api -> request( $var_set['url'], $var_set['app_key'], $var_set['host'], $var_set['items'] ); + // here we store the response we get from the server + $return_set['char_achievements'] = $ach_data ; } } @@ -119,14 +176,16 @@ function achievements_hook_get_db() { global $return_set; - $db = new DBLayer( 'lib' ); - - // getting content for selecting characters - $sth = $db -> selectWithParameter( 'UserCharacter', 'ams_api_keys', array( 'User' => $_SESSION['user'] ) , 'User = :User' ); - $row = $sth -> fetchAll(); - $retur_set['Character'] = $row; - - } + if ( isset( $_SESSION['user'] ) ) + { + $db = new DBLayer( 'lib' ); + + // getting content for selecting characters + $sth = $db -> selectWithParameter( 'UserCharacter', 'ams_api_keys', array( 'User' => $_SESSION['user'] ) , 'User = :User' ); + $row = $sth -> fetch(); + $return_set['Character'] = $row; + } + } /** * Global Hook to return global variables which contains @@ -138,5 +197,4 @@ function achievements_hook_return_global() { global $return_set; return $return_set; - - } + } diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl index a83acd359..e33ac3590 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/plugins/Achievements/templates/index.tpl @@ -11,10 +11,8 @@
    - - {if isset($smarty.get.success) and $smarty.get.success eq '1'}

    Key added successfully

    {/if} - {if isset($smarty.get.success) and $smarty.get.success eq '2'}

    Key deleted successfully

    {/if}
    + {if isset($hook_info.Achievements.no_char)}

    {$hook_info.Achievements.no_char}

    {/if}
    {$hook_info.Achievements.char_achievements}
    @@ -49,8 +47,8 @@
    diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index c93310c55..6fb5981d3 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -198,7 +198,7 @@ INSERT INTO `plugins` (`Id`, `FileName`, `Name`, `Type`, `Owner`, `Permission`, `Status`, `Weight`, `Info`) VALUES (1, '../../ams_lib/plugins/API_key_management', 'API_key_management', 'automatic', '', 'admin', 1, 0, '{\"PluginName\":\"API Key Management\",\"Description\":\"Provides public access to the API''s by generating access tokens.\",\"Version\":\"1.0.0\",\"Type\":\"automatic\",\"TemplatePath\":\"..\\/..\\/..\\/ams_lib\\/plugins\\/API_key_management\\/templates\\/index.tpl\",\"\":null}'), -(2, '../../ams_lib/plugins/Achievements', 'Achievements', 'Manual', '', 'admin', 1, 0, '{\"PluginName\":\"Achievements\",\"Description\":\"Returns the achivements of a user with respect to the character =.\",\"Version\":\"1.0.0\",\"TemplatePath\":\"..\\/..\\/..\\/ams_lib\\/plugins\\/Achievements\\/templates\\/index.tpl\",\"Type\":\"Manual\",\"\":null}'); +(2, '../../ams_lib/plugins/Achievements', 'Achievements', 'Manual', '', 'admin', 0, 0, '{\"PluginName\":\"Achievements\",\"Description\":\"Returns the achivements of a user with respect to the character =.\",\"Version\":\"1.0.0\",\"TemplatePath\":\"..\\/..\\/..\\/ams_lib\\/plugins\\/Achievements\\/templates\\/index.tpl\",\"Type\":\"Manual\",\"\":null}'); -- ----------------------------------------------------- From 750ded21bd66ed56e6baabe3f8cd88d5936732b9 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Thu, 14 Aug 2014 22:25:16 +0530 Subject: [PATCH 252/282] added option for posting data in REST api --HG-- branch : Gsoc14-ryzomAppImprovements --- .../server/ryzom_ams/ams_lib/autoload/rest_api.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php index 91607292c..74281c6f6 100644 --- a/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php +++ b/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/rest_api.php @@ -20,7 +20,7 @@ class Rest_Api { * @param $host host for the website * @return URL response. */ - public function request( $url , $applicationKey, $host ) + public function request( $url , $applicationKey, $host , $data ) { // Check the referer is the host website $referer = $_SERVER['HTTP_REFERER']; @@ -36,10 +36,13 @@ class Rest_Api { // Set the HTTP request authentication headers $headers = array( 'AppKey: ' . $applicationKey, - 'Timestamp: ' . date( 'Ymd H:i:s', time() ) + 'Timestamp: ' . date( 'Ymd H:i:s', time() ), + 'Accept: application/json', + 'Content-Type: application/json' ); curl_setopt( $session, CURLOPT_HTTPHEADER, $headers ); - + curl_setopt( $session, CURLOPT_CUSTOMREQUEST, "POST" ); + curl_setopt( $session, CURLOPT_POSTFIELDS, $data ); // Execute cURL on the session handle $response = curl_exec( $session ); @@ -66,4 +69,4 @@ class Rest_Api { return null; } } - } + } From a01e331639f7b5bde20ccaa61b2e7d274bd1ee37 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Fri, 15 Aug 2014 00:13:00 +0530 Subject: [PATCH 253/282] bug fix in plugin installation --HG-- branch : Gsoc14-ryzomAppImprovements --- .../tools/server/ryzom_ams/www/html/func/install_plugin.php | 6 +++--- .../tools/server/ryzom_ams/www/html/installer/libsetup.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php index 1ea950d38..052d4f14b 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/func/install_plugin.php @@ -220,7 +220,7 @@ function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) // check for the version for the plugin $db = new DBLayer( "lib" ); - $sth = $db -> select( "plugins", array( ':name' => $result['PluginName'] ), "Name = :name" ); + $sth = $db -> select( "plugins", array( 'Name' => $result['PluginName'] ), "Name = :Name" ); $info = $sth -> fetch(); $info['Info'] = json_decode( $info['Info'] ); @@ -237,11 +237,11 @@ function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) // then there MUST be an increment in the Y value. // When there is increment in the X value , Y and Z MUST be 0. // comparing if there is some change - if ( !array_intersect( $new_version , $pre_version ) ) + if ( !array_diff( $new_version , $pre_version ) ) { // removing the uploaded file Plugincache :: rrmdir( $tempPath . "/test/" . $fileName ); - return '2'; + return '2'; //plugin already exists } else { diff --git a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php index 6fb5981d3..77a5269f7 100644 --- a/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php +++ b/code/ryzom/tools/server/ryzom_ams/www/html/installer/libsetup.php @@ -186,7 +186,7 @@ CREATE TABLE IF NOT EXISTS `" . $cfg['db']['lib']['name'] ."`.`plugins` ( `Id` INT(10) NOT NULL AUTO_INCREMENT, `FileName` VARCHAR(255) NOT NULL, - `Name` VARCHAR(11) NOT NULL, + `Name` VARCHAR(56) NOT NULL, `Type` VARCHAR(12) NOT NULL, `Owner` VARCHAR(25) NOT NULL, `Permission` VARCHAR(5) NOT NULL, From ee6db8ef7f67fb9935f9554953d428e3ba72ee0a Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Fri, 15 Aug 2014 00:24:31 +0530 Subject: [PATCH 254/282] code modified to accept request through Rest and sending achievments in response --HG-- branch : Gsoc14-ryzomAppImprovements --- code/web/app/app_achievements/index.php | 230 ++++++++++++++---------- 1 file changed, 139 insertions(+), 91 deletions(-) diff --git a/code/web/app/app_achievements/index.php b/code/web/app/app_achievements/index.php index 90ce612bb..9db5b991f 100644 --- a/code/web/app/app_achievements/index.php +++ b/code/web/app/app_achievements/index.php @@ -1,110 +1,158 @@ isIG()) { - require_once("include/ach_render_ig.php"); -} -else { - require_once("include/ach_render_web.php"); -} -require_once("include/ach_render_common.php"); - -require_once("class/DLL_class.php"); -#require_once("class/InDev_trait.php"); -require_once("class/Node_abstract.php"); -require_once("class/AVLTree_class.php"); -require_once("class/Parentum_abstract.php"); -require_once("class/AchList_abstract.php"); -require_once("class/Tieable_inter.php"); -require_once("class/NodeIterator_class.php"); - - -require_once("class/AchMenu_class.php"); -require_once("class/AchMenuNode_class.php"); -require_once("class/AchSummary_class.php"); -require_once("class/AchCategory_class.php"); -require_once("class/AchAchievement_class.php"); -require_once("class/AchTask_class.php"); -require_once("class/AchObjective_class.php"); - -#require_once("fb/facebook.php"); // Update user acces on Db -#$DBc = ryDB::getInstance(APP_NAME."_test"); -$DBc = ryDB::getInstance(APP_NAME); +// $DBc = ryDB::getInstance(APP_NAME."_test"); +$DBc = ryDB :: getInstance( APP_NAME ); + + +// if getting request using REST +if ( isset( $_GET['search'] ) && isset( $_GET['format'] ) ) + { + // if the format is json + if ( $_GET['format'] == 'json' ) + { + // getting the headers when the request is sent + $header = getallheaders(); + + // this block is to get the posted data + $fp = fopen( 'php://input', 'r' ); + $rawData = stream_get_contents( $fp ); + $userd = json_decode( $rawData, true ); + + // authenticate the user using data we get from server + appAuthenticateRest( $user, $userd ); + + // create a ryzom user object whose achievements we have to send in response + $_USER = new RyzomUser( $user ); + + require_once( "include/ach_render_web.php" ); + $c .= ach_render(); + $response = $c; + // sending the response + echo( $response ); + exit; + + } + } +else + { + echo 'Invalid response'; + exit; + } + + + + +// Ask to authenticate user (using ingame or session method) and fill $user with all information +ryzom_app_authenticate( $user, true ); + + +// echo var_export($user,true); +// $user['id'] = $user['char_id']; +// $user['name'] = $user['char_name']; +/** + * $user = array(); + * $user['cid'] = 1; + * $user['lang'] = 'en'; + * $user['name'] = 'Talvela'; + * $user['race'] = "r_matis"; + * $user['civilization'] = "c_neutral"; + * $user['cult'] = "c_neutral"; + * $user['ig'] = ($_REQUEST['ig']==1); + * #$user['ig'] = true; + */ + +$_USER = new RyzomUser( $user ); + + +if ( $_USER -> isIG() ) { + require_once( "include/ach_render_ig.php" ); + } +else { + require_once( "include/ach_render_web.php" ); + } + +// require_once("fb/facebook.php"); $c = ""; -if(!$_USER->isIG()) { - /*$facebook = new Facebook(array( - 'appId' => $_CONF['fb_id'], - 'secret' => $_CONF['fb_secret'], - 'cookie' => true - )); - - #code taken from facebook tutorial - - // Get the url to redirect for login to facebook - // and request permission to write on the user's wall. - $login_url = $facebook->getLoginUrl( - array('scope' => 'publish_stream') - ); - - // If not authenticated, redirect to the facebook login dialog. - // The $login_url will take care of redirecting back to us - // after successful login. - if (! $facebook->getUser()) { - $c .= ';'; - } - else { - $DBc->sqlQuery("INSERT INTO ach_fb_token (aft_player,aft_token,aft_date,aft_allow) VALUES ('".$_USER->getID()."','".$DBc->sqlEscape($facebook->getAccessToken())."','".time()."','1') ON DUPLICATE KEY UPDATE aft_token='".$DBc->sqlEscape($facebook->getAccessToken())."', aft_date='".time()."'"); - }*/ - - -} - -if(!$_USER->isIG && $_CONF['enable_webig'] == false) { - $c .= ach_render_forbidden(false); -} -elseif($_USER->isIG && $_CONF['enable_offgame'] == false) { - $c .= ach_render_forbidden(true); -} +if ( !$_USER -> isIG() ) { + /** + * $facebook = new Facebook(array( + * 'appId' => $_CONF['fb_id'], + * 'secret' => $_CONF['fb_secret'], + * 'cookie' => true + * )); + * + * #code taken from facebook tutorial + * + * // Get the url to redirect for login to facebook + * // and request permission to write on the user's wall. + * $login_url = $facebook->getLoginUrl( + * array('scope' => 'publish_stream') + * ); + * + * // If not authenticated, redirect to the facebook login dialog. + * // The $login_url will take care of redirecting back to us + * // after successful login. + * if (! $facebook->getUser()) { + * $c .= ';'; + * } + * else { + * $DBc->sqlQuery("INSERT INTO ach_fb_token (aft_player,aft_token,aft_date,aft_allow) VALUES ('".$_USER->getID()."','".$DBc->sqlEscape($facebook->getAccessToken())."','".time()."','1') ON DUPLICATE KEY UPDATE aft_token='".$DBc->sqlEscape($facebook->getAccessToken())."', aft_date='".time()."'"); + * } + */ + + + } + +if ( !$_USER -> isIG && $_CONF['enable_webig'] == false ) { + $c .= ach_render_forbidden( false ); + + } +elseif ( $_USER -> isIG && $_CONF['enable_offgame'] == false ) { + $c .= ach_render_forbidden( true ); + + } else { - $c .= ach_render(); -} + $c .= ach_render(); + } -echo ryzom_app_render(strtoupper(get_translation('ach_app_name',$_USER->getLang())), $c, $_USER->isIG()); +echo ryzom_app_render( strtoupper( get_translation( 'ach_app_name', $_USER -> getLang() ) ), $c, $_USER -> isIG() ); ?> From 4b871c43f5d42aa8d9af4c4be5610b956c5b9622 Mon Sep 17 00:00:00 2001 From: botanic Date: Fri, 15 Aug 2014 03:49:39 -0700 Subject: [PATCH 255/282] updated doxygen --- code/web/docs/ams/doxygen/Doxyfile | 18 +- code/web/docs/ams/html/add__sgroup_8php.html | 138 -- code/web/docs/ams/html/add__user_8php.html | 156 -- .../ams/html/add__user__to__sgroup_8php.html | 138 -- code/web/docs/ams/html/annotated.html | 136 -- code/web/docs/ams/html/assigned_8php.html | 117 -- code/web/docs/ams/html/bc_s.png | Bin 677 -> 0 bytes code/web/docs/ams/html/change__info_8php.html | 138 -- code/web/docs/ams/html/change__mail_8php.html | 138 -- .../docs/ams/html/change__password_8php.html | 138 -- .../ams/html/change__permission_8php.html | 138 -- .../ams/html/change__receivemail_8php.html | 138 -- code/web/docs/ams/html/classAssigned.html | 529 ------ code/web/docs/ams/html/classDBLayer.html | 284 ---- code/web/docs/ams/html/classForwarded.html | 478 ------ .../web/docs/ams/html/classGui__Elements.html | 250 --- code/web/docs/ams/html/classHelpers.html | 292 ---- .../ams/html/classIn__Support__Group.html | 393 ----- .../web/docs/ams/html/classMail__Handler.html | 524 ------ code/web/docs/ams/html/classMyCrypt.html | 327 ---- code/web/docs/ams/html/classPagination.html | 368 ---- code/web/docs/ams/html/classQuerycache.html | 485 ------ .../docs/ams/html/classSupport__Group.html | 1082 ------------ code/web/docs/ams/html/classSync.html | 149 -- code/web/docs/ams/html/classTicket.html | 1429 ---------------- .../docs/ams/html/classTicket__Category.html | 402 ----- .../docs/ams/html/classTicket__Content.html | 382 ----- code/web/docs/ams/html/classTicket__Info.html | 1463 ---------------- code/web/docs/ams/html/classTicket__Log.html | 763 --------- .../web/docs/ams/html/classTicket__Queue.html | 401 ----- .../ams/html/classTicket__Queue__Handler.html | 395 ----- .../web/docs/ams/html/classTicket__Reply.html | 764 --------- code/web/docs/ams/html/classTicket__User.html | 745 -------- code/web/docs/ams/html/classUsers.html | 641 ------- code/web/docs/ams/html/classUsers.png | Bin 423 -> 0 bytes code/web/docs/ams/html/classWebUsers.html | 1509 ----------------- code/web/docs/ams/html/classWebUsers.png | Bin 428 -> 0 bytes code/web/docs/ams/html/classes.html | 141 -- code/web/docs/ams/html/closed.png | Bin 126 -> 0 bytes .../docs/ams/html/create__ticket_8php.html | 138 -- code/web/docs/ams/html/createticket_8php.html | 138 -- code/web/docs/ams/html/dashboard_8php.html | 138 -- code/web/docs/ams/html/db.png | Bin 205565 -> 0 bytes code/web/docs/ams/html/dblayer_8php.html | 117 -- code/web/docs/ams/html/deprecated.html | 107 -- code/web/docs/ams/html/design.html | 216 --- code/web/docs/ams/html/doxygen.css | 949 ----------- code/web/docs/ams/html/doxygen.png | Bin 3942 -> 0 bytes ...2ryzommanage_2autoload_2webusers_8php.html | 117 -- ...pal__module_2ryzommanage_2config_8php.html | 820 --------- ...module_2ryzommanage_2inc_2logout_8php.html | 133 -- ...dule_2ryzommanage_2inc_2settings_8php.html | 150 -- ...le_2ryzommanage_2inc_2show__user_8php.html | 133 -- code/web/docs/ams/html/error_8php.html | 138 -- code/web/docs/ams/html/files.html | 175 -- code/web/docs/ams/html/forwarded_8php.html | 117 -- code/web/docs/ams/html/func_2login_8php.html | 138 -- code/web/docs/ams/html/functions.html | 351 ---- code/web/docs/ams/html/functions_0x5f.html | 159 -- code/web/docs/ams/html/functions_0x61.html | 147 -- code/web/docs/ams/html/functions_0x63.html | 254 --- code/web/docs/ams/html/functions_0x64.html | 158 -- code/web/docs/ams/html/functions_0x65.html | 152 -- code/web/docs/ams/html/functions_0x66.html | 144 -- code/web/docs/ams/html/functions_0x67.html | 461 ----- code/web/docs/ams/html/functions_0x68.html | 149 -- code/web/docs/ams/html/functions_0x69.html | 158 -- code/web/docs/ams/html/functions_0x6c.html | 195 --- code/web/docs/ams/html/functions_0x6d.html | 149 -- code/web/docs/ams/html/functions_0x6e.html | 143 -- code/web/docs/ams/html/functions_0x6f.html | 143 -- code/web/docs/ams/html/functions_0x73.html | 344 ---- code/web/docs/ams/html/functions_0x74.html | 149 -- code/web/docs/ams/html/functions_0x75.html | 163 -- code/web/docs/ams/html/functions_0x76.html | 143 -- code/web/docs/ams/html/functions_func.html | 158 -- .../docs/ams/html/functions_func_0x61.html | 146 -- .../docs/ams/html/functions_func_0x63.html | 253 --- .../docs/ams/html/functions_func_0x64.html | 157 -- .../docs/ams/html/functions_func_0x65.html | 151 -- .../docs/ams/html/functions_func_0x66.html | 143 -- .../docs/ams/html/functions_func_0x67.html | 460 ----- .../docs/ams/html/functions_func_0x68.html | 148 -- .../docs/ams/html/functions_func_0x69.html | 157 -- .../docs/ams/html/functions_func_0x6c.html | 194 --- .../docs/ams/html/functions_func_0x6d.html | 148 -- .../docs/ams/html/functions_func_0x6e.html | 142 -- .../docs/ams/html/functions_func_0x6f.html | 142 -- .../docs/ams/html/functions_func_0x73.html | 343 ---- .../docs/ams/html/functions_func_0x74.html | 148 -- .../docs/ams/html/functions_func_0x75.html | 162 -- .../docs/ams/html/functions_func_0x76.html | 142 -- code/web/docs/ams/html/functions_vars.html | 334 ---- code/web/docs/ams/html/globals.html | 345 ---- code/web/docs/ams/html/globals_func.html | 269 --- code/web/docs/ams/html/globals_vars.html | 192 --- .../web/docs/ams/html/gui__elements_8php.html | 117 -- code/web/docs/ams/html/helpers_8php.html | 117 -- code/web/docs/ams/html/hierarchy.html | 139 -- .../ams/html/in__support__group_8php.html | 117 -- code/web/docs/ams/html/inc_2login_8php.html | 138 -- code/web/docs/ams/html/index.html | 110 -- code/web/docs/ams/html/index_8php.html | 109 -- code/web/docs/ams/html/info.jpg | Bin 464423 -> 0 bytes code/web/docs/ams/html/info_8php.html | 109 -- code/web/docs/ams/html/install_8php.html | 130 -- code/web/docs/ams/html/installdox | 112 -- code/web/docs/ams/html/jquery.js | 64 - code/web/docs/ams/html/libinclude_8php.html | 138 -- code/web/docs/ams/html/logo.png | Bin 19642 -> 0 bytes code/web/docs/ams/html/mail__cron_8php.html | 134 -- .../web/docs/ams/html/mail__handler_8php.html | 117 -- .../html/modify__email__of__sgroup_8php.html | 138 -- code/web/docs/ams/html/mycrypt_8php.html | 117 -- code/web/docs/ams/html/nav_f.png | Bin 159 -> 0 bytes code/web/docs/ams/html/nav_h.png | Bin 97 -> 0 bytes code/web/docs/ams/html/open.png | Bin 118 -> 0 bytes code/web/docs/ams/html/pages.html | 111 -- code/web/docs/ams/html/pagination_8php.html | 117 -- code/web/docs/ams/html/querycache_8php.html | 117 -- code/web/docs/ams/html/register_8php.html | 137 -- .../docs/ams/html/reply__on__ticket_8php.html | 138 -- code/web/docs/ams/html/search/all_24.html | 25 - code/web/docs/ams/html/search/all_24.js | 91 - code/web/docs/ams/html/search/all_5f.html | 25 - code/web/docs/ams/html/search/all_5f.js | 5 - code/web/docs/ams/html/search/all_61.html | 25 - code/web/docs/ams/html/search/all_61.js | 13 - code/web/docs/ams/html/search/all_63.html | 25 - code/web/docs/ams/html/search/all_63.js | 51 - code/web/docs/ams/html/search/all_64.html | 25 - code/web/docs/ams/html/search/all_64.js | 12 - code/web/docs/ams/html/search/all_65.html | 25 - code/web/docs/ams/html/search/all_65.js | 9 - code/web/docs/ams/html/search/all_66.html | 25 - code/web/docs/ams/html/search/all_66.js | 6 - code/web/docs/ams/html/search/all_67.html | 25 - code/web/docs/ams/html/search/all_67.js | 108 -- code/web/docs/ams/html/search/all_68.html | 25 - code/web/docs/ams/html/search/all_68.js | 8 - code/web/docs/ams/html/search/all_69.html | 25 - code/web/docs/ams/html/search/all_69.js | 14 - code/web/docs/ams/html/search/all_6c.html | 25 - code/web/docs/ams/html/search/all_6c.js | 28 - code/web/docs/ams/html/search/all_6d.html | 25 - code/web/docs/ams/html/search/all_6d.js | 13 - code/web/docs/ams/html/search/all_6e.html | 25 - code/web/docs/ams/html/search/all_6e.js | 4 - code/web/docs/ams/html/search/all_6f.html | 25 - code/web/docs/ams/html/search/all_6f.js | 4 - code/web/docs/ams/html/search/all_70.html | 25 - code/web/docs/ams/html/search/all_70.js | 5 - code/web/docs/ams/html/search/all_71.html | 25 - code/web/docs/ams/html/search/all_71.js | 5 - code/web/docs/ams/html/search/all_72.html | 25 - code/web/docs/ams/html/search/all_72.js | 7 - code/web/docs/ams/html/search/all_73.html | 25 - code/web/docs/ams/html/search/all_73.js | 90 - code/web/docs/ams/html/search/all_74.html | 25 - code/web/docs/ams/html/search/all_74.js | 24 - code/web/docs/ams/html/search/all_75.html | 25 - code/web/docs/ams/html/search/all_75.js | 12 - code/web/docs/ams/html/search/all_76.html | 25 - code/web/docs/ams/html/search/all_76.js | 4 - code/web/docs/ams/html/search/all_77.html | 25 - code/web/docs/ams/html/search/all_77.js | 7 - code/web/docs/ams/html/search/classes_61.html | 25 - code/web/docs/ams/html/search/classes_61.js | 4 - code/web/docs/ams/html/search/classes_64.html | 25 - code/web/docs/ams/html/search/classes_64.js | 4 - code/web/docs/ams/html/search/classes_66.html | 25 - code/web/docs/ams/html/search/classes_66.js | 4 - code/web/docs/ams/html/search/classes_67.html | 25 - code/web/docs/ams/html/search/classes_67.js | 4 - code/web/docs/ams/html/search/classes_68.html | 25 - code/web/docs/ams/html/search/classes_68.js | 4 - code/web/docs/ams/html/search/classes_69.html | 25 - code/web/docs/ams/html/search/classes_69.js | 4 - code/web/docs/ams/html/search/classes_6d.html | 25 - code/web/docs/ams/html/search/classes_6d.js | 5 - code/web/docs/ams/html/search/classes_70.html | 25 - code/web/docs/ams/html/search/classes_70.js | 4 - code/web/docs/ams/html/search/classes_71.html | 25 - code/web/docs/ams/html/search/classes_71.js | 4 - code/web/docs/ams/html/search/classes_73.html | 25 - code/web/docs/ams/html/search/classes_73.js | 5 - code/web/docs/ams/html/search/classes_74.html | 25 - code/web/docs/ams/html/search/classes_74.js | 12 - code/web/docs/ams/html/search/classes_75.html | 25 - code/web/docs/ams/html/search/classes_75.js | 4 - code/web/docs/ams/html/search/classes_77.html | 25 - code/web/docs/ams/html/search/classes_77.js | 4 - code/web/docs/ams/html/search/close.png | Bin 273 -> 0 bytes code/web/docs/ams/html/search/files_61.html | 25 - code/web/docs/ams/html/search/files_61.js | 7 - code/web/docs/ams/html/search/files_63.html | 25 - code/web/docs/ams/html/search/files_63.js | 12 - code/web/docs/ams/html/search/files_64.html | 25 - code/web/docs/ams/html/search/files_64.js | 5 - code/web/docs/ams/html/search/files_65.html | 25 - code/web/docs/ams/html/search/files_65.js | 4 - code/web/docs/ams/html/search/files_66.html | 25 - code/web/docs/ams/html/search/files_66.js | 4 - code/web/docs/ams/html/search/files_67.html | 25 - code/web/docs/ams/html/search/files_67.js | 4 - code/web/docs/ams/html/search/files_68.html | 25 - code/web/docs/ams/html/search/files_68.js | 4 - code/web/docs/ams/html/search/files_69.html | 25 - code/web/docs/ams/html/search/files_69.js | 7 - code/web/docs/ams/html/search/files_6c.html | 25 - code/web/docs/ams/html/search/files_6c.js | 8 - code/web/docs/ams/html/search/files_6d.html | 25 - code/web/docs/ams/html/search/files_6d.js | 7 - code/web/docs/ams/html/search/files_70.html | 25 - code/web/docs/ams/html/search/files_70.js | 4 - code/web/docs/ams/html/search/files_71.html | 25 - code/web/docs/ams/html/search/files_71.js | 4 - code/web/docs/ams/html/search/files_72.html | 25 - code/web/docs/ams/html/search/files_72.js | 5 - code/web/docs/ams/html/search/files_73.html | 25 - code/web/docs/ams/html/search/files_73.js | 18 - code/web/docs/ams/html/search/files_74.html | 25 - code/web/docs/ams/html/search/files_74.js | 12 - code/web/docs/ams/html/search/files_75.html | 25 - code/web/docs/ams/html/search/files_75.js | 5 - code/web/docs/ams/html/search/files_77.html | 25 - code/web/docs/ams/html/search/files_77.js | 5 - .../docs/ams/html/search/functions_5f.html | 25 - code/web/docs/ams/html/search/functions_5f.js | 5 - .../docs/ams/html/search/functions_61.html | 25 - code/web/docs/ams/html/search/functions_61.js | 8 - .../docs/ams/html/search/functions_63.html | 25 - code/web/docs/ams/html/search/functions_63.js | 42 - .../docs/ams/html/search/functions_64.html | 25 - code/web/docs/ams/html/search/functions_64.js | 9 - .../docs/ams/html/search/functions_65.html | 25 - code/web/docs/ams/html/search/functions_65.js | 8 - .../docs/ams/html/search/functions_66.html | 25 - code/web/docs/ams/html/search/functions_66.js | 4 - .../docs/ams/html/search/functions_67.html | 25 - code/web/docs/ams/html/search/functions_67.js | 106 -- .../docs/ams/html/search/functions_68.html | 25 - code/web/docs/ams/html/search/functions_68.js | 6 - .../docs/ams/html/search/functions_69.html | 25 - code/web/docs/ams/html/search/functions_69.js | 9 - .../docs/ams/html/search/functions_6c.html | 25 - code/web/docs/ams/html/search/functions_6c.js | 23 - .../docs/ams/html/search/functions_6d.html | 25 - code/web/docs/ams/html/search/functions_6d.js | 7 - .../docs/ams/html/search/functions_6e.html | 25 - code/web/docs/ams/html/search/functions_6e.js | 4 - .../docs/ams/html/search/functions_6f.html | 25 - code/web/docs/ams/html/search/functions_6f.js | 4 - .../docs/ams/html/search/functions_72.html | 25 - code/web/docs/ams/html/search/functions_72.js | 5 - .../docs/ams/html/search/functions_73.html | 25 - code/web/docs/ams/html/search/functions_73.js | 73 - .../docs/ams/html/search/functions_74.html | 25 - code/web/docs/ams/html/search/functions_74.js | 6 - .../docs/ams/html/search/functions_75.html | 25 - code/web/docs/ams/html/search/functions_75.js | 9 - .../docs/ams/html/search/functions_76.html | 25 - code/web/docs/ams/html/search/functions_76.js | 4 - .../docs/ams/html/search/functions_77.html | 25 - code/web/docs/ams/html/search/functions_77.js | 4 - code/web/docs/ams/html/search/mag_sel.png | Bin 563 -> 0 bytes code/web/docs/ams/html/search/nomatches.html | 12 - code/web/docs/ams/html/search/search.css | 238 --- code/web/docs/ams/html/search/search.js | 803 --------- code/web/docs/ams/html/search/search_l.png | Bin 604 -> 0 bytes code/web/docs/ams/html/search/search_m.png | Bin 158 -> 0 bytes code/web/docs/ams/html/search/search_r.png | Bin 612 -> 0 bytes .../docs/ams/html/search/variables_24.html | 25 - code/web/docs/ams/html/search/variables_24.js | 91 - code/web/docs/ams/html/sgroup__list_8php.html | 138 -- code/web/docs/ams/html/show__queue_8php.html | 138 -- code/web/docs/ams/html/show__reply_8php.html | 138 -- code/web/docs/ams/html/show__sgroup_8php.html | 138 -- code/web/docs/ams/html/show__ticket_8php.html | 138 -- .../ams/html/show__ticket__info_8php.html | 138 -- .../docs/ams/html/show__ticket__log_8php.html | 138 -- .../docs/ams/html/support__group_8php.html | 117 -- code/web/docs/ams/html/sync_8php.html | 117 -- code/web/docs/ams/html/sync__cron_8php.html | 109 -- code/web/docs/ams/html/syncing_8php.html | 138 -- code/web/docs/ams/html/tab_a.png | Bin 140 -> 0 bytes code/web/docs/ams/html/tab_b.png | Bin 178 -> 0 bytes code/web/docs/ams/html/tab_h.png | Bin 192 -> 0 bytes code/web/docs/ams/html/tab_s.png | Bin 189 -> 0 bytes code/web/docs/ams/html/tabs.css | 59 - code/web/docs/ams/html/ticket_8php.html | 117 -- .../docs/ams/html/ticket__category_8php.html | 117 -- .../docs/ams/html/ticket__content_8php.html | 117 -- code/web/docs/ams/html/ticket__info_8php.html | 117 -- code/web/docs/ams/html/ticket__log_8php.html | 117 -- .../web/docs/ams/html/ticket__queue_8php.html | 117 -- .../ams/html/ticket__queue__handler_8php.html | 117 -- .../web/docs/ams/html/ticket__reply_8php.html | 117 -- code/web/docs/ams/html/ticket__user_8php.html | 117 -- code/web/docs/ams/html/todo.html | 115 -- code/web/docs/ams/html/userlist_8php.html | 138 -- code/web/docs/ams/html/users_8php.html | 117 -- code/web/docs/ams/html/www_2config_8php.html | 820 --------- .../www_2html_2autoload_2webusers_8php.html | 117 -- .../ams/html/www_2html_2inc_2logout_8php.html | 138 -- .../html/www_2html_2inc_2settings_8php.html | 155 -- .../html/www_2html_2inc_2show__user_8php.html | 138 -- 307 files changed, 7 insertions(+), 38002 deletions(-) delete mode 100644 code/web/docs/ams/html/add__sgroup_8php.html delete mode 100644 code/web/docs/ams/html/add__user_8php.html delete mode 100644 code/web/docs/ams/html/add__user__to__sgroup_8php.html delete mode 100644 code/web/docs/ams/html/annotated.html delete mode 100644 code/web/docs/ams/html/assigned_8php.html delete mode 100644 code/web/docs/ams/html/bc_s.png delete mode 100644 code/web/docs/ams/html/change__info_8php.html delete mode 100644 code/web/docs/ams/html/change__mail_8php.html delete mode 100644 code/web/docs/ams/html/change__password_8php.html delete mode 100644 code/web/docs/ams/html/change__permission_8php.html delete mode 100644 code/web/docs/ams/html/change__receivemail_8php.html delete mode 100644 code/web/docs/ams/html/classAssigned.html delete mode 100644 code/web/docs/ams/html/classDBLayer.html delete mode 100644 code/web/docs/ams/html/classForwarded.html delete mode 100644 code/web/docs/ams/html/classGui__Elements.html delete mode 100644 code/web/docs/ams/html/classHelpers.html delete mode 100644 code/web/docs/ams/html/classIn__Support__Group.html delete mode 100644 code/web/docs/ams/html/classMail__Handler.html delete mode 100644 code/web/docs/ams/html/classMyCrypt.html delete mode 100644 code/web/docs/ams/html/classPagination.html delete mode 100644 code/web/docs/ams/html/classQuerycache.html delete mode 100644 code/web/docs/ams/html/classSupport__Group.html delete mode 100644 code/web/docs/ams/html/classSync.html delete mode 100644 code/web/docs/ams/html/classTicket.html delete mode 100644 code/web/docs/ams/html/classTicket__Category.html delete mode 100644 code/web/docs/ams/html/classTicket__Content.html delete mode 100644 code/web/docs/ams/html/classTicket__Info.html delete mode 100644 code/web/docs/ams/html/classTicket__Log.html delete mode 100644 code/web/docs/ams/html/classTicket__Queue.html delete mode 100644 code/web/docs/ams/html/classTicket__Queue__Handler.html delete mode 100644 code/web/docs/ams/html/classTicket__Reply.html delete mode 100644 code/web/docs/ams/html/classTicket__User.html delete mode 100644 code/web/docs/ams/html/classUsers.html delete mode 100644 code/web/docs/ams/html/classUsers.png delete mode 100644 code/web/docs/ams/html/classWebUsers.html delete mode 100644 code/web/docs/ams/html/classWebUsers.png delete mode 100644 code/web/docs/ams/html/classes.html delete mode 100644 code/web/docs/ams/html/closed.png delete mode 100644 code/web/docs/ams/html/create__ticket_8php.html delete mode 100644 code/web/docs/ams/html/createticket_8php.html delete mode 100644 code/web/docs/ams/html/dashboard_8php.html delete mode 100644 code/web/docs/ams/html/db.png delete mode 100644 code/web/docs/ams/html/dblayer_8php.html delete mode 100644 code/web/docs/ams/html/deprecated.html delete mode 100644 code/web/docs/ams/html/design.html delete mode 100644 code/web/docs/ams/html/doxygen.css delete mode 100644 code/web/docs/ams/html/doxygen.png delete mode 100644 code/web/docs/ams/html/drupal__module_2ryzommanage_2autoload_2webusers_8php.html delete mode 100644 code/web/docs/ams/html/drupal__module_2ryzommanage_2config_8php.html delete mode 100644 code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2logout_8php.html delete mode 100644 code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2settings_8php.html delete mode 100644 code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2show__user_8php.html delete mode 100644 code/web/docs/ams/html/error_8php.html delete mode 100644 code/web/docs/ams/html/files.html delete mode 100644 code/web/docs/ams/html/forwarded_8php.html delete mode 100644 code/web/docs/ams/html/func_2login_8php.html delete mode 100644 code/web/docs/ams/html/functions.html delete mode 100644 code/web/docs/ams/html/functions_0x5f.html delete mode 100644 code/web/docs/ams/html/functions_0x61.html delete mode 100644 code/web/docs/ams/html/functions_0x63.html delete mode 100644 code/web/docs/ams/html/functions_0x64.html delete mode 100644 code/web/docs/ams/html/functions_0x65.html delete mode 100644 code/web/docs/ams/html/functions_0x66.html delete mode 100644 code/web/docs/ams/html/functions_0x67.html delete mode 100644 code/web/docs/ams/html/functions_0x68.html delete mode 100644 code/web/docs/ams/html/functions_0x69.html delete mode 100644 code/web/docs/ams/html/functions_0x6c.html delete mode 100644 code/web/docs/ams/html/functions_0x6d.html delete mode 100644 code/web/docs/ams/html/functions_0x6e.html delete mode 100644 code/web/docs/ams/html/functions_0x6f.html delete mode 100644 code/web/docs/ams/html/functions_0x73.html delete mode 100644 code/web/docs/ams/html/functions_0x74.html delete mode 100644 code/web/docs/ams/html/functions_0x75.html delete mode 100644 code/web/docs/ams/html/functions_0x76.html delete mode 100644 code/web/docs/ams/html/functions_func.html delete mode 100644 code/web/docs/ams/html/functions_func_0x61.html delete mode 100644 code/web/docs/ams/html/functions_func_0x63.html delete mode 100644 code/web/docs/ams/html/functions_func_0x64.html delete mode 100644 code/web/docs/ams/html/functions_func_0x65.html delete mode 100644 code/web/docs/ams/html/functions_func_0x66.html delete mode 100644 code/web/docs/ams/html/functions_func_0x67.html delete mode 100644 code/web/docs/ams/html/functions_func_0x68.html delete mode 100644 code/web/docs/ams/html/functions_func_0x69.html delete mode 100644 code/web/docs/ams/html/functions_func_0x6c.html delete mode 100644 code/web/docs/ams/html/functions_func_0x6d.html delete mode 100644 code/web/docs/ams/html/functions_func_0x6e.html delete mode 100644 code/web/docs/ams/html/functions_func_0x6f.html delete mode 100644 code/web/docs/ams/html/functions_func_0x73.html delete mode 100644 code/web/docs/ams/html/functions_func_0x74.html delete mode 100644 code/web/docs/ams/html/functions_func_0x75.html delete mode 100644 code/web/docs/ams/html/functions_func_0x76.html delete mode 100644 code/web/docs/ams/html/functions_vars.html delete mode 100644 code/web/docs/ams/html/globals.html delete mode 100644 code/web/docs/ams/html/globals_func.html delete mode 100644 code/web/docs/ams/html/globals_vars.html delete mode 100644 code/web/docs/ams/html/gui__elements_8php.html delete mode 100644 code/web/docs/ams/html/helpers_8php.html delete mode 100644 code/web/docs/ams/html/hierarchy.html delete mode 100644 code/web/docs/ams/html/in__support__group_8php.html delete mode 100644 code/web/docs/ams/html/inc_2login_8php.html delete mode 100644 code/web/docs/ams/html/index.html delete mode 100644 code/web/docs/ams/html/index_8php.html delete mode 100644 code/web/docs/ams/html/info.jpg delete mode 100644 code/web/docs/ams/html/info_8php.html delete mode 100644 code/web/docs/ams/html/install_8php.html delete mode 100644 code/web/docs/ams/html/installdox delete mode 100644 code/web/docs/ams/html/jquery.js delete mode 100644 code/web/docs/ams/html/libinclude_8php.html delete mode 100644 code/web/docs/ams/html/logo.png delete mode 100644 code/web/docs/ams/html/mail__cron_8php.html delete mode 100644 code/web/docs/ams/html/mail__handler_8php.html delete mode 100644 code/web/docs/ams/html/modify__email__of__sgroup_8php.html delete mode 100644 code/web/docs/ams/html/mycrypt_8php.html delete mode 100644 code/web/docs/ams/html/nav_f.png delete mode 100644 code/web/docs/ams/html/nav_h.png delete mode 100644 code/web/docs/ams/html/open.png delete mode 100644 code/web/docs/ams/html/pages.html delete mode 100644 code/web/docs/ams/html/pagination_8php.html delete mode 100644 code/web/docs/ams/html/querycache_8php.html delete mode 100644 code/web/docs/ams/html/register_8php.html delete mode 100644 code/web/docs/ams/html/reply__on__ticket_8php.html delete mode 100644 code/web/docs/ams/html/search/all_24.html delete mode 100644 code/web/docs/ams/html/search/all_24.js delete mode 100644 code/web/docs/ams/html/search/all_5f.html delete mode 100644 code/web/docs/ams/html/search/all_5f.js delete mode 100644 code/web/docs/ams/html/search/all_61.html delete mode 100644 code/web/docs/ams/html/search/all_61.js delete mode 100644 code/web/docs/ams/html/search/all_63.html delete mode 100644 code/web/docs/ams/html/search/all_63.js delete mode 100644 code/web/docs/ams/html/search/all_64.html delete mode 100644 code/web/docs/ams/html/search/all_64.js delete mode 100644 code/web/docs/ams/html/search/all_65.html delete mode 100644 code/web/docs/ams/html/search/all_65.js delete mode 100644 code/web/docs/ams/html/search/all_66.html delete mode 100644 code/web/docs/ams/html/search/all_66.js delete mode 100644 code/web/docs/ams/html/search/all_67.html delete mode 100644 code/web/docs/ams/html/search/all_67.js delete mode 100644 code/web/docs/ams/html/search/all_68.html delete mode 100644 code/web/docs/ams/html/search/all_68.js delete mode 100644 code/web/docs/ams/html/search/all_69.html delete mode 100644 code/web/docs/ams/html/search/all_69.js delete mode 100644 code/web/docs/ams/html/search/all_6c.html delete mode 100644 code/web/docs/ams/html/search/all_6c.js delete mode 100644 code/web/docs/ams/html/search/all_6d.html delete mode 100644 code/web/docs/ams/html/search/all_6d.js delete mode 100644 code/web/docs/ams/html/search/all_6e.html delete mode 100644 code/web/docs/ams/html/search/all_6e.js delete mode 100644 code/web/docs/ams/html/search/all_6f.html delete mode 100644 code/web/docs/ams/html/search/all_6f.js delete mode 100644 code/web/docs/ams/html/search/all_70.html delete mode 100644 code/web/docs/ams/html/search/all_70.js delete mode 100644 code/web/docs/ams/html/search/all_71.html delete mode 100644 code/web/docs/ams/html/search/all_71.js delete mode 100644 code/web/docs/ams/html/search/all_72.html delete mode 100644 code/web/docs/ams/html/search/all_72.js delete mode 100644 code/web/docs/ams/html/search/all_73.html delete mode 100644 code/web/docs/ams/html/search/all_73.js delete mode 100644 code/web/docs/ams/html/search/all_74.html delete mode 100644 code/web/docs/ams/html/search/all_74.js delete mode 100644 code/web/docs/ams/html/search/all_75.html delete mode 100644 code/web/docs/ams/html/search/all_75.js delete mode 100644 code/web/docs/ams/html/search/all_76.html delete mode 100644 code/web/docs/ams/html/search/all_76.js delete mode 100644 code/web/docs/ams/html/search/all_77.html delete mode 100644 code/web/docs/ams/html/search/all_77.js delete mode 100644 code/web/docs/ams/html/search/classes_61.html delete mode 100644 code/web/docs/ams/html/search/classes_61.js delete mode 100644 code/web/docs/ams/html/search/classes_64.html delete mode 100644 code/web/docs/ams/html/search/classes_64.js delete mode 100644 code/web/docs/ams/html/search/classes_66.html delete mode 100644 code/web/docs/ams/html/search/classes_66.js delete mode 100644 code/web/docs/ams/html/search/classes_67.html delete mode 100644 code/web/docs/ams/html/search/classes_67.js delete mode 100644 code/web/docs/ams/html/search/classes_68.html delete mode 100644 code/web/docs/ams/html/search/classes_68.js delete mode 100644 code/web/docs/ams/html/search/classes_69.html delete mode 100644 code/web/docs/ams/html/search/classes_69.js delete mode 100644 code/web/docs/ams/html/search/classes_6d.html delete mode 100644 code/web/docs/ams/html/search/classes_6d.js delete mode 100644 code/web/docs/ams/html/search/classes_70.html delete mode 100644 code/web/docs/ams/html/search/classes_70.js delete mode 100644 code/web/docs/ams/html/search/classes_71.html delete mode 100644 code/web/docs/ams/html/search/classes_71.js delete mode 100644 code/web/docs/ams/html/search/classes_73.html delete mode 100644 code/web/docs/ams/html/search/classes_73.js delete mode 100644 code/web/docs/ams/html/search/classes_74.html delete mode 100644 code/web/docs/ams/html/search/classes_74.js delete mode 100644 code/web/docs/ams/html/search/classes_75.html delete mode 100644 code/web/docs/ams/html/search/classes_75.js delete mode 100644 code/web/docs/ams/html/search/classes_77.html delete mode 100644 code/web/docs/ams/html/search/classes_77.js delete mode 100644 code/web/docs/ams/html/search/close.png delete mode 100644 code/web/docs/ams/html/search/files_61.html delete mode 100644 code/web/docs/ams/html/search/files_61.js delete mode 100644 code/web/docs/ams/html/search/files_63.html delete mode 100644 code/web/docs/ams/html/search/files_63.js delete mode 100644 code/web/docs/ams/html/search/files_64.html delete mode 100644 code/web/docs/ams/html/search/files_64.js delete mode 100644 code/web/docs/ams/html/search/files_65.html delete mode 100644 code/web/docs/ams/html/search/files_65.js delete mode 100644 code/web/docs/ams/html/search/files_66.html delete mode 100644 code/web/docs/ams/html/search/files_66.js delete mode 100644 code/web/docs/ams/html/search/files_67.html delete mode 100644 code/web/docs/ams/html/search/files_67.js delete mode 100644 code/web/docs/ams/html/search/files_68.html delete mode 100644 code/web/docs/ams/html/search/files_68.js delete mode 100644 code/web/docs/ams/html/search/files_69.html delete mode 100644 code/web/docs/ams/html/search/files_69.js delete mode 100644 code/web/docs/ams/html/search/files_6c.html delete mode 100644 code/web/docs/ams/html/search/files_6c.js delete mode 100644 code/web/docs/ams/html/search/files_6d.html delete mode 100644 code/web/docs/ams/html/search/files_6d.js delete mode 100644 code/web/docs/ams/html/search/files_70.html delete mode 100644 code/web/docs/ams/html/search/files_70.js delete mode 100644 code/web/docs/ams/html/search/files_71.html delete mode 100644 code/web/docs/ams/html/search/files_71.js delete mode 100644 code/web/docs/ams/html/search/files_72.html delete mode 100644 code/web/docs/ams/html/search/files_72.js delete mode 100644 code/web/docs/ams/html/search/files_73.html delete mode 100644 code/web/docs/ams/html/search/files_73.js delete mode 100644 code/web/docs/ams/html/search/files_74.html delete mode 100644 code/web/docs/ams/html/search/files_74.js delete mode 100644 code/web/docs/ams/html/search/files_75.html delete mode 100644 code/web/docs/ams/html/search/files_75.js delete mode 100644 code/web/docs/ams/html/search/files_77.html delete mode 100644 code/web/docs/ams/html/search/files_77.js delete mode 100644 code/web/docs/ams/html/search/functions_5f.html delete mode 100644 code/web/docs/ams/html/search/functions_5f.js delete mode 100644 code/web/docs/ams/html/search/functions_61.html delete mode 100644 code/web/docs/ams/html/search/functions_61.js delete mode 100644 code/web/docs/ams/html/search/functions_63.html delete mode 100644 code/web/docs/ams/html/search/functions_63.js delete mode 100644 code/web/docs/ams/html/search/functions_64.html delete mode 100644 code/web/docs/ams/html/search/functions_64.js delete mode 100644 code/web/docs/ams/html/search/functions_65.html delete mode 100644 code/web/docs/ams/html/search/functions_65.js delete mode 100644 code/web/docs/ams/html/search/functions_66.html delete mode 100644 code/web/docs/ams/html/search/functions_66.js delete mode 100644 code/web/docs/ams/html/search/functions_67.html delete mode 100644 code/web/docs/ams/html/search/functions_67.js delete mode 100644 code/web/docs/ams/html/search/functions_68.html delete mode 100644 code/web/docs/ams/html/search/functions_68.js delete mode 100644 code/web/docs/ams/html/search/functions_69.html delete mode 100644 code/web/docs/ams/html/search/functions_69.js delete mode 100644 code/web/docs/ams/html/search/functions_6c.html delete mode 100644 code/web/docs/ams/html/search/functions_6c.js delete mode 100644 code/web/docs/ams/html/search/functions_6d.html delete mode 100644 code/web/docs/ams/html/search/functions_6d.js delete mode 100644 code/web/docs/ams/html/search/functions_6e.html delete mode 100644 code/web/docs/ams/html/search/functions_6e.js delete mode 100644 code/web/docs/ams/html/search/functions_6f.html delete mode 100644 code/web/docs/ams/html/search/functions_6f.js delete mode 100644 code/web/docs/ams/html/search/functions_72.html delete mode 100644 code/web/docs/ams/html/search/functions_72.js delete mode 100644 code/web/docs/ams/html/search/functions_73.html delete mode 100644 code/web/docs/ams/html/search/functions_73.js delete mode 100644 code/web/docs/ams/html/search/functions_74.html delete mode 100644 code/web/docs/ams/html/search/functions_74.js delete mode 100644 code/web/docs/ams/html/search/functions_75.html delete mode 100644 code/web/docs/ams/html/search/functions_75.js delete mode 100644 code/web/docs/ams/html/search/functions_76.html delete mode 100644 code/web/docs/ams/html/search/functions_76.js delete mode 100644 code/web/docs/ams/html/search/functions_77.html delete mode 100644 code/web/docs/ams/html/search/functions_77.js delete mode 100644 code/web/docs/ams/html/search/mag_sel.png delete mode 100644 code/web/docs/ams/html/search/nomatches.html delete mode 100644 code/web/docs/ams/html/search/search.css delete mode 100644 code/web/docs/ams/html/search/search.js delete mode 100644 code/web/docs/ams/html/search/search_l.png delete mode 100644 code/web/docs/ams/html/search/search_m.png delete mode 100644 code/web/docs/ams/html/search/search_r.png delete mode 100644 code/web/docs/ams/html/search/variables_24.html delete mode 100644 code/web/docs/ams/html/search/variables_24.js delete mode 100644 code/web/docs/ams/html/sgroup__list_8php.html delete mode 100644 code/web/docs/ams/html/show__queue_8php.html delete mode 100644 code/web/docs/ams/html/show__reply_8php.html delete mode 100644 code/web/docs/ams/html/show__sgroup_8php.html delete mode 100644 code/web/docs/ams/html/show__ticket_8php.html delete mode 100644 code/web/docs/ams/html/show__ticket__info_8php.html delete mode 100644 code/web/docs/ams/html/show__ticket__log_8php.html delete mode 100644 code/web/docs/ams/html/support__group_8php.html delete mode 100644 code/web/docs/ams/html/sync_8php.html delete mode 100644 code/web/docs/ams/html/sync__cron_8php.html delete mode 100644 code/web/docs/ams/html/syncing_8php.html delete mode 100644 code/web/docs/ams/html/tab_a.png delete mode 100644 code/web/docs/ams/html/tab_b.png delete mode 100644 code/web/docs/ams/html/tab_h.png delete mode 100644 code/web/docs/ams/html/tab_s.png delete mode 100644 code/web/docs/ams/html/tabs.css delete mode 100644 code/web/docs/ams/html/ticket_8php.html delete mode 100644 code/web/docs/ams/html/ticket__category_8php.html delete mode 100644 code/web/docs/ams/html/ticket__content_8php.html delete mode 100644 code/web/docs/ams/html/ticket__info_8php.html delete mode 100644 code/web/docs/ams/html/ticket__log_8php.html delete mode 100644 code/web/docs/ams/html/ticket__queue_8php.html delete mode 100644 code/web/docs/ams/html/ticket__queue__handler_8php.html delete mode 100644 code/web/docs/ams/html/ticket__reply_8php.html delete mode 100644 code/web/docs/ams/html/ticket__user_8php.html delete mode 100644 code/web/docs/ams/html/todo.html delete mode 100644 code/web/docs/ams/html/userlist_8php.html delete mode 100644 code/web/docs/ams/html/users_8php.html delete mode 100644 code/web/docs/ams/html/www_2config_8php.html delete mode 100644 code/web/docs/ams/html/www_2html_2autoload_2webusers_8php.html delete mode 100644 code/web/docs/ams/html/www_2html_2inc_2logout_8php.html delete mode 100644 code/web/docs/ams/html/www_2html_2inc_2settings_8php.html delete mode 100644 code/web/docs/ams/html/www_2html_2inc_2show__user_8php.html diff --git a/code/web/docs/ams/doxygen/Doxyfile b/code/web/docs/ams/doxygen/Doxyfile index 8c4cad40f..fc764ef01 100644 --- a/code/web/docs/ams/doxygen/Doxyfile +++ b/code/web/docs/ams/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "Ryzom Account Management System" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.0 +PROJECT_NUMBER = 1.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -721,7 +721,7 @@ WARN_FORMAT = "$file:$line: $text" # messages should be written. If left blank the output is written to standard # error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = warnfile.log #--------------------------------------------------------------------------- # Configuration options related to the input files @@ -733,8 +733,8 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = ../../ryzom_ams \ - info.php +INPUT = ../../../private_php/ams \ + ../../../public_php/ams # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -769,11 +769,8 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../ryzom_ams/ams_lib/smarty \ - ../../ryzom_ams/ams_lib/plugins \ - ../../ryzom_ams/www/html/misc \ - ../../ryzom_ams/www/html/templates_c \ - ../../ryzom_ams/drupal +EXCLUDE = ../../../private_php/ams/smarty \ + ../../../public_php/ams/misc/elfinder-connector # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -894,7 +891,7 @@ USE_MDFILE_AS_MAINPAGE = # also VERBATIM_HEADERS is set to NO. # The default value is: NO. -SOURCE_BROWSER = NO +SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. @@ -2309,4 +2306,3 @@ GENERATE_LEGEND = YES # This tag requires that the tag HAVE_DOT is set to YES. DOT_CLEANUP = YES - diff --git a/code/web/docs/ams/html/add__sgroup_8php.html b/code/web/docs/ams/html/add__sgroup_8php.html deleted file mode 100644 index f525076f5..000000000 --- a/code/web/docs/ams/html/add__sgroup_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_sgroup.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_sgroup.php File Reference
    -
    -
    - - - - -

    -Functions

     add_sgroup ()
     This function is beign used to add a new Support Group to the database.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    add_sgroup ()
    -
    -
    - -

    This function is beign used to add a new Support Group to the database.

    -

    What it will do is check if the user who executed the function is an Admin, if so then it will filter all POST'ed data and use it to create a new Support_Group entry. if not logged in or not an admin, an appropriate redirection to an error page will take place.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/add__user_8php.html b/code/web/docs/ams/html/add__user_8php.html deleted file mode 100644 index 0b89554f9..000000000 --- a/code/web/docs/ams/html/add__user_8php.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php File Reference
    -
    -
    - - - - - -

    -Functions

     add_user ()
     This function is beign used to add a new user to the www database.
     write_user ($newUser)
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    add_user ()
    -
    -
    - -

    This function is beign used to add a new user to the www database.

    -

    it will first check if the sent $_POST variables are valid for registering, if one or more rules are broken (eg the username is too short) the template will be reloaded but this time with the appropriate error messages. If the checking was successful it will call the write_user() function (located in this same file). That function will create a new www user and matching ticket_user. It will also push the newly created user to the shard. In case the shard is offline, the new user will be temporary stored in the ams_querycache, waiting for the sync cron job to update it.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    - -
    -
    - - - - - - - - -
    write_user (newUser)
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/add__user__to__sgroup_8php.html b/code/web/docs/ams/html/add__user__to__sgroup_8php.html deleted file mode 100644 index 878ce18d0..000000000 --- a/code/web/docs/ams/html/add__user__to__sgroup_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user_to_sgroup.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user_to_sgroup.php File Reference
    -
    -
    - - - - -

    -Functions

     add_user_to_sgroup ()
     This function is beign used to add a user to a support group.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    add_user_to_sgroup ()
    -
    -
    - -

    This function is beign used to add a user to a support group.

    -

    It will first check if the user who executed this function is an admin. If the user exists it will try to add it to the supportgroup, in case it's not a mod or admin it will not add it to the group. if the executing user is not an admin or not logged in, the page will be redirected to the error page.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/annotated.html b/code/web/docs/ams/html/annotated.html deleted file mode 100644 index dd7fc058c..000000000 --- a/code/web/docs/ams/html/annotated.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - -Ryzom Account Management System: Data Structures - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    -
    -
    Data Structures
    -
    -
    -
    Here are the data structures with brief descriptions:
    - - - - - - - - - - - - - - - - - - - - - - - -
    AssignedHandles the assigning of a ticket to a user
    DBLayerHandles the database connections
    ForwardedHandles the forwarding of a ticket to a support_group
    Gui_ElementsHelper class for generating gui related elements
    HelpersHelper class for more site specific functions
    In_Support_GroupHandles the linkage of users being in a support group
    Mail_HandlerHandles the mailing functionality
    MyCryptBasic encryption/decryption class
    PaginationHandles returning arrays based on a given pagenumber
    QuerycacheClass for storing changes when shard is offline
    Support_GroupGroups moderators & admins together
    SyncHandler for performing changes when shard is back online after being offline
    TicketClass that handles most ticket related functions
    Ticket_CategoryClass related to the ticket categories
    Ticket_ContentClass that handles the content of a reply
    Ticket_InfoClass that handles additional info sent by ticket creation ingame
    Ticket_LogClass that handles the logging
    Ticket_QueueData class that holds a lot of queries that load specific tickets
    Ticket_Queue_HandlerReturns tickets (queues) that are related in some way
    Ticket_ReplyHandles functions related to replies on tickets
    Ticket_UserUser entry point in the ticket system
    UsersHandles basic user registration & management functions (shard related)
    WebUsersHandles CMS/WWW related functions regarding user management & registration
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/assigned_8php.html b/code/web/docs/ams/html/assigned_8php.html deleted file mode 100644 index 54e26a775..000000000 --- a/code/web/docs/ams/html/assigned_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Assigned
     Handles the assigning of a ticket to a user. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/bc_s.png b/code/web/docs/ams/html/bc_s.png deleted file mode 100644 index e4018628b5b45cb4301037485a29d7d74ac22138..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 zcmV;W0$TlvP)X?0Pv5h+5!wElpi=&YL!gfY!djl#UDdPKy97F|A-deTa@qo3BWh1YQIvzmHR^g zFjV4I6pLB7_*vEZk^%p7c7Bh>0`4r^X#gpJE_Vz9fSHKqclcZaV^k3gX%h+1`u||O zZ+BY?7(R=ayr^kXE=E0Dw=$Ud3VJ?9^Cz@hP?388Cw5>9TloOJ>^KczCgj zns2=|0!a|)Yq3{hjL{xyy7|Tk0N}Pe+g9PUTL!4{#;eUhrNd@!_T<>Vu+35c)h>sq ztgb?(6W3oFLz#%?OMEV@{j#4LuDvjVGZ~6hpQT8li5b0yjvK8c4efl+vSz5)P6 zle78)00_Iv5)&E~hnOdcd}L}i+MU>k+Q8#@KjqJJN`gRj(~)RmNrck9ht@LelPtVO zwp(J;k!T=gC#%o(13-^E+g@aqc()pf{+j|0w)AH*Mq$54UjLv#jV$RYpz3Vjg$$=u z>yjfBQOhL=^@+#4#$l|{~}HZ-?1Yy{lI*$N}*YDC`<{+;>_#gMXZdz4NI00000 LNkvXXu0mjfx86dR diff --git a/code/web/docs/ams/html/change__info_8php.html b/code/web/docs/ams/html/change__info_8php.html deleted file mode 100644 index 4b5bb8b4b..000000000 --- a/code/web/docs/ams/html/change__info_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_info.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_info.php File Reference
    -
    -
    - - - - -

    -Functions

     change_info ()
     This function is beign used to change the users personal info.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    change_info ()
    -
    -
    - -

    This function is beign used to change the users personal info.

    -

    It will first check if the user who executed this function is the person of whom the information is or if it's a mod/admin. If this is not the case the page will be redirected to an error page. afterwards the current info will be loaded, which will be used to determine what to update. After updating the information, the settings template will be reloaded. Errors made by invalid data will be shown also after reloading the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/change__mail_8php.html b/code/web/docs/ams/html/change__mail_8php.html deleted file mode 100644 index 1a177af49..000000000 --- a/code/web/docs/ams/html/change__mail_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_mail.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_mail.php File Reference
    -
    -
    - - - - -

    -Functions

     change_mail ()
     This function is beign used to change the users emailaddress info.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    change_mail ()
    -
    -
    - -

    This function is beign used to change the users emailaddress info.

    -

    It will first check if the user who executed this function is the person of whom the emailaddress is or if it's a mod/admin. If this is not the case the page will be redirected to an error page. The emailaddress will be validated first. If the checking was successful the email will be updated and the settings template will be reloaded. Errors made by invalid data will be shown also after reloading the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/change__password_8php.html b/code/web/docs/ams/html/change__password_8php.html deleted file mode 100644 index a8cc2bbc1..000000000 --- a/code/web/docs/ams/html/change__password_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_password.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_password.php File Reference
    -
    -
    - - - - -

    -Functions

     change_password ()
     This function is beign used to change the users password.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    change_password ()
    -
    -
    - -

    This function is beign used to change the users password.

    -

    It will first check if the user who executed this function is the person of whom the emailaddress is or if it's a mod/admin. If this is not the case the page will be redirected to an error page. If the executing user tries to change someone elses password, he doesn't has to fill in the previous password. The password will be validated first. If the checking was successful the password will be updated and the settings template will be reloaded. Errors made by invalid data will be shown also after reloading the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/change__permission_8php.html b/code/web/docs/ams/html/change__permission_8php.html deleted file mode 100644 index f8eccb214..000000000 --- a/code/web/docs/ams/html/change__permission_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/change_permission.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/change_permission.php File Reference
    -
    -
    - - - - -

    -Functions

     change_permission ()
     This function is beign used to change the permission of a ticket_user.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    change_permission ()
    -
    -
    - -

    This function is beign used to change the permission of a ticket_user.

    -

    It will first check if the user who executed this function is an admin. If this is not the case the page will be redirected to an error page. in case the $_GET['value'] is smaller than 4 and the user whoes permission is being changed is different from the admin(id 1), the change will be executed and the page will redirect to the users profile page.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/change__receivemail_8php.html b/code/web/docs/ams/html/change__receivemail_8php.html deleted file mode 100644 index fbb0d77e5..000000000 --- a/code/web/docs/ams/html/change__receivemail_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_receivemail.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_receivemail.php File Reference
    -
    -
    - - - - -

    -Functions

     change_receivemail ()
     This function is beign used to change the users receiveMail setting.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    change_receivemail ()
    -
    -
    - -

    This function is beign used to change the users receiveMail setting.

    -

    It will first check if the user who executed this function is the person of whom the setting is or if it's a mod/admin. If this is not the case the page will be redirected to an error page. it will check if the new value equals 1 or 0 and it will update the setting and redirect the page again.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classAssigned.html b/code/web/docs/ams/html/classAssigned.html deleted file mode 100644 index e91a4c362..000000000 --- a/code/web/docs/ams/html/classAssigned.html +++ /dev/null @@ -1,529 +0,0 @@ - - - - - -Ryzom Account Management System: Assigned Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    Handles the assigning of a ticket to a user. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     create ()
     creates a new 'assigned' entry.
     delete ()
     deletes an existing 'assigned' entry.
     load ($ticket_id)
     loads the object's attributes.
     getUser ()
     get user attribute of the object.
     getTicket ()
     get ticket attribute of the object.
     setUser ($u)
     set user attribute of the object.
     setTicket ($t)
     set ticket attribute of the object.

    -Static Public Member Functions

    static assignTicket ($user_id, $ticket_id)
     Assigns a ticket to a user or returns an error message.
    static unAssignTicket ($user_id, $ticket_id)
     Unassign a ticket being coupled to a user or return an error message.
    static getUserAssignedToTicket ($ticket_id)
     Get the (external) id of the user assigned to a ticket.
    static isAssigned ($ticket_id, $user_id=0)
     Check if a ticket is already assigned (in case the user_id param is used, it will check if it's assigned to that user)

    -Private Attributes

     $user
     The id of the user being assigned.
     $ticket
     The id of the ticket being assigned.
    -

    Detailed Description

    -

    Handles the assigning of a ticket to a user.

    -

    This is being used to make someone responsible for the handling and solving of a ticket. The idea is that someone can easily assign a ticket to himself and by doing that, he makes aware to the other moderators that he will deal with the ticket in the future.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static assignTicket (user_id,
    ticket_id 
    ) [static]
    -
    -
    - -

    Assigns a ticket to a user or returns an error message.

    -

    It will first check if the ticket isn't already assigned, if not, it will create a new 'assigned' entry.

    -
    Parameters:
    - - - -
    $user_idthe id of the user we want to assign to the ticket
    $ticket_idthe id of the ticket.
    -
    -
    -
    Returns:
    A string, if assigning succeedded "SUCCESS_ASSIGNED" will be returned, else "ALREADY_ASSIGNED" will be returned.
    - -
    -
    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'assigned' entry.

    -

    this method will use the object's attributes for creating a new 'assigned' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - -
    delete ()
    -
    -
    - -

    deletes an existing 'assigned' entry.

    -

    this method will use the object's attributes for deleting an existing 'assigned' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - -
    getTicket ()
    -
    -
    - -

    get ticket attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUser ()
    -
    -
    - -

    get user attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getUserAssignedToTicket (ticket_id) [static]
    -
    -
    - -

    Get the (external) id of the user assigned to a ticket.

    -
    Parameters:
    - - -
    $ticket_idthe Id of the ticket that's being queried
    -
    -
    -
    Returns:
    The (external)id of the user being assigned to the ticket
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static isAssigned (ticket_id,
    user_id = 0 
    ) [static]
    -
    -
    - -

    Check if a ticket is already assigned (in case the user_id param is used, it will check if it's assigned to that user)

    -
    Parameters:
    - - - -
    $ticket_idthe Id of the ticket that's being queried
    $user_idthe id of the user, default parameter = 0, by using a user_id, it will check if that user is assigned to the ticket.
    -
    -
    -
    Returns:
    true in case it's assigned, false in case it isn't.
    - -
    -
    - -
    -
    - - - - - - - - -
    load (ticket_id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a ticket_id, it will put the matching user_id and the ticket_id into the attributes.

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('User' => user_id, 'Ticket' => ticket_id).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTicket (t)
    -
    -
    - -

    set ticket attribute of the object.

    -
    Parameters:
    - - -
    $tinteger id of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setUser (u)
    -
    -
    - -

    set user attribute of the object.

    -
    Parameters:
    - - -
    $uinteger id of the user
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static unAssignTicket (user_id,
    ticket_id 
    ) [static]
    -
    -
    - -

    Unassign a ticket being coupled to a user or return an error message.

    -

    It will first check if the ticket is assigned, if this is indeed the case it will delete the 'assigned' entry.

    -
    Parameters:
    - - - -
    $user_idthe id of the user we want to unassign from the ticket
    $ticket_idthe id of the ticket.
    -
    -
    -
    Returns:
    A string, if unassigning succeedded "SUCCESS_UNASSIGNED" will be returned, else "NOT_ASSIGNED" will be returned.
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $ticket [private]
    -
    -
    - -

    The id of the ticket being assigned.

    - -
    -
    - -
    -
    - - - - -
    $user [private]
    -
    -
    - -

    The id of the user being assigned.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classDBLayer.html b/code/web/docs/ams/html/classDBLayer.html deleted file mode 100644 index 8d405ef53..000000000 --- a/code/web/docs/ams/html/classDBLayer.html +++ /dev/null @@ -1,284 +0,0 @@ - - - - - -Ryzom Account Management System: DBLayer Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    DBLayer Class Reference
    -
    -
    - -

    Handles the database connections. - More...

    - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ($db)
     The constructor.
     executeWithoutParams ($query)
     execute a query that doesn't have any parameters
     execute ($query, $params)
     execute a query that has parameters
     executeReturnId ($query, $params)
     execute a query (an insertion query) that has parameters and return the id of it's insertion

    -Private Attributes

     $PDO
     The PDO object, instantiated by the constructor.
    -

    Detailed Description

    -

    Handles the database connections.

    -

    It uses PDO to connect to the different databases. It will use the argument of the constructor to setup a connection to the database with the matching entry in the $cfg global variable.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - - -
    __construct (db)
    -
    -
    - -

    The constructor.

    -

    Instantiates the PDO object attribute by connecting to the arguments matching database(the db info is stored in the $cfg global var)

    -
    Parameters:
    - - -
    $dbString, the name of the databases entry in the $cfg global var.
    -
    -
    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    execute (query,
    params 
    )
    -
    -
    - -

    execute a query that has parameters

    -
    Parameters:
    - - - -
    $querythe mysql query
    $paramsthe parameters that are being used by the query
    -
    -
    -
    Returns:
    returns a PDOStatement object
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    executeReturnId (query,
    params 
    )
    -
    -
    - -

    execute a query (an insertion query) that has parameters and return the id of it's insertion

    -
    Parameters:
    - - - -
    $querythe mysql query
    $paramsthe parameters that are being used by the query
    -
    -
    -
    Returns:
    returns the id of the last inserted element.
    - -
    -
    - -
    -
    - - - - - - - - -
    executeWithoutParams (query)
    -
    -
    - -

    execute a query that doesn't have any parameters

    -
    Parameters:
    - - -
    $querythe mysql query
    -
    -
    -
    Returns:
    returns a PDOStatement object
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $PDO [private]
    -
    -
    - -

    The PDO object, instantiated by the constructor.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classForwarded.html b/code/web/docs/ams/html/classForwarded.html deleted file mode 100644 index be376db96..000000000 --- a/code/web/docs/ams/html/classForwarded.html +++ /dev/null @@ -1,478 +0,0 @@ - - - - - -Ryzom Account Management System: Forwarded Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    Handles the forwarding of a ticket to a support_group. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     create ()
     creates a new 'forwarded' entry.
     delete ()
     deletes an existing 'forwarded' entry.
     load ($ticket_id)
     loads the object's attributes.
     getGroup ()
     get group attribute of the object.
     getTicket ()
     get ticket attribute of the object.
     setGroup ($g)
     set group attribute of the object.
     setTicket ($t)
     set ticket attribute of the object.

    -Static Public Member Functions

    static forwardTicket ($group_id, $ticket_id)
     Forward a ticket to a group, also removes the previous group where it was forwarded to.
    static getSGroupOfTicket ($ticket_id)
     get the id of the group a ticket is forwarded to.
    static isForwarded ($ticket_id)
     check if the ticket is forwarded

    -Private Attributes

     $group
     The id of the group to which the ticket is being forwarded.
     $ticket
     The id of the ticket being forwarded.
    -

    Detailed Description

    -

    Handles the forwarding of a ticket to a support_group.

    -

    This is being used to transfer tickets to different groups (eg Developers, Website-Team, SupportGroup etc..) The idea is that someone can easily forward a ticket to a group and by doing that, the moderators that are in that group will receive the ticket in their todo queue.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'forwarded' entry.

    -

    this method will use the object's attributes for creating a new 'forwarded' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - -
    delete ()
    -
    -
    - -

    deletes an existing 'forwarded' entry.

    -

    this method will use the object's attributes for deleting an existing 'forwarded' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static forwardTicket (group_id,
    ticket_id 
    ) [static]
    -
    -
    - -

    Forward a ticket to a group, also removes the previous group where it was forwarded to.

    -

    It will first check if the ticket is already forwarded, if that's the case, it will delete that entry. Afterwards it creates the new forward entry

    -
    Parameters:
    - - - -
    $group_idthe id of the support group we want to forward the ticket to.
    $ticket_idthe id of the ticket.
    -
    -
    -
    Returns:
    A string, if assigning succeedded "SUCCESS_FORWARDED" will be returned.
    - -
    -
    - -
    -
    - - - - - - - -
    getGroup ()
    -
    -
    - -

    get group attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getSGroupOfTicket (ticket_id) [static]
    -
    -
    - -

    get the id of the group a ticket is forwarded to.

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket.
    -
    -
    -
    Returns:
    the id of the group
    - -
    -
    - -
    -
    - - - - - - - -
    getTicket ()
    -
    -
    - -

    get ticket attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    static isForwarded (ticket_id) [static]
    -
    -
    - -

    check if the ticket is forwarded

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket.
    -
    -
    -
    Returns:
    returns true if the ticket is forwarded, else return false;
    - -
    -
    - -
    -
    - - - - - - - - -
    load (ticket_id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a ticket_id, it will put the matching group_id and the ticket_id into the attributes.

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('Group' => group_id, 'Ticket' => ticket_id).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setGroup (g)
    -
    -
    - -

    set group attribute of the object.

    -
    Parameters:
    - - -
    $ginteger id of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTicket (t)
    -
    -
    - -

    set ticket attribute of the object.

    -
    Parameters:
    - - -
    $tinteger id of the ticket
    -
    -
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $group [private]
    -
    -
    - -

    The id of the group to which the ticket is being forwarded.

    - -
    -
    - -
    -
    - - - - -
    $ticket [private]
    -
    -
    - -

    The id of the ticket being forwarded.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classGui__Elements.html b/code/web/docs/ams/html/classGui__Elements.html deleted file mode 100644 index 98e30a949..000000000 --- a/code/web/docs/ams/html/classGui__Elements.html +++ /dev/null @@ -1,250 +0,0 @@ - - - - - -Ryzom Account Management System: Gui_Elements Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Gui_Elements Class Reference
    -
    -
    - -

    Helper class for generating gui related elements. - More...

    - - - - - - - - -

    -Static Public Member Functions

    static make_table ($inputList, $funcArray, $fieldArray)
     creates an array of information out of a list of objects which can be used to form a table.
    static make_table_with_key_is_id ($inputList, $funcArray, $idFunction)
     creates an array of information out of a list of objects which can be used to form a table with a key as id.
    static time_elapsed_string ($ptime)
     returns the elapsed time from a timestamp up till now.
    -

    Detailed Description

    -

    Helper class for generating gui related elements.

    -

    This class contains functions that generate data-arrays for tables, or other visual entities

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static make_table (inputList,
    funcArray,
    fieldArray 
    ) [static]
    -
    -
    - -

    creates an array of information out of a list of objects which can be used to form a table.

    -

    The idea of this is that you can pass an array of objects, an array of functions to perform on each object and a name for the index of the returning array to store the result.

    -
    Parameters:
    - - - - -
    $inputListthe list of objects of which we want to make a table.
    $funcArraya list of methods of that object we want to perform.
    $fieldArraya list of strings, that will be used to store our result into.
    -
    -
    -
    Returns:
    an array with the indexes listed in $fieldArray and which holds the results of the methods in $funcArray on each object in the $inputList
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static make_table_with_key_is_id (inputList,
    funcArray,
    idFunction 
    ) [static]
    -
    -
    - -

    creates an array of information out of a list of objects which can be used to form a table with a key as id.

    -

    The idea is comparable to the make_table() function, though this time the results are stored in the index that is returned by the idFunction()

    -
    Parameters:
    - - - - -
    $inputListthe list of objects of which we want to make a table.
    $funcArraya list of methods of that object we want to perform.
    $idFunctiona function that returns an id that will be used as index to store our result
    -
    -
    -
    Returns:
    an array which holds the results of the methods in $funcArray on each object in the $inputList, though thearrays indexes are formed by using the idFunction.
    - -
    -
    - -
    -
    - - - - - - - - -
    static time_elapsed_string (ptime) [static]
    -
    -
    - -

    returns the elapsed time from a timestamp up till now.

    -
    Parameters:
    - - -
    $ptimea timestamp.
    -
    -
    -
    Returns:
    a string in the form of A years, B months, C days, D hours, E minutes, F seconds ago.
    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/gui_elements.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classHelpers.html b/code/web/docs/ams/html/classHelpers.html deleted file mode 100644 index e0109cd70..000000000 --- a/code/web/docs/ams/html/classHelpers.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - - -Ryzom Account Management System: Helpers Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Helpers Class Reference
    -
    -
    - -

    Helper class for more site specific functions. - More...

    - - - - - - - - - - - - - - -

    -Static Public Member Functions

    static loadTemplate ($template, $vars=array(), $returnHTML=false)
     workhorse of the website, it loads the template and shows it or returns th html.
    static create_folders ()
     creates the folders that are needed for smarty.
    static check_if_game_client ()
     check if the http request is sent ingame or not.
    static handle_language ()
     Handles the language specific aspect.
    static outputTime ($time, $str=1)
     Time output function for handling the time display.
    static check_login_ingame ()
     Auto login function for ingame use.
    -

    Detailed Description

    -

    Helper class for more site specific functions.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    static check_if_game_client () [static]
    -
    -
    - -

    check if the http request is sent ingame or not.

    -
    Returns:
    returns true in case it's sent ingame, else false is returned.
    - -
    -
    - -
    -
    - - - - - - - -
    static check_login_ingame () [static]
    -
    -
    - -

    Auto login function for ingame use.

    -

    This function will allow users who access the website ingame, to log in without entering the username and password. It uses the COOKIE entry in the open_ring db. it checks if the cookie sent by the http request matches the one in the db. This cookie in the db is changed everytime the user relogs.

    -
    Returns:
    returns "FALSE" if the cookies didn't match, else it returns an array with the user's id and name.
    - -
    -
    - -
    -
    - - - - - - - -
    static create_folders () [static]
    -
    -
    - -

    creates the folders that are needed for smarty.

    -
    Todo:
    for the drupal module it might be possible that drupal_mkdir needs to be used instead of mkdir, also this should be in the install.php instead.
    - -
    -
    - -
    -
    - - - - - - - -
    static handle_language () [static]
    -
    -
    - -

    Handles the language specific aspect.

    -

    The language can be changed by setting the $_GET['Language'] & $_GET['setLang'] together. This will also change the language entry of the user in the db. Cookies are also being used in case the user isn't logged in.

    -
    Returns:
    returns the parsed content of the language .ini file related to the users language setting.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static loadTemplate (template,
    vars = array (),
    returnHTML = false 
    ) [static]
    -
    -
    - -

    workhorse of the website, it loads the template and shows it or returns th html.

    -

    it uses smarty to load the $template, but before displaying the template it will pass the $vars to smarty. Also based on your language settings a matching array of words & sentences for that page will be loaded. In case the $returnHTML parameter is set to true, it will return the html instead of displaying the template.

    -
    Parameters:
    - - - - -
    $templatethe name of the template(page) that we want to load.
    $varsan array of variables that should be loaded by smarty before displaying or returning the html.
    $returnHTML(default=false) if set to true, the html that should have been displayed, will be returned.
    -
    -
    -
    Returns:
    in case $returnHTML=true, it returns the html of the template being loaded.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static outputTime (time,
    str = 1 
    ) [static]
    -
    -
    - -

    Time output function for handling the time display.

    -
    Returns:
    returns the time in the format specified in the $TIME_FORMAT global variable.
    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classIn__Support__Group.html b/code/web/docs/ams/html/classIn__Support__Group.html deleted file mode 100644 index 206752abf..000000000 --- a/code/web/docs/ams/html/classIn__Support__Group.html +++ /dev/null @@ -1,393 +0,0 @@ - - - - - -Ryzom Account Management System: In_Support_Group Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    In_Support_Group Class Reference
    -
    -
    - -

    Handles the linkage of users being in a support group. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     create ()
     creates a new 'in_support_group' entry.
     delete ()
     deletes an existing 'in_support_group' entry.
     getUser ()
     get user attribute of the object.
     getGroup ()
     get group attribute of the object.
     setUser ($u)
     set user attribute of the object.
     setGroup ($g)
     set group attribute of the object.

    -Static Public Member Functions

    static userExistsInSGroup ($user_id, $group_id)
     Check if user is in in_support_group.

    -Private Attributes

     $user
     The id of the user being in a support group.
     $group
     The id of the support group.
    -

    Detailed Description

    -

    Handles the linkage of users being in a support group.

    -

    Moderators and Admins can be part of a support group, this class offers functionality to check if a link between a user and group is existing.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'in_support_group' entry.

    -

    this method will use the object's attributes for creating a new 'in_support_group' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - -
    delete ()
    -
    -
    - -

    deletes an existing 'in_support_group' entry.

    -

    this method will use the object's attributes for deleting an existing 'in_support_group' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - -
    getGroup ()
    -
    -
    - -

    get group attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUser ()
    -
    -
    - -

    get user attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('User' => user_id, 'Group' => support_groups_id).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setGroup (g)
    -
    -
    - -

    set group attribute of the object.

    -
    Parameters:
    - - -
    $ginteger id of the support group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setUser (u)
    -
    -
    - -

    set user attribute of the object.

    -
    Parameters:
    - - -
    $uinteger id of the user
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static userExistsInSGroup (user_id,
    group_id 
    ) [static]
    -
    -
    - -

    Check if user is in in_support_group.

    -
    Parameters:
    - - - -
    $user_idthe id of the user.
    $group_idthe id of the support group.
    -
    -
    -
    Returns:
    true is returned in case the user is in the support group, else false is returned.
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $group [private]
    -
    -
    - -

    The id of the support group.

    - -
    -
    - -
    -
    - - - - -
    $user [private]
    -
    -
    - -

    The id of the user being in a support group.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classMail__Handler.html b/code/web/docs/ams/html/classMail__Handler.html deleted file mode 100644 index a11be88a0..000000000 --- a/code/web/docs/ams/html/classMail__Handler.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - - -Ryzom Account Management System: Mail_Handler Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    Handles the mailing functionality. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     cron ()
     the cron funtion (workhorse of the mailing system).
     new_message_id ($ticketId)
     creates a new message id for a email about to send.
     get_ticket_id_from_subject ($subject)
     try to fetch the ticket_id out of the subject.
     incoming_mail_handler ($mbox, $i, $group)
     Handles an incomming email Read the content of one email by using imap's functionality.
     decode_utf8 ($str)
     decode utf8
     get_mime_type (&$structure)
     returns the mime type of a structure of a email
     get_part ($stream, $msg_number, $mime_type, $structure=false, $part_number=false)

    -Static Public Member Functions

    static send_ticketing_mail ($receiver, $ticketObj, $content, $type, $sender=0)
     Wrapper for sending emails, creates the content of the email Based on the type of the ticketing mail it will create a specific email, it will use the language.ini files to load the correct language of the email for the receiver.
    static send_mail ($recipient, $subject, $body, $ticket_id=0, $from=NULL)
     send mail function that will add the email to the db.

    -Private Member Functions

     mail_fork ()
     Start a new child process and return the process id this is used because imap might take some time, we dont want the cron parent process waiting on that.

    -Private Attributes

     $db
     db object used by various methods.
    -

    Detailed Description

    -

    Handles the mailing functionality.

    -

    This class covers the reading of the mail boxes of the support_groups, handling those emails, updating tickets accoring to the content & title of the emails, but also the sending of emails after creating a new ticket and when someone else replies on your ticket.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    cron ()
    -
    -
    - -

    the cron funtion (workhorse of the mailing system).

    -

    The cron job will create a child process, which will first send the emails that are in the email table in the database, we use some kind of semaphore (a temp file) to make sure that if the cron job is called multiple times, it wont email those mails multiple times. After this, we will read the mail inboxes of the support groups and the default group using IMAP and we will add new tickets or new replies according to the incoming emails.

    - -
    -
    - -
    -
    - - - - - - - - -
    decode_utf8 (str)
    -
    -
    - -

    decode utf8

    -
    Parameters:
    - - -
    $strstr to be decoded
    -
    -
    -
    Returns:
    decoded string
    - -
    -
    - -
    -
    - - - - - - - - -
    get_mime_type (&$ structure)
    -
    -
    - -

    returns the mime type of a structure of a email

    -
    Parameters:
    - - -
    &$structurethe structure of an email message.
    -
    -
    -
    Returns:
    "TEXT", "MULTIPART","MESSAGE", "APPLICATION", "AUDIO","IMAGE", "VIDEO", "OTHER","TEXT/PLAIN"
    -
    Todo:
    take care of the HTML part of incoming emails.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    get_part (stream,
    msg_number,
    mime_type,
    structure = false,
    part_number = false 
    )
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    get_ticket_id_from_subject (subject)
    -
    -
    - -

    try to fetch the ticket_id out of the subject.

    -

    The subject should have a substring of the form [Ticket #ticket_id], where ticket_id should be the integer ID of the ticket.

    -
    Parameters:
    - - -
    $subjectthe subject of an incomming email.
    -
    -
    -
    Returns:
    if the ticket's id is succesfully parsed, it will return the ticket_id, else it returns 0.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    incoming_mail_handler (mbox,
    i,
    group 
    )
    -
    -
    - -

    Handles an incomming email Read the content of one email by using imap's functionality.

    -

    If a ticket id is found inside the message_id or else in the subject line, then a reply will be added (if the email is not being sent from the authors email address it won't be added though and a warning will be sent to both parties). If no ticket id is found, then a new ticket will be created.

    -
    Parameters:
    - - - - -
    $mboxa mailbox object
    $ithe email's id in the mailbox (integer)
    $groupthe group object that owns the inbox.
    -
    -
    -
    Returns:
    a string based on the found ticket i and timestamp (will be used to store a copy of the email locally)
    - -
    -
    - -
    -
    - - - - - - - -
    mail_fork () [private]
    -
    -
    - -

    Start a new child process and return the process id this is used because imap might take some time, we dont want the cron parent process waiting on that.

    -
    Returns:
    return the child process id
    - -
    -
    - -
    -
    - - - - - - - - -
    new_message_id (ticketId)
    -
    -
    - -

    creates a new message id for a email about to send.

    -
    Parameters:
    - - -
    $ticketIdthe ticket id of the ticket that is mentioned in the email.
    -
    -
    -
    Returns:
    returns a string, that consist out of some variable parts, a consistent part and the ticket_id. The ticket_id will be used lateron, if someone replies on the message, to see to which ticket the reply should be added.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static send_mail (recipient,
    subject,
    body,
    ticket_id = 0,
    from = NULL 
    ) [static]
    -
    -
    - -

    send mail function that will add the email to the db.

    -

    this function is being used by the send_ticketing_mail() function. It adds the email as an entry to the `email` table in the database, which will be sent later on when we run the cron job.

    -
    Parameters:
    - - - - - - -
    $recipientif integer, then it refers to the id of the user to whom we want to mail, if it's a string(email-address) then we will use that.
    $subjectthe subject of the email
    $bodythe body of the email
    $ticket_idthe id of the ticket
    $fromthe sending support_group's id (NULL in case the default group is sending))
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static send_ticketing_mail (receiver,
    ticketObj,
    content,
    type,
    sender = 0 
    ) [static]
    -
    -
    - -

    Wrapper for sending emails, creates the content of the email Based on the type of the ticketing mail it will create a specific email, it will use the language.ini files to load the correct language of the email for the receiver.

    -

    Also if the $TICKET_MAILING_SUPPORT is set to false or if the user's personal 'ReceiveMail' entry is set to false then no mail will be sent.

    -
    Parameters:
    - - - - - - -
    $receiverif integer, then it refers to the id of the user to whom we want to mail, if it's a string(email-address) then we will use that.
    $ticketObjthe ticket object itself, this is being used for including ticket related information into the email.
    $contentthe content of a reply or new ticket
    $typeREPLY, NEW, WARNAUTHOR, WARNSENDER, WARNUNKNOWNSENDER
    $sender(default = 0 (if it is not forwarded)) else use the id of the support group to which the ticket is currently forwarded, the support groups email address will be used to send the ticket.
    -
    -
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $db [private]
    -
    -
    - -

    db object used by various methods.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classMyCrypt.html b/code/web/docs/ams/html/classMyCrypt.html deleted file mode 100644 index f08d22b88..000000000 --- a/code/web/docs/ams/html/classMyCrypt.html +++ /dev/null @@ -1,327 +0,0 @@ - - - - - -Ryzom Account Management System: MyCrypt Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    Basic encryption/decryption class. - More...

    - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ($cryptinfo)
     constructor.
     encrypt ($data)
     encrypts by using the given enc_method and hash_method.
     decrypt ($edata)
     decrypts by using the given enc_method and hash_method.

    -Static Private Member Functions

    static hashIV ($key, $method, $iv_size)
     hashes the key by using a hash method specified.
    static check_methods ($enc, $hash)
     checks if the encryption and hash methods are supported

    -Private Attributes

     $config
     array that should contain the enc_method & hash_method & key
    -

    Detailed Description

    -

    Basic encryption/decryption class.

    -

    We use this class atm for encrypting & decrypting the imap passwords.

    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - - -
    __construct (cryptinfo)
    -
    -
    - -

    constructor.

    -

    loads the config array with the given argument.

    -
    Parameters:
    - - -
    $cryptinfoan array containing the info needed to encrypt & decrypt.(enc_method & hash_method & key)
    -
    -
    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static check_methods (enc,
    hash 
    ) [static, private]
    -
    -
    - -

    checks if the encryption and hash methods are supported

    -
    Parameters:
    - - - -
    $encthe encryption method.
    $hashthe hash method.
    -
    -
    -
    Exceptions:
    - - -
    Exceptionin case a method is not supported.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    decrypt (edata)
    -
    -
    - -

    decrypts by using the given enc_method and hash_method.

    -
    Parameters:
    - - -
    $edatathe encrypted string that we want to decrypt
    -
    -
    -
    Returns:
    the decrypted string.
    - -
    -
    - -
    -
    - - - - - - - - -
    encrypt (data)
    -
    -
    - -

    encrypts by using the given enc_method and hash_method.

    -

    It will first check if the methods are supported, if not it will throw an error, if so it will encrypt the $data

    -
    Parameters:
    - - -
    $datathe string that we want to encrypt.
    -
    -
    -
    Returns:
    the encrypted string.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static hashIV (key,
    method,
    iv_size 
    ) [static, private]
    -
    -
    - -

    hashes the key by using a hash method specified.

    -
    Parameters:
    - - - - -
    $keythe key to be hashed
    $methodthe metho of hashing to be used
    $iv_sizethe size of the initialization vector.
    -
    -
    -
    Returns:
    return the hashed key up till the size of the iv_size param.
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $config [private]
    -
    -
    - -

    array that should contain the enc_method & hash_method & key

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mycrypt.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classPagination.html b/code/web/docs/ams/html/classPagination.html deleted file mode 100644 index 3623ac807..000000000 --- a/code/web/docs/ams/html/classPagination.html +++ /dev/null @@ -1,368 +0,0 @@ - - - - - -Ryzom Account Management System: Pagination Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Pagination Class Reference
    -
    -
    - -

    Handles returning arrays based on a given pagenumber. - More...

    - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ($query, $db, $nrDisplayed, $resultClass, $params=array())
     Constructor.
     getLast ()
     return the number of the 'last' object attribute
     getCurrent ()
     return the number of the 'current' object attribute
     getElements ()
     return the elements array of the object
     getAmountOfRows ()
     return total amount of rows for the original query
     getLinks ($nrOfLinks)
     return the page links.

    -Private Attributes

     $element_array
     Array containing the elements that are extracted for that specific page number.
     $last
     The last page number.
     $current
     The current page number (read from $_GET['pagenum'])
     $amountOfRows
     Total amount of rows that a query would return (if no limits would be used)
    -

    Detailed Description

    -

    Handles returning arrays based on a given pagenumber.

    -

    By specifing a $_GET['pagenum'] or if not(page = 1 will be used) a few elements from a specific query will be returned. Not all elements have to be loaded into objects, only the elements needed for that specific page, this is a good thing performance wise. This is done by passign the query to the constructor and specifying how many you want to display.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    __construct (query,
    db,
    nrDisplayed,
    resultClass,
    params = array() 
    )
    -
    -
    - -

    Constructor.

    -

    will fetch the correct elements that match to a specific page (specified by the $_GET['pagenum'] variable). The query has to be passed as a string to the function that way it will only load the specific elements that are related to the pagenumber. The $params, parameter is optional and is used to pass the parameters for the query. The result class will be used to instantiate the found elements with, their set() function will be called. The class its getters can be later used to get the info out of the object.

    -
    Parameters:
    - - - - - - -
    $querythe query to be paginated
    $dbthe db on which the query should be performed
    $nrDisplayedthe amount of elements that should be displayed /page
    $resultClassthe elements that should be returned should be of that specific class.
    $paramsthe parameters used by the query (optional)
    -
    -
    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    getAmountOfRows ()
    -
    -
    - -

    return total amount of rows for the original query

    -
    Returns:
    the total amount of rows for the original query
    - -
    -
    - -
    -
    - - - - - - - -
    getCurrent ()
    -
    -
    - -

    return the number of the 'current' object attribute

    -
    Returns:
    the number of the current page
    - -
    -
    - -
    -
    - - - - - - - -
    getElements ()
    -
    -
    - -

    return the elements array of the object

    -
    Returns:
    the elements of a specific page (these are instantiations of the class passed as parameter ($resultClass) to the constructor)
    - -
    -
    - -
    -
    - - - - - - - -
    getLast ()
    -
    -
    - -

    return the number of the 'last' object attribute

    -
    Returns:
    the number of the last page
    - -
    -
    - -
    -
    - - - - - - - - -
    getLinks (nrOfLinks)
    -
    -
    - -

    return the page links.

    -

    (for browsing the pages, placed under a table for example) the $nrOfLinks parameter specifies the amount of links you want to return. it will show the links closest to the current page on both sides (in case one side can't show more, it will show more on the other side)

    -
    Returns:
    an array of integerswhich refer to the clickable pagenumbers for browsing other pages.
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $amountOfRows [private]
    -
    -
    - -

    Total amount of rows that a query would return (if no limits would be used)

    - -
    -
    - -
    -
    - - - - -
    $current [private]
    -
    -
    - -

    The current page number (read from $_GET['pagenum'])

    - -
    -
    - -
    -
    - - - - -
    $element_array [private]
    -
    -
    - -

    Array containing the elements that are extracted for that specific page number.

    - -
    -
    - -
    -
    - - - - -
    $last [private]
    -
    -
    - -

    The last page number.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/pagination.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classQuerycache.html b/code/web/docs/ams/html/classQuerycache.html deleted file mode 100644 index 320125d43..000000000 --- a/code/web/docs/ams/html/classQuerycache.html +++ /dev/null @@ -1,485 +0,0 @@ - - - - - -Ryzom Account Management System: Querycache Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Querycache Class Reference
    -
    -
    - -

    class for storing changes when shard is offline. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     load_With_SID ($id)
     loads the object's attributes.
     update ()
     updates the entry.
     getSID ()
     get SID attribute of the object.
     getType ()
     get type attribute of the object.
     getQuery ()
     get query attribute of the object.
     getDb ()
     get db attribute of the object.
     setSID ($s)
     set SID attribute of the object.
     setType ($t)
     set type attribute of the object.
     setQuery ($q)
     set query attribute of the object.
     setDb ($d)
     set db attribute of the object.

    -Private Attributes

     $SID
     The queries ID.
     $type
     The type of query.
     $query
     The query itself (json encoded)
     $db
     the db where the query should be performed
    -

    Detailed Description

    -

    class for storing changes when shard is offline.

    -
    Todo:
    make sure that the querycache class is being used by the sync class and also for inserting the queries themselfs into it. Atm this class isn't used yet if I remember correctly
    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    getDb ()
    -
    -
    - -

    get db attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getQuery ()
    -
    -
    - -

    get query attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getSID ()
    -
    -
    - -

    get SID attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getType ()
    -
    -
    - -

    get type attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_SID (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a SID as parameter

    -
    Parameters:
    - - -
    $idthe id of the querycaches row
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('SID' => sid, 'type' => type, 'query' => query, 'db' => db).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setDb (d)
    -
    -
    - -

    set db attribute of the object.

    -
    Parameters:
    - - -
    $dthe name of the database in the config global var that we want to use.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setQuery (q)
    -
    -
    - -

    set query attribute of the object.

    -
    Parameters:
    - - -
    $qquery string
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setSID (s)
    -
    -
    - -

    set SID attribute of the object.

    -
    Parameters:
    - - -
    $sinteger id
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setType (t)
    -
    -
    - -

    set type attribute of the object.

    -
    Parameters:
    - - -
    $ttype of the query, could be changePassword, changePermissions, changeEmail, createUser
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    updates the entry.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $db [private]
    -
    -
    - -

    the db where the query should be performed

    - -
    -
    - -
    -
    - - - - -
    $query [private]
    -
    -
    - -

    The query itself (json encoded)

    - -
    -
    - -
    -
    - - - - -
    $SID [private]
    -
    -
    - -

    The queries ID.

    - -
    -
    - -
    -
    - - - - -
    $type [private]
    -
    -
    - -

    The type of query.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classSupport__Group.html b/code/web/docs/ams/html/classSupport__Group.html deleted file mode 100644 index badfc9e03..000000000 --- a/code/web/docs/ams/html/classSupport__Group.html +++ /dev/null @@ -1,1082 +0,0 @@ - - - - - -Ryzom Account Management System: Support_Group Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    groups moderators & admins together. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     create ()
     creates a new 'support_group' entry.
     load_With_SGroupId ($id)
     loads the object's attributes.
     update ()
     update the objects attributes to the db.
     delete ()
     deletes an existing 'support_group' entry.
     getSGroupId ()
     get sGroupId attribute of the object.
     getName ()
     get name attribute of the object.
     getTag ()
     get tag attribute of the object.
     getGroupEmail ()
     get groupEmail attribute of the object.
     getIMAP_MailServer ()
     get iMAP_MailServer attribute of the object.
     getIMAP_Username ()
     get iMAP_Username attribute of the object.
     getIMAP_Password ()
     get iMAP_Password attribute of the object.
     setSGroupId ($id)
     set sGroupId attribute of the object.
     setName ($n)
     set name attribute of the object.
     setTag ($t)
     set tag attribute of the object.
     setGroupEmail ($ge)
     set groupEmail attribute of the object.
     setIMAP_MailServer ($ms)
     set iMAP_MailServer attribute of the object.
     setIMAP_Username ($u)
     set iMAP_Username attribute of the object.
     setIMAP_Password ($p)
     set iMAP_Password attribute of the object.

    -Static Public Member Functions

    static getGroup ($id)
     return a specific support_group object.
    static getGroups ()
     return all support_group objects.
    static createSupportGroup ($name, $tag, $groupemail, $imap_mailserver, $imap_username, $imap_password)
     Wrapper for creating a support group.
    static supportGroup_EntryNotExists ($name, $tag)
     check if support group name/tag doesn't exist yet.
    static supportGroup_Exists ($id)
     check if support group entry coupled to a given id exist or not.
    static constr_SGroupId ($id)
     construct an object based on the SGroupId.
    static getAllUsersOfSupportGroup ($group_id)
     get list of all users that are enlisted to a support group.
    static deleteSupportGroup ($group_id)
     wrapper for deleting a support group.
    static deleteUserOfSupportGroup ($user_id, $group_id)
     wrapper for deleting a user that's in a specified support group.
    static addUserToSupportGroup ($user_id, $group_id)
     wrapper for adding a user to a specified support group.
    static getAllSupportGroups ()
     return all support_group objects.

    -Private Attributes

     $sGroupId
     The id of the support group.
     $name
     The name of the support group.
     $tag
     The tag of the support group, a tag is max 4 letters big, and will be used in the future as easy reference to indicate what group it is refered to (eg [DEV])
     $groupEmail
     The email address of the group.
     $iMAP_MailServer
     The imap server connection string.
     $iMAP_Username
     The imap username of the account.
     $iMAP_Password
     The imap matching password.
    -

    Detailed Description

    -

    groups moderators & admins together.

    -

    A Support Group is a group of people with the same skills or knowledge. A typical example will be the (Developers group, webteam group, management, etc..) The idea is that tickets can be forwarded to a group of persons that might be able to answer that specific question. Support Groups are also the key of handling the emails, because the email addresses of the support groups will be used by the Mail_Handler class.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static addUserToSupportGroup (user_id,
    group_id 
    ) [static]
    -
    -
    - -

    wrapper for adding a user to a specified support group.

    -

    We will first check if the group really exists, if not than "GROUP_NOT_EXISING" will be returned. Afterwards we will check if the user exists in the support group, if so "ALREADY_ADDED" will be returned. Else the user will be added to the in_support_group table and "SUCCESS" will be returned.

    -
    Parameters:
    - - - -
    $user_idthe id of the user we want to add to the group.
    $group_idthe id of the group the user wants to be in
    -
    -
    -
    Returns:
    a string (SUCCESS, ALREADY_ADDED or GROUP_NOT_EXISTING)
    - -
    -
    - -
    -
    - - - - - - - - -
    static constr_SGroupId (id) [static]
    -
    -
    - -

    construct an object based on the SGroupId.

    -
    Parameters:
    - - -
    $idthe id of the group we want to construct
    -
    -
    -
    Returns:
    the constructed support group object
    - -
    -
    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'support_group' entry.

    -

    this method will use the object's attributes for creating a new 'support_group' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static createSupportGroup (name,
    tag,
    groupemail,
    imap_mailserver,
    imap_username,
    imap_password 
    ) [static]
    -
    -
    - -

    Wrapper for creating a support group.

    -

    It will check if the support group doesn't exist yet, if the tag or name already exists then NAME_TAKEN or TAG_TAKEN will be returned. If the name is bigger than 20 characters or smaller than 4 and the tag greater than 7 or smaller than 2 a SIZE_ERROR will be returned. Else it will return SUCCESS

    -
    Returns:
    a string that specifies if it was a success or not (SUCCESS, SIZE_ERROR, NAME_TAKEN or TAG_TAKEN )
    - -
    -
    - -
    -
    - - - - - - - -
    delete ()
    -
    -
    - -

    deletes an existing 'support_group' entry.

    -

    this method will use the object's attributes for deleting an existing 'support_group' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - - -
    static deleteSupportGroup (group_id) [static]
    -
    -
    - -

    wrapper for deleting a support group.

    -

    We will first check if the group really exists, if not than "GROUP_NOT_EXISING" will be returned.

    -
    Parameters:
    - - -
    $group_idthe id of the group we want to delete
    -
    -
    -
    Returns:
    an array of ticket_user objects that are in the support group.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static deleteUserOfSupportGroup (user_id,
    group_id 
    ) [static]
    -
    -
    - -

    wrapper for deleting a user that's in a specified support group.

    -

    We will first check if the group really exists, if not than "GROUP_NOT_EXISING" will be returned. Afterwards we will check if the user exists in the support group, if not "USER_NOT_IN_GROUP" will be returned. Else the users entry in the in_support_group table will be deleted and "SUCCESS" will be returned.

    -
    Parameters:
    - - - -
    $user_idthe id of the user we want to remove out of the group.
    $group_idthe id of the group the user should be in
    -
    -
    -
    Returns:
    a string (SUCCESS, USER_NOT_IN_GROUP or GROUP_NOT_EXISTING)
    - -
    -
    - -
    -
    - - - - - - - -
    static getAllSupportGroups () [static]
    -
    -
    - -

    return all support_group objects.

    -
    Returns:
    an array containing all support_group objects.
    -
    Deprecated:
    should be removed in the future, because getGroups does the same.
    - -
    -
    - -
    -
    - - - - - - - - -
    static getAllUsersOfSupportGroup (group_id) [static]
    -
    -
    - -

    get list of all users that are enlisted to a support group.

    -
    Parameters:
    - - -
    $group_idthe id of the group we want to query
    -
    -
    -
    Returns:
    an array of ticket_user objects that are in the support group.
    - -
    -
    - -
    -
    - - - - - - - - -
    static getGroup (id) [static]
    -
    -
    - -

    return a specific support_group object.

    -
    Parameters:
    - - -
    $idthe id of the support group that we want to return
    -
    -
    -
    Returns:
    a support_group object.
    - -
    -
    - -
    -
    - - - - - - - -
    getGroupEmail ()
    -
    -
    - -

    get groupEmail attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    static getGroups () [static]
    -
    -
    - -

    return all support_group objects.

    -
    Returns:
    an array containing all support_group objects.
    - -
    -
    - -
    -
    - - - - - - - -
    getIMAP_MailServer ()
    -
    -
    - -

    get iMAP_MailServer attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getIMAP_Password ()
    -
    -
    - -

    get iMAP_Password attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getIMAP_Username ()
    -
    -
    - -

    get iMAP_Username attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getName ()
    -
    -
    - -

    get name attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getSGroupId ()
    -
    -
    - -

    get sGroupId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTag ()
    -
    -
    - -

    get tag attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_SGroupId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a group id, it will put the matching groups attributes in the object.

    -
    Parameters:
    - - -
    $idthe id of the support group that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('SGroupId' => groupid, 'Name' => name, 'Tag' => tag, 'GroupEmail' => mail, 'IMAP_MailServer' => server, 'IMAP_Username' => username,'IMAP_Password' => pass).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setGroupEmail (ge)
    -
    -
    - -

    set groupEmail attribute of the object.

    -
    Parameters:
    - - -
    $geemail of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setIMAP_MailServer (ms)
    -
    -
    - -

    set iMAP_MailServer attribute of the object.

    -
    Parameters:
    - - -
    $msmailserver of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setIMAP_Password (p)
    -
    -
    - -

    set iMAP_Password attribute of the object.

    -
    Parameters:
    - - -
    $pimap password of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setIMAP_Username (u)
    -
    -
    - -

    set iMAP_Username attribute of the object.

    -
    Parameters:
    - - -
    $uimap username of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setName (n)
    -
    -
    - -

    set name attribute of the object.

    -
    Parameters:
    - - -
    $nname of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setSGroupId (id)
    -
    -
    - -

    set sGroupId attribute of the object.

    -
    Parameters:
    - - -
    $idinteger id of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTag (t)
    -
    -
    - -

    set tag attribute of the object.

    -
    Parameters:
    - - -
    $ttag of the group
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static supportGroup_EntryNotExists (name,
    tag 
    ) [static]
    -
    -
    - -

    check if support group name/tag doesn't exist yet.

    -
    Parameters:
    - - - -
    $namethe name of the group we want to check
    $tagthe tag of the group we want to check
    -
    -
    -
    Returns:
    if name is already taken return NAME_TAKEN, else if tag is already taken return TAG_TAKEN, else return success.
    - -
    -
    - -
    -
    - - - - - - - - -
    static supportGroup_Exists (id) [static]
    -
    -
    - -

    check if support group entry coupled to a given id exist or not.

    -
    Parameters:
    - - -
    $idthe id of the group we want to check
    -
    -
    -
    Returns:
    true or false.
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    update the objects attributes to the db.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $groupEmail [private]
    -
    -
    - -

    The email address of the group.

    - -
    -
    - -
    -
    - - - - -
    $iMAP_MailServer [private]
    -
    -
    - -

    The imap server connection string.

    - -
    -
    - -
    -
    - - - - -
    $iMAP_Password [private]
    -
    -
    - -

    The imap matching password.

    - -
    -
    - -
    -
    - - - - -
    $iMAP_Username [private]
    -
    -
    - -

    The imap username of the account.

    - -
    -
    - -
    -
    - - - - -
    $name [private]
    -
    -
    - -

    The name of the support group.

    - -
    -
    - -
    -
    - - - - -
    $sGroupId [private]
    -
    -
    - -

    The id of the support group.

    - -
    -
    - -
    -
    - - - - -
    $tag [private]
    -
    -
    - -

    The tag of the support group, a tag is max 4 letters big, and will be used in the future as easy reference to indicate what group it is refered to (eg [DEV])

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classSync.html b/code/web/docs/ams/html/classSync.html deleted file mode 100644 index a8dd8f45e..000000000 --- a/code/web/docs/ams/html/classSync.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Ryzom Account Management System: Sync Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Sync Class Reference
    -
    -
    - -

    handler for performing changes when shard is back online after being offline. - More...

    - - - - -

    -Static Public Member Functions

    static syncdata ()
     performs the actions listed in the querycache.
    -

    Detailed Description

    -

    handler for performing changes when shard is back online after being offline.

    -

    the sync class is responsible for the syncdata function, which will synchronise the website with the shard (when the shard is offline, users can still change their password, email or even register)

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    static syncdata () [static]
    -
    -
    - -

    performs the actions listed in the querycache.

    -

    All entries in the querycache will be read and performed depending on their type. This is done because the shard could have been offline and we want changes made on the website (which is still online) to eventually hit the shard. These changes are: createPermissions, createUser, change_pass, change_mail

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket.html b/code/web/docs/ams/html/classTicket.html deleted file mode 100644 index 939c11d57..000000000 --- a/code/web/docs/ams/html/classTicket.html +++ /dev/null @@ -1,1429 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    class that handles most ticket related functions. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     create ()
     creates a new 'ticket' entry.
     load_With_TId ($id)
     loads the object's attributes.
     update ()
     update the objects attributes to the db.
     hasInfo ()
     check if a ticket has a ticket_info page or not.
     getTId ()
     get tId attribute of the object.
     getTimestamp ()
     get timestamp attribute of the object in the format defined in the outputTime function of the Helperclass.
     getTitle ()
     get title attribute of the object.
     getStatus ()
     get status attribute of the object.
     getStatusText ()
     get status attribute of the object in the form of text (string).
     getCategoryName ()
     get category attribute of the object in the form of text (string).
     getQueue ()
     get queue attribute of the object.
     getTicket_Category ()
     get ticket_category attribute of the object (int).
     getAuthor ()
     get author attribute of the object (int).
     getPriority ()
     get priority attribute of the object (int).
     getPriorityText ()
     get priority attribute of the object in the form of text (string).
     getAssigned ()
     get the user assigned to the ticket.
     getForwardedGroupName ()
     get the name of the support group to whom the ticket is forwarded or return 0 in case not forwarded.
     getForwardedGroupId ()
     get the id of the support group to whom the ticket is forwarded or return 0 in case not forwarded.
     setTId ($id)
     set tId attribute of the object.
     setTimestamp ($ts)
     set timestamp attribute of the object.
     setTitle ($t)
     set title attribute of the object.
     setStatus ($s)
     set status attribute of the object.
     setQueue ($q)
     set queue attribute of the object.
     setTicket_Category ($tc)
     set ticket_category attribute of the object.
     setAuthor ($a)
     set author attribute of the object.
     setPriority ($p)
     set priority attribute of the object.

    -Static Public Member Functions

    static ticketExists ($id)
     check if a ticket exists.
    static getStatusArray ()
     return an array of the possible statuses
    static getPriorityArray ()
     return an array of the possible priorities
    static getEntireTicket ($id, $view_as_admin)
     return an entire ticket.
    static getTicketsOf ($author)
     return all tickets of a specific user.
    static create_Ticket ($title, $content, $category, $author, $real_author, $for_support_group=0, $extra_info=0)
     function that creates a new ticket.
    static updateTicketStatus ($ticket_id, $newStatus, $author)
     updates the ticket's status.
    static updateTicketStatusAndPriority ($ticket_id, $newStatus, $newPriority, $author)
     updates the ticket's status & priority.
    static getLatestReply ($ticket_id)
     return the latest reply of a ticket
    static createReply ($content, $author, $ticket_id, $hidden)
     create a new reply for a ticket.
    static assignTicket ($user_id, $ticket_id)
     assign a ticket to a user.
    static unAssignTicket ($user_id, $ticket_id)
     unassign a ticket of a user.
    static forwardTicket ($user_id, $ticket_id, $group_id)
     forward a ticket to a specific support group.

    -Private Attributes

     $tId
     The id of ticket.
     $timestamp
     Timestamp of the ticket.
     $title
     Title of the ticket.
     $status
     Status of the ticket (0 = waiting on user reply, 1 = waiting on support, (2= not used atm), 3 = closed.
     $queue
     (not in use atm)
     $ticket_category
     the id of the category belonging to the ticket
     $author
     The ticket_users id.
     $priority
     The priority of the ticket where 0 = low, 3= supadupahigh.
    -

    Detailed Description

    -

    class that handles most ticket related functions.

    -

    the ticket class is used for most ticketing related functions, it also holds some wrapper functions.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static assignTicket (user_id,
    ticket_id 
    ) [static]
    -
    -
    - -

    assign a ticket to a user.

    -

    Checks if the ticket exists, if so then it will try to assign the user to it, a log entry will be written about this.

    -
    Parameters:
    - - - -
    $user_idthe id of user trying to be assigned to the ticket.
    $ticket_idthe id of the ticket that we try to assign to the user.
    -
    -
    -
    Returns:
    SUCCESS_ASSIGNED, TICKET_NOT_EXISTING or ALREADY_ASSIGNED
    - -
    -
    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'ticket' entry.

    -

    this method will use the object's attributes for creating a new 'ticket' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static create_Ticket (title,
    content,
    category,
    author,
    real_author,
    for_support_group = 0,
    extra_info = 0 
    ) [static]
    -
    -
    - -

    function that creates a new ticket.

    -

    A new ticket will be created, in case the extra_info != 0 and the http request came from ingame, then a ticket_info page will be created. A log entry will be written, depending on the $real_authors value. In case the for_support_group parameter is set, the ticket will be forwarded immediately. Also the mail handler will create a new email that will be sent to the author to notify him that his ticket is freshly created.

    -
    Parameters:
    - - - - - - - - -
    $titlethe title we want to give to the ticket.
    $contentthe content we want to give to the starting post of the ticket.
    $categorythe id of the category that should be related to the ticket.
    $authorthe person who's id will be stored in the database as creator of the ticket.
    $real_authorshould be the same id, or a moderator/admin who creates a ticket for another user (this is used for logging purposes).
    $for_support_groupin case you directly want to forward the ticket after creating it. (default value = 0 = don't forward)
    $extra_infoused for creating an ticket_info page related to the ticket, this only happens when the ticket is made ingame.
    -
    -
    -
    Returns:
    the created tickets id.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static createReply (content,
    author,
    ticket_id,
    hidden 
    ) [static]
    -
    -
    - -

    create a new reply for a ticket.

    -

    A reply will only be added if the content isn't empty and if the ticket isn't closed. The ticket creator will be notified by email that someone else replied on his ticket.

    -
    Parameters:
    - - - - - -
    $contentthe content of the reply
    $authorthe author of the reply
    $ticket_idthe id of the ticket to which we want to add the reply.
    $hiddenboolean that specifies if the reply should only be shown to mods/admins or all users.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static forwardTicket (user_id,
    ticket_id,
    group_id 
    ) [static]
    -
    -
    - -

    forward a ticket to a specific support group.

    -

    Checks if the ticket exists, if so then it will try to forward the ticket to the support group specified, a log entry will be written about this. if no log entry should be written then the user_id should be 0, else te $user_id will be used in the log to specify who forwarded it.

    -
    Parameters:
    - - - - -
    $user_idthe id of user trying to forward the ticket.
    $ticket_idthe id of the ticket that we try to forward to a support group.
    $group_idthe id of the support group.
    -
    -
    -
    Returns:
    SUCCESS_FORWARDED, TICKET_NOT_EXISTING or INVALID_SGROUP
    - -
    -
    - -
    -
    - - - - - - - -
    getAssigned ()
    -
    -
    - -

    get the user assigned to the ticket.

    -

    or return 0 in case not assigned.

    - -
    -
    - -
    -
    - - - - - - - -
    getAuthor ()
    -
    -
    - -

    get author attribute of the object (int).

    - -
    -
    - -
    -
    - - - - - - - -
    getCategoryName ()
    -
    -
    - -

    get category attribute of the object in the form of text (string).

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static getEntireTicket (id,
    view_as_admin 
    ) [static]
    -
    -
    - -

    return an entire ticket.

    -

    returns the ticket object and an array of all replies to that ticket.

    -
    Parameters:
    - - - -
    $idthe id of the ticket.
    $view_as_admintrue if the viewer of the ticket is a mod, else false (depending on this it will also show the hidden comments)
    -
    -
    -
    Returns:
    an array containing the 'ticket_obj' and a 'reply_array', which is an array containing all replies to that ticket.
    - -
    -
    - -
    -
    - - - - - - - -
    getForwardedGroupId ()
    -
    -
    - -

    get the id of the support group to whom the ticket is forwarded or return 0 in case not forwarded.

    - -
    -
    - -
    -
    - - - - - - - -
    getForwardedGroupName ()
    -
    -
    - -

    get the name of the support group to whom the ticket is forwarded or return 0 in case not forwarded.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getLatestReply (ticket_id) [static]
    -
    -
    - -

    return the latest reply of a ticket

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket.
    -
    -
    -
    Returns:
    a ticket_reply object.
    - -
    -
    - -
    -
    - - - - - - - -
    getPriority ()
    -
    -
    - -

    get priority attribute of the object (int).

    - -
    -
    - -
    -
    - - - - - - - -
    static getPriorityArray () [static]
    -
    -
    - -

    return an array of the possible priorities

    -
    Returns:
    an array containing the string values that represent the different priorities.
    - -
    -
    - -
    -
    - - - - - - - -
    getPriorityText ()
    -
    -
    - -

    get priority attribute of the object in the form of text (string).

    - -
    -
    - -
    -
    - - - - - - - -
    getQueue ()
    -
    -
    - -

    get queue attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getStatus ()
    -
    -
    - -

    get status attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    static getStatusArray () [static]
    -
    -
    - -

    return an array of the possible statuses

    -
    Returns:
    an array containing the string values that represent the different statuses.
    - -
    -
    - -
    -
    - - - - - - - -
    getStatusText ()
    -
    -
    - -

    get status attribute of the object in the form of text (string).

    - -
    -
    - -
    -
    - - - - - - - -
    getTicket_Category ()
    -
    -
    - -

    get ticket_category attribute of the object (int).

    - -
    -
    - -
    -
    - - - - - - - - -
    static getTicketsOf (author) [static]
    -
    -
    - -

    return all tickets of a specific user.

    -

    an array of all tickets created by a specific user are returned by this function.

    -
    Parameters:
    - - -
    $authorthe id of the user of whom we want all tickets from.
    -
    -
    -
    Returns:
    an array containing all ticket objects related to a user.
    - -
    -
    - -
    -
    - - - - - - - -
    getTId ()
    -
    -
    - -

    get tId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTimestamp ()
    -
    -
    - -

    get timestamp attribute of the object in the format defined in the outputTime function of the Helperclass.

    - -
    -
    - -
    -
    - - - - - - - -
    getTitle ()
    -
    -
    - -

    get title attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    hasInfo ()
    -
    -
    - -

    check if a ticket has a ticket_info page or not.

    -
    Returns:
    true or false
    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a TId (ticket id).

    -
    Parameters:
    - - -
    $idthe id of the ticket that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('TId' => ticket_id, 'Title' => title, 'Status'=> status, 'Timestamp' => ts, 'Queue' => queue, 'Ticket_Category' => tc, 'Author' => author, 'Priority' => priority).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setAuthor (a)
    -
    -
    - -

    set author attribute of the object.

    -
    Parameters:
    - - -
    $aauthor of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setPriority (p)
    -
    -
    - -

    set priority attribute of the object.

    -
    Parameters:
    - - -
    $ppriority of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setQueue (q)
    -
    -
    - -

    set queue attribute of the object.

    -
    Parameters:
    - - -
    $qqueue of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setStatus (s)
    -
    -
    - -

    set status attribute of the object.

    -
    Parameters:
    - - -
    $sstatus of the ticket(int)
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTicket_Category (tc)
    -
    -
    - -

    set ticket_category attribute of the object.

    -
    Parameters:
    - - -
    $tcticket_category id of the ticket(int)
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTId (id)
    -
    -
    - -

    set tId attribute of the object.

    -
    Parameters:
    - - -
    $idinteger id of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTimestamp (ts)
    -
    -
    - -

    set timestamp attribute of the object.

    -
    Parameters:
    - - -
    $tstimestamp of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTitle (t)
    -
    -
    - -

    set title attribute of the object.

    -
    Parameters:
    - - -
    $ttitle of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    static ticketExists (id) [static]
    -
    -
    - -

    check if a ticket exists.

    -
    Parameters:
    - - -
    $idthe id of the ticket to be checked.
    -
    -
    -
    Returns:
    true if the ticket exists, else false.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static unAssignTicket (user_id,
    ticket_id 
    ) [static]
    -
    -
    - -

    unassign a ticket of a user.

    -

    Checks if the ticket exists, if so then it will try to unassign the user of it, a log entry will be written about this.

    -
    Parameters:
    - - - -
    $user_idthe id of user trying to be assigned to the ticket.
    $ticket_idthe id of the ticket that we try to assign to the user.
    -
    -
    -
    Returns:
    SUCCESS_UNASSIGNED, TICKET_NOT_EXISTING or NOT_ASSIGNED
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    update the objects attributes to the db.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static updateTicketStatus (ticket_id,
    newStatus,
    author 
    ) [static]
    -
    -
    - -

    updates the ticket's status.

    -

    A log entry about this will be created only if the newStatus is different from the current status.

    -
    Parameters:
    - - - - -
    $ticket_idthe id of the ticket of which we want to change the status.
    $newStatusthe new status value (integer)
    $authorthe user (id) that performed the update status action
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static updateTicketStatusAndPriority (ticket_id,
    newStatus,
    newPriority,
    author 
    ) [static]
    -
    -
    - -

    updates the ticket's status & priority.

    -

    A log entry about this will be created only if the newStatus is different from the current status and also when the newPriority is different from the current priority.

    -
    Todo:
    break this function up into a updateStatus (already exists) and updatePriority function and perhaps write a wrapper function for the combo.
    -
    Parameters:
    - - - - - -
    $ticket_idthe id of the ticket of which we want to change the status & priority
    $newStatusthe new status value (integer)
    $newPrioritythe new priority value (integer)
    $authorthe user (id) that performed the update
    -
    -
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $author [private]
    -
    -
    - -

    The ticket_users id.

    - -
    -
    - -
    -
    - - - - -
    $priority [private]
    -
    -
    - -

    The priority of the ticket where 0 = low, 3= supadupahigh.

    - -
    -
    - -
    -
    - - - - -
    $queue [private]
    -
    -
    - -

    (not in use atm)

    - -
    -
    - -
    -
    - - - - -
    $status [private]
    -
    -
    - -

    Status of the ticket (0 = waiting on user reply, 1 = waiting on support, (2= not used atm), 3 = closed.

    - -
    -
    - -
    -
    - - - - -
    $ticket_category [private]
    -
    -
    - -

    the id of the category belonging to the ticket

    - -
    -
    - -
    -
    - - - - -
    $tId [private]
    -
    -
    - -

    The id of ticket.

    - -
    -
    - -
    -
    - - - - -
    $timestamp [private]
    -
    -
    - -

    Timestamp of the ticket.

    - -
    -
    - -
    -
    - - - - -
    $title [private]
    -
    -
    - -

    Title of the ticket.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Category.html b/code/web/docs/ams/html/classTicket__Category.html deleted file mode 100644 index 4a04b6b8d..000000000 --- a/code/web/docs/ams/html/classTicket__Category.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Category Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Ticket_Category Class Reference
    -
    -
    - -

    Class related to the ticket categories. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     load_With_TCategoryId ($id)
     loads the object's attributes.
     update ()
     update object attributes to the DB.
     getName ()
     get name attribute of the object.
     getTCategoryId ()
     get tCategoryId attribute of the object.
     setName ($n)
     set name attribute of the object.
     setTCategoryId ($id)
     set tCategoryId attribute of the object.

    -Static Public Member Functions

    static createTicketCategory ($name)
     creates a ticket_Catergory in the DB.
    static constr_TCategoryId ($id)
     construct a category object based on the TCategoryId.
    static getAllCategories ()
     return a list of all category objects.

    -Private Attributes

     $tCategoryId
     The id of the category.
     $name
     The name of the category.
    -

    Detailed Description

    -

    Class related to the ticket categories.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - -
    static constr_TCategoryId (id) [static]
    -
    -
    - -

    construct a category object based on the TCategoryId.

    -
    Returns:
    constructed element based on TCategoryId
    - -
    -
    - -
    -
    - - - - - - - - -
    static createTicketCategory (name) [static]
    -
    -
    - -

    creates a ticket_Catergory in the DB.

    -
    Parameters:
    - - -
    $namename we want to give to the new category.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    static getAllCategories () [static]
    -
    -
    - -

    return a list of all category objects.

    -
    Returns:
    an array consisting of all category objects.
    - -
    -
    - -
    -
    - - - - - - - -
    getName ()
    -
    -
    - -

    get name attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTCategoryId ()
    -
    -
    - -

    get tCategoryId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TCategoryId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a categories id.

    -
    Parameters:
    - - -
    $idthe id of the ticket_category that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setName (n)
    -
    -
    - -

    set name attribute of the object.

    -
    Parameters:
    - - -
    $nname of the category
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTCategoryId (id)
    -
    -
    - -

    set tCategoryId attribute of the object.

    -
    Parameters:
    - - -
    $idinteger id of the category
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    update object attributes to the DB.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $name [private]
    -
    -
    - -

    The name of the category.

    - -
    -
    - -
    -
    - - - - -
    $tCategoryId [private]
    -
    -
    - -

    The id of the category.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Content.html b/code/web/docs/ams/html/classTicket__Content.html deleted file mode 100644 index 0f375bbb7..000000000 --- a/code/web/docs/ams/html/classTicket__Content.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Content Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Ticket_Content Class Reference
    -
    -
    - -

    Class that handles the content of a reply. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     create ()
     creates a new 'tickt_content' entry.
     load_With_TContentId ($id)
     loads the object's attributes.
     update ()
     update the object's attributes to the database.
     getContent ()
     get content attribute of the object.
     getTContentId ()
     get tContentId attribute of the object.
     setContent ($c)
     set content attribute of the object.
     setTContentId ($c)
     set tContentId attribute of the object.

    -Static Public Member Functions

    static constr_TContentId ($id)
     return constructed element based on TContentId.

    -Private Attributes

     $tContentId
     The id of ticket_content entry.
     $content
     The content of an entry.
    -

    Detailed Description

    -

    Class that handles the content of a reply.

    -

    The Ticket_Content has a one-to-one relation with a ticket_reply, it contains the content of a reply, this way the content doesn't always have to be loaded when we query the database when we only need information regarding to the replies basic information.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - -
    static constr_TContentId (id) [static]
    -
    -
    - -

    return constructed element based on TContentId.

    -
    Parameters:
    - - -
    $idthe id of ticket_content entry.
    -
    -
    -
    Returns:
    a constructed ticket_content object by specifying the TContentId.
    - -
    -
    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'tickt_content' entry.

    -

    this method will use the object's attributes for creating a new 'ticket_content' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - -
    getContent ()
    -
    -
    - -

    get content attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTContentId ()
    -
    -
    - -

    get tContentId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TContentId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a ticket_content's id,

    -
    Parameters:
    - - -
    $idthe id of the ticket_content entry that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setContent (c)
    -
    -
    - -

    set content attribute of the object.

    -
    Parameters:
    - - -
    $ccontent of a reply
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTContentId (c)
    -
    -
    - -

    set tContentId attribute of the object.

    -
    Parameters:
    - - -
    $cinteger id of ticket_content entry
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    update the object's attributes to the database.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $content [private]
    -
    -
    - -

    The content of an entry.

    - -
    -
    - -
    -
    - - - - -
    $tContentId [private]
    -
    -
    - -

    The id of ticket_content entry.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Info.html b/code/web/docs/ams/html/classTicket__Info.html deleted file mode 100644 index c88c41481..000000000 --- a/code/web/docs/ams/html/classTicket__Info.html +++ /dev/null @@ -1,1463 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Info Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    Class that handles additional info sent by ticket creation ingame. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     load_With_TInfoId ($id)
     loads the object's attributes by using a ticket_info id.
     load_With_Ticket ($id)
     loads the object's attributes by using a ticket's id.
     create ()
     creates a new 'ticket_info' entry.
     getTInfoId ()
     get tInfoId attribute of the object.
     getTicket ()
     get ticket attribute of the object.
     getShardId ()
     get shardid attribute of the object.
     getUser_Position ()
     get user_position attribute of the object.
     getView_Position ()
     get view_position attribute of the object.
     getClient_Version ()
     get client_version attribute of the object.
     getPatch_Version ()
     get patch_version attribute of the object.
     getServer_Tick ()
     get server_tick attribute of the object.
     getConnect_State ()
     get connect_state attribute of the object.
     getLocal_Address ()
     get local_address attribute of the object.
     getMemory ()
     get memory attribute of the object.
     getOS ()
     get os attribute of the object.
     getProcessor ()
     get processor attribute of the object.
     getCPUId ()
     get cpu_id attribute of the object.
     getCPU_Mask ()
     get cpu_mask attribute of the object.
     getHT ()
     get ht attribute of the object.
     getNel3D ()
     get nel3d attribute of the object.
     getUser_Id ()
     get user_id attribute of the object.
     setTInfoId ($id)
     set tInfoId attribute of the object.
     setTicket ($t)
     set ticket attribute of the object.
     setShardId ($s)
     set shardid attribute of the object.
     setUser_Position ($u)
     set user_position attribute of the object.
     setView_Position ($v)
     set view_position attribute of the object.
     setClient_Version ($c)
     set client_version attribute of the object.
     setPatch_Version ($p)
     set patch_version attribute of the object.
     setServer_Tick ($s)
     set server_tick attribute of the object.
     setConnect_State ($c)
     set connect_state attribute of the object.
     setLocal_Address ($l)
     set local_address attribute of the object.
     setMemory ($m)
     set memory attribute of the object.
     setOS ($o)
     set os attribute of the object.
     setProcessor ($p)
     set processor attribute of the object.
     setCPUId ($c)
     set cpu_id attribute of the object.
     setCPU_Mask ($c)
     set cpu_mask attribute of the object.
     setHT ($h)
     set ht attribute of the object.
     setNel3D ($n)
     set nel3d attribute of the object.
     setUser_Id ($u)
     set user_id attribute of the object.

    -Static Public Member Functions

    static create_Ticket_Info ($info_array)
     create a ticket_info entry.
    static TicketHasInfo ($ticket_id)
     check if a specific ticket has extra info or not.

    -Private Attributes

     $tInfoId
     The id of ticket_info entry.
     $ticket
     The ticket linked to this ticket_info entry.
     $shardid
     The shard id.
     $user_position
     The user's character position.
     $view_position
     The view position of the character.
     $client_version
     The client version in use.
     $patch_version
     The patch version in use.
     $server_tick
     The current server tick.
     $connect_state
     The connect state.
     $local_address
     local ip
     $memory
     memory usage information
     $os
     os information
     $processor
     processor information
     $cpu_id
     the cpu id
     $cpu_mask
     the cpu mask
     $ht
     tbh I have no idea :D
     $nel3d
     the nel3d version
     $user_id
     The users id.
    -

    Detailed Description

    -

    Class that handles additional info sent by ticket creation ingame.

    -

    If a user creates a ticket ingame, there are a lot of extra $_GET parameters being sent inside the http request that might have something todo with the ticket. for example the OS the user uses or the processor of it's computer, but also the current client version etc. This information can be stored and retrieved by using the ticket_info class.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'ticket_info' entry.

    -

    this method will use the object's attributes for creating a new 'ticket_info' entry in the database.

    - -
    -
    - -
    -
    - - - - - - - - -
    static create_Ticket_Info (info_array) [static]
    -
    -
    - -

    create a ticket_info entry.

    -
    Parameters:
    - - -
    $info_arraythe info array (this can be the entire $_GET array being sent by the ingame browser)
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    getClient_Version ()
    -
    -
    - -

    get client_version attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getConnect_State ()
    -
    -
    - -

    get connect_state attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getCPU_Mask ()
    -
    -
    - -

    get cpu_mask attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getCPUId ()
    -
    -
    - -

    get cpu_id attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getHT ()
    -
    -
    - -

    get ht attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getLocal_Address ()
    -
    -
    - -

    get local_address attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getMemory ()
    -
    -
    - -

    get memory attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getNel3D ()
    -
    -
    - -

    get nel3d attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getOS ()
    -
    -
    - -

    get os attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getPatch_Version ()
    -
    -
    - -

    get patch_version attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getProcessor ()
    -
    -
    - -

    get processor attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getServer_Tick ()
    -
    -
    - -

    get server_tick attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getShardId ()
    -
    -
    - -

    get shardid attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTicket ()
    -
    -
    - -

    get ticket attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTInfoId ()
    -
    -
    - -

    get tInfoId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUser_Id ()
    -
    -
    - -

    get user_id attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUser_Position ()
    -
    -
    - -

    get user_position attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getView_Position ()
    -
    -
    - -

    get view_position attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_Ticket (id)
    -
    -
    - -

    loads the object's attributes by using a ticket's id.

    -

    loads the object's attributes by giving a ticket's entry id.

    -
    Parameters:
    - - -
    $idthe id of the ticket, the ticket_info entry of that ticket should be loaded.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TInfoId (id)
    -
    -
    - -

    loads the object's attributes by using a ticket_info id.

    -

    loads the object's attributes by giving a ticket_info's entry id.

    -
    Parameters:
    - - -
    $idthe id of the ticket_info entry that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setClient_Version (c)
    -
    -
    - -

    set client_version attribute of the object.

    -
    Parameters:
    - - -
    $cclient version number
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setConnect_State (c)
    -
    -
    - -

    set connect_state attribute of the object.

    -
    Parameters:
    - - -
    $cstring that defines the connect state.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setCPU_Mask (c)
    -
    -
    - -

    set cpu_mask attribute of the object.

    -
    Parameters:
    - - -
    $cmask of the cpu
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setCPUId (c)
    -
    -
    - -

    set cpu_id attribute of the object.

    -
    Parameters:
    - - -
    $ccpu id information
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setHT (h)
    -
    -
    - -

    set ht attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    setLocal_Address (l)
    -
    -
    - -

    set local_address attribute of the object.

    -
    Parameters:
    - - -
    $llocal address
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setMemory (m)
    -
    -
    - -

    set memory attribute of the object.

    -
    Parameters:
    - - -
    $mmemory usage
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setNel3D (n)
    -
    -
    - -

    set nel3d attribute of the object.

    -
    Parameters:
    - - -
    $nversion information about NeL3D
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setOS (o)
    -
    -
    - -

    set os attribute of the object.

    -
    Parameters:
    - - -
    $oset os version information
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setPatch_Version (p)
    -
    -
    - -

    set patch_version attribute of the object.

    -
    Parameters:
    - - -
    $ppatch version number
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setProcessor (p)
    -
    -
    - -

    set processor attribute of the object.

    -
    Parameters:
    - - -
    $pprocessor information
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setServer_Tick (s)
    -
    -
    - -

    set server_tick attribute of the object.

    -
    Parameters:
    - - -
    $sinteger that resembles the server tick
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setShardId (s)
    -
    -
    - -

    set shardid attribute of the object.

    -
    Parameters:
    - - -
    $s(integer) shard id
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTicket (t)
    -
    -
    - -

    set ticket attribute of the object.

    -
    Parameters:
    - - -
    $tinteger id of the ticket linked to the info object
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTInfoId (id)
    -
    -
    - -

    set tInfoId attribute of the object.

    -
    Parameters:
    - - -
    $idinteger id of ticket_info object itself
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setUser_Id (u)
    -
    -
    - -

    set user_id attribute of the object.

    -
    Parameters:
    - - -
    $uthe user_id.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setUser_Position (u)
    -
    -
    - -

    set user_position attribute of the object.

    -
    Parameters:
    - - -
    $uthe users position
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setView_Position (v)
    -
    -
    - -

    set view_position attribute of the object.

    -
    Parameters:
    - - -
    $vthe view position
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    static TicketHasInfo (ticket_id) [static]
    -
    -
    - -

    check if a specific ticket has extra info or not.

    -

    Not all tickets have extra info, only tickets made ingame do. This function checks if a specific ticket does have a ticket_info entry linked to it.

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket that we want to query
    -
    -
    -
    Returns:
    true or false
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $client_version [private]
    -
    -
    - -

    The client version in use.

    - -
    -
    - -
    -
    - - - - -
    $connect_state [private]
    -
    -
    - -

    The connect state.

    - -
    -
    - -
    -
    - - - - -
    $cpu_id [private]
    -
    -
    - -

    the cpu id

    - -
    -
    - -
    -
    - - - - -
    $cpu_mask [private]
    -
    -
    - -

    the cpu mask

    - -
    -
    - -
    -
    - - - - -
    $ht [private]
    -
    -
    - -

    tbh I have no idea :D

    - -
    -
    - -
    -
    - - - - -
    $local_address [private]
    -
    -
    - -

    local ip

    - -
    -
    - -
    -
    - - - - -
    $memory [private]
    -
    -
    - -

    memory usage information

    - -
    -
    - -
    -
    - - - - -
    $nel3d [private]
    -
    -
    - -

    the nel3d version

    - -
    -
    - -
    -
    - - - - -
    $os [private]
    -
    -
    - -

    os information

    - -
    -
    - -
    -
    - - - - -
    $patch_version [private]
    -
    -
    - -

    The patch version in use.

    - -
    -
    - -
    -
    - - - - -
    $processor [private]
    -
    -
    - -

    processor information

    - -
    -
    - -
    -
    - - - - -
    $server_tick [private]
    -
    -
    - -

    The current server tick.

    - -
    -
    - -
    -
    - - - - -
    $shardid [private]
    -
    -
    - -

    The shard id.

    - -
    -
    - -
    -
    - - - - -
    $ticket [private]
    -
    -
    - -

    The ticket linked to this ticket_info entry.

    - -
    -
    - -
    -
    - - - - -
    $tInfoId [private]
    -
    -
    - -

    The id of ticket_info entry.

    - -
    -
    - -
    -
    - - - - -
    $user_id [private]
    -
    -
    - -

    The users id.

    - -
    -
    - -
    -
    - - - - -
    $user_position [private]
    -
    -
    - -

    The user's character position.

    - -
    -
    - -
    -
    - - - - -
    $view_position [private]
    -
    -
    - -

    The view position of the character.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Log.html b/code/web/docs/ams/html/classTicket__Log.html deleted file mode 100644 index 59efe7def..000000000 --- a/code/web/docs/ams/html/classTicket__Log.html +++ /dev/null @@ -1,763 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Log Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    Class that handles the logging. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     load_With_TLogId ($id)
     loads the object's attributes.
     update ()
     update attributes of the object to the DB.
     getTLogId ()
     get tLogId attribute of the object.
     getTimestamp ()
     get timestamp attribute of the object.
     getQuery ()
     get query attribute of the object.
     getAuthor ()
     get author attribute of the object.
     getTicket ()
     get ticket attribute of the object.
     getAction ()
     get the action id out of the query by decoding it.
     getArgument ()
     get the argument out of the query by decoding it.
     getActionTextArray ()
     get the action text(string) array.
     setTLogId ($id)
     set tLogId attribute of the object.
     setTimestamp ($t)
     set timestamp attribute of the object.
     setQuery ($q)
     set query attribute of the object.
     setAuthor ($a)
     set author attribute of the object.
     setTicket ($t)
     set ticket attribute of the object.

    -Static Public Member Functions

    static getLogsOfTicket ($ticket_id)
     return all log entries related to a ticket.
    static createLogEntry ($ticket_id, $author_id, $action, $arg=-1)
     create a new log entry.
    static constr_TLogId ($id)
     return constructed element based on TLogId
    static getAllLogs ($ticket_id)
     return all log entries related to a ticket.

    -Private Attributes

     $tLogId
     The id of the log entry.
     $timestamp
     The timestamp of the log entry.
     $query
     The query (json encoded array containing action id & argument)
     $author
     author of the log
     $ticket
     the id of the ticket related to the log entry
    -

    Detailed Description

    -

    Class that handles the logging.

    -

    The logging will be used when a ticket is created, a reply is added, if someone views a ticket, if someone assigns a ticket to him or if someone forwards a ticket. This class provides functions to get retrieve those logs and also make them.

    -

    -the Action IDs being used are:

    -
      -
    1. User X Created ticket
    2. -
    3. Admin X created ticket for arg
    4. -
    5. Read ticket
    6. -
    7. Added Reply ID: arg to ticket
    8. -
    9. Changed status to arg
    10. -
    11. Changed Priority to arg
    12. -
    13. assigned to the ticket
    14. -
    15. forwarded ticket to support group arg
    16. -
    17. unassigned to the ticket
    18. -
    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - -
    static constr_TLogId (id) [static]
    -
    -
    - -

    return constructed element based on TLogId

    -
    Parameters:
    - - -
    $idticket_log id of the entry that we want to load into our object.
    -
    -
    -
    Returns:
    constructed ticket_log object.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static createLogEntry (ticket_id,
    author_id,
    action,
    arg = -1 
    ) [static]
    -
    -
    - -

    create a new log entry.

    -

    It will check if the $TICKET_LOGGING global var is true, this var is used to turn logging on and off. In case it's on, the log message will be stored. the action id and argument (which is -1 by default), will be json encoded and stored in the query field in the db.

    -
    Parameters:
    - - - - - -
    $ticket_idthe id of the ticket related to the new log entry
    $author_idthe id of the user that instantiated the logging.
    $actionthe action id (see the list in the class description)
    $argargument for the action (default = -1)
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    getAction ()
    -
    -
    - -

    get the action id out of the query by decoding it.

    - -
    -
    - -
    -
    - - - - - - - -
    getActionTextArray ()
    -
    -
    - -

    get the action text(string) array.

    -

    this is being read from the language .ini files.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getAllLogs (ticket_id) [static]
    -
    -
    - -

    return all log entries related to a ticket.

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket of which we want all related log entries returned.
    -
    -
    -
    Returns:
    an array of ticket_log objects, here the author is an integer.
    -
    Todo:
    only use one of the 2 comparable functions in the future and make the other depricated.
    - -
    -
    - -
    -
    - - - - - - - -
    getArgument ()
    -
    -
    - -

    get the argument out of the query by decoding it.

    - -
    -
    - -
    -
    - - - - - - - -
    getAuthor ()
    -
    -
    - -

    get author attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getLogsOfTicket (ticket_id) [static]
    -
    -
    - -

    return all log entries related to a ticket.

    -
    Parameters:
    - - -
    $ticket_idthe id of the ticket of which we want all related log entries returned.
    -
    -
    -
    Returns:
    an array of ticket_log objects, be aware that the author in the ticket_log object is a ticket_user object on its own (so not a simple integer).
    - -
    -
    - -
    -
    - - - - - - - -
    getQuery ()
    -
    -
    - -

    get query attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTicket ()
    -
    -
    - -

    get ticket attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTimestamp ()
    -
    -
    - -

    get timestamp attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTLogId ()
    -
    -
    - -

    get tLogId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TLogId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a ticket_log entries ID (TLogId).

    -
    Parameters:
    - - -
    idthe id of the ticket_log entry that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setAuthor (a)
    -
    -
    - -

    set author attribute of the object.

    -
    Parameters:
    - - -
    $ainteger id of the user who created the log entry
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setQuery (q)
    -
    -
    - -

    set query attribute of the object.

    -
    Parameters:
    - - -
    $qthe encoded query
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTicket (t)
    -
    -
    - -

    set ticket attribute of the object.

    -
    Parameters:
    - - -
    $tinteger id of ticket of which the log entry is related to.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTimestamp (t)
    -
    -
    - -

    set timestamp attribute of the object.

    -
    Parameters:
    - - -
    $ttimestamp of the log entry
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTLogId (id)
    -
    -
    - -

    set tLogId attribute of the object.

    -
    Parameters:
    - - -
    $idinteger id of the log entry
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    update attributes of the object to the DB.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $author [private]
    -
    -
    - -

    author of the log

    - -
    -
    - -
    -
    - - - - -
    $query [private]
    -
    -
    - -

    The query (json encoded array containing action id & argument)

    - -
    -
    - -
    -
    - - - - -
    $ticket [private]
    -
    -
    - -

    the id of the ticket related to the log entry

    - -
    -
    - -
    -
    - - - - -
    $timestamp [private]
    -
    -
    - -

    The timestamp of the log entry.

    - -
    -
    - -
    -
    - - - - -
    $tLogId [private]
    -
    -
    - -

    The id of the log entry.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Queue.html b/code/web/docs/ams/html/classTicket__Queue.html deleted file mode 100644 index 63ebf5e09..000000000 --- a/code/web/docs/ams/html/classTicket__Queue.html +++ /dev/null @@ -1,401 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Queue Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Ticket_Queue Class Reference
    -
    -
    - -

    Data class that holds a lot of queries that load specific tickets. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     loadAllNotAssignedTickets ()
     loads the not yet assigned tickets query into the objects attributes.
     loadAllTickets ()
     loads the 'all' tickets query into the objects attributes.
     loadAllOpenTickets ()
     loads the 'all open' tickets query into the objects attributes.
     loadAllClosedTickets ()
     loads the 'closed' tickets query into the objects attributes.
     loadToDoTickets ($user_id)
     loads the 'todo' tickets query & params into the objects attributes.
     loadAssignedandWaiting ($user_id)
     loads the 'tickets asssigned to a user and waiting on support' query & params into the objects attributes.
     createQueue ($userid, $groupid, $what, $how, $who)
     loads the 'created' query & params into the objects attributes.
     getQuery ()
     get query attribute of the object.
     getParams ()
     get params attribute of the object.

    -Private Attributes

     $query
     The query that loads specific tickets.
     $params
     The parameter array that's being needed by the query.
    -

    Detailed Description

    -

    Data class that holds a lot of queries that load specific tickets.

    -

    These queries are being used by the ticket_queue_handler class. An object of this class holds 2 attributes: the query and the params used for the query.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    createQueue (userid,
    groupid,
    what,
    how,
    who 
    )
    -
    -
    - -

    loads the 'created' query & params into the objects attributes.

    -

    This function creates dynamically a query based on the selected features.

    -
    Parameters:
    - - - - - - -
    $whospecifies if we want to user the user_id or group_id to form the query.
    $useridthe user's id to whom the tickets should be assigned/not assigned
    $groupidthe group's id to whom the tickets should be forwarded/not forwarded
    $whatspecifies what kind of tickets we want to return: waiting for support, waiting on user, closed
    $howspecifies if the tickets should be or shouldn't be assigned/forwarded to the group/user selected.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    getParams ()
    -
    -
    - -

    get params attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getQuery ()
    -
    -
    - -

    get query attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    loadAllClosedTickets ()
    -
    -
    - -

    loads the 'closed' tickets query into the objects attributes.

    - -
    -
    - -
    -
    - - - - - - - -
    loadAllNotAssignedTickets ()
    -
    -
    - -

    loads the not yet assigned tickets query into the objects attributes.

    - -
    -
    - -
    -
    - - - - - - - -
    loadAllOpenTickets ()
    -
    -
    - -

    loads the 'all open' tickets query into the objects attributes.

    - -
    -
    - -
    -
    - - - - - - - -
    loadAllTickets ()
    -
    -
    - -

    loads the 'all' tickets query into the objects attributes.

    - -
    -
    - -
    -
    - - - - - - - - -
    loadAssignedandWaiting (user_id)
    -
    -
    - -

    loads the 'tickets asssigned to a user and waiting on support' query & params into the objects attributes.

    -
    Parameters:
    - - -
    $user_idthe user's id to whom the tickets should be assigned
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    loadToDoTickets (user_id)
    -
    -
    - -

    loads the 'todo' tickets query & params into the objects attributes.

    -

    first: find the tickets assigned to the user with status = waiting on support, second find all not assigned tickets that aren't forwarded yet. find all tickets assigned to someone else witht status waiting on support, with timestamp of last reply > 1 day, find all non-assigned tickets forwarded to the support groups to which that user belongs

    -
    Parameters:
    - - -
    $user_idthe user's id to whom the tickets should be assigned
    -
    -
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $params [private]
    -
    -
    - -

    The parameter array that's being needed by the query.

    - -
    -
    - -
    -
    - - - - -
    $query [private]
    -
    -
    - -

    The query that loads specific tickets.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Queue__Handler.html b/code/web/docs/ams/html/classTicket__Queue__Handler.html deleted file mode 100644 index 93d3cb996..000000000 --- a/code/web/docs/ams/html/classTicket__Queue__Handler.html +++ /dev/null @@ -1,395 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Queue_Handler Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    Ticket_Queue_Handler Class Reference
    -
    -
    - -

    returns tickets (queues) that are related in some way. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     getTickets ($input, $user_id)
     returns the tickets that are related in someway defined by $input.
     getPagination ()
     get pagination attribute of the object.
     createQueue ($userid, $groupid, $what, $how, $who)
     creates the queue.

    -Static Public Member Functions

    static getNrOfTicketsToDo ($user_id)
     get the number of tickets in the todo queue for a specific user.
    static getNrOfTicketsAssignedWaiting ($user_id)
     get the number of tickets assigned to a specific user and waiting for support.
    static getNrOfTickets ()
     get the total number of tickets.
    static getNewestTicket ()
     get the ticket object of the latest added ticket.

    -Private Attributes

     $pagination
     Pagination object, this way only a few tickets (related to that pagenumber) will be shown.
     $queue
     The queue object, being used to get the queries and parameters.
    -

    Detailed Description

    -

    returns tickets (queues) that are related in some way.

    -

    This class handles the creation and returning of existing ticket queues. Normally a $_GET['get'] parameter is being used to identify what kind of tickets should be shown. the getTickets() function uses this parameter($input) and uses the ticket_queue class to load the specific query.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Instantiates the queue object.

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    createQueue (userid,
    groupid,
    what,
    how,
    who 
    )
    -
    -
    - -

    creates the queue.

    -

    afterwards the getTickets function should be called, else a lot of extra parameters had to be added to the getTickets function..

    - -
    -
    - -
    -
    - - - - - - - -
    static getNewestTicket () [static]
    -
    -
    - -

    get the ticket object of the latest added ticket.

    - -
    -
    - -
    -
    - - - - - - - -
    static getNrOfTickets () [static]
    -
    -
    - -

    get the total number of tickets.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getNrOfTicketsAssignedWaiting (user_id) [static]
    -
    -
    - -

    get the number of tickets assigned to a specific user and waiting for support.

    -
    Parameters:
    - - -
    $user_idthe user being queried
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    static getNrOfTicketsToDo (user_id) [static]
    -
    -
    - -

    get the number of tickets in the todo queue for a specific user.

    -
    Parameters:
    - - -
    $user_idthe user being queried
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    getPagination ()
    -
    -
    - -

    get pagination attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    getTickets (input,
    user_id 
    )
    -
    -
    - -

    returns the tickets that are related in someway defined by $input.

    -

    The $input parameter should be a string that defines what kind of queue should be loaded. A new pagination object will be instantiated and will load 10 entries, related to the $_GET['pagenum'] variable.

    -
    Parameters:
    - - - -
    $inputidentifier that defines what queue to load.
    $user_idthe id of the user that browses the queues, some queues can be depending on this.
    -
    -
    -
    Returns:
    an array consisting of ticket objects, beware, the author & category of a ticket, are objects on their own (no integers are used this time).
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $pagination [private]
    -
    -
    - -

    Pagination object, this way only a few tickets (related to that pagenumber) will be shown.

    - -
    -
    - -
    -
    - - - - -
    $queue [private]
    -
    -
    - -

    The queue object, being used to get the queries and parameters.

    - -
    -
    -
    The documentation for this class was generated from the following file: -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__Reply.html b/code/web/docs/ams/html/classTicket__Reply.html deleted file mode 100644 index eed01a154..000000000 --- a/code/web/docs/ams/html/classTicket__Reply.html +++ /dev/null @@ -1,764 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_Reply Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    handles functions related to replies on tickets. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     create ()
     creates a new 'ticket_reply' entry.
     load_With_TReplyId ($id)
     loads the object's attributes.
     update ()
     updates a ticket_reply entry based on the objects attributes.
     getTicket ()
     get ticket attribute of the object.
     getContent ()
     get content attribute of the object.
     getAuthor ()
     get author attribute of the object.
     getTimestamp ()
     get timestamp attribute of the object.
     getTReplyId ()
     get tReplyId attribute of the object.
     getHidden ()
     get hidden attribute of the object.
     setTicket ($t)
     set ticket attribute of the object.
     setContent ($c)
     set content attribute of the object.
     setAuthor ($a)
     set author attribute of the object.
     setTimestamp ($t)
     set timestamp attribute of the object.
     setTReplyId ($i)
     set tReplyId attribute of the object.
     setHidden ($h)
     set hidden attribute of the object.

    -Static Public Member Functions

    static constr_TReplyId ($id)
     return constructed element based on TReplyId.
    static getRepliesOfTicket ($ticket_id, $view_as_admin)
     return all replies on a specific ticket.
    static createReply ($content, $author, $ticket_id, $hidden, $ticket_creator)
     creates a new reply on a ticket.

    -Private Attributes

     $tReplyId
     The id of the reply.
     $ticket
     the ticket id related to the reply
     $content
     the content of the reply
     $author
     The id of the user that made the reply.
     $timestamp
     The timestamp of the reply.
     $hidden
     indicates if reply should be hidden for normal users or not
    -

    Detailed Description

    -

    handles functions related to replies on tickets.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - -
    static constr_TReplyId (id) [static]
    -
    -
    - -

    return constructed element based on TReplyId.

    -
    Parameters:
    - - -
    $idthe Id the reply we want to load.
    -
    -
    -
    Returns:
    the loaded object.
    - -
    -
    - -
    -
    - - - - - - - -
    create ()
    -
    -
    - -

    creates a new 'ticket_reply' entry.

    -

    this method will use the object's attributes for creating a new 'ticket_reply' entry in the database (the now() function will create the timestamp).

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    static createReply (content,
    author,
    ticket_id,
    hidden,
    ticket_creator 
    ) [static]
    -
    -
    - -

    creates a new reply on a ticket.

    -

    Creates a ticket_content entry and links it with a new created ticket_reply, a log entry will be written about this. In case the ticket creator replies on a ticket, he will set the status by default to 'waiting on support'.

    -
    Parameters:
    - - - - - - -
    $contentthe content of the reply
    $authorthe id of the reply creator.
    $ticket_idthe id of the ticket of which we want the replies.
    $hiddenshould be 0 or 1
    $ticket_creatorthe ticket's starter his id.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    getAuthor ()
    -
    -
    - -

    get author attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getContent ()
    -
    -
    - -

    get content attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getHidden ()
    -
    -
    - -

    get hidden attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static getRepliesOfTicket (ticket_id,
    view_as_admin 
    ) [static]
    -
    -
    - -

    return all replies on a specific ticket.

    -
    Parameters:
    - - - -
    $ticket_idthe id of the ticket of which we want the replies.
    $view_as_adminif the browsing user is an admin/mod it should be 1, this will also show the hidden replies.
    -
    -
    -
    Returns:
    an array with ticket_reply objects (beware the author and content are objects on their own, not integers!)
    - -
    -
    - -
    -
    - - - - - - - -
    getTicket ()
    -
    -
    - -

    get ticket attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTimestamp ()
    -
    -
    - -

    get timestamp attribute of the object.

    -

    The output format is defined by the Helpers class function, outputTime().

    - -
    -
    - -
    -
    - - - - - - - -
    getTReplyId ()
    -
    -
    - -

    get tReplyId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TReplyId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a ticket_reply's id.

    -
    Parameters:
    - - -
    $idthe id of the ticket_reply that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setAuthor (a)
    -
    -
    - -

    set author attribute of the object.

    -
    Parameters:
    - - -
    $ainteger id of the user
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setContent (c)
    -
    -
    - -

    set content attribute of the object.

    -
    Parameters:
    - - -
    $cinteger id of the ticket_content entry
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setHidden (h)
    -
    -
    - -

    set hidden attribute of the object.

    -
    Parameters:
    - - -
    $hshould be 0 or 1
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTicket (t)
    -
    -
    - -

    set ticket attribute of the object.

    -
    Parameters:
    - - -
    $tinteger id of the ticket
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTimestamp (t)
    -
    -
    - -

    set timestamp attribute of the object.

    -
    Parameters:
    - - -
    $ttimestamp of the reply
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTReplyId (i)
    -
    -
    - -

    set tReplyId attribute of the object.

    -
    Parameters:
    - - -
    $iinteger id of the ticket_reply
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    updates a ticket_reply entry based on the objects attributes.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $author [private]
    -
    -
    - -

    The id of the user that made the reply.

    - -
    -
    - -
    -
    - - - - -
    $content [private]
    -
    -
    - -

    the content of the reply

    - -
    -
    - -
    -
    - - - - -
    $hidden [private]
    -
    -
    - -

    indicates if reply should be hidden for normal users or not

    - -
    -
    - -
    -
    - - - - -
    $ticket [private]
    -
    -
    - -

    the ticket id related to the reply

    - -
    -
    - -
    -
    - - - - -
    $timestamp [private]
    -
    -
    - -

    The timestamp of the reply.

    - -
    -
    - -
    -
    - - - - -
    $tReplyId [private]
    -
    -
    - -

    The id of the reply.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classTicket__User.html b/code/web/docs/ams/html/classTicket__User.html deleted file mode 100644 index 3e74dc034..000000000 --- a/code/web/docs/ams/html/classTicket__User.html +++ /dev/null @@ -1,745 +0,0 @@ - - - - - -Ryzom Account Management System: Ticket_User Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    user entry point in the ticket system. - More...

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ()
     A constructor.
     set ($values)
     sets the object's attributes.
     load_With_TUserId ($id)
     loads the object's attributes.
     update ()
     update the object's attributes to the db.
     getPermission ()
     get permission attribute of the object.
     getExternId ()
     get externId attribute of the object.
     getTUserId ()
     get tUserId attribute of the object.
     setPermission ($perm)
     set permission attribute of the object.
     setExternId ($id)
     set externId attribute of the object.
     setTUserId ($id)
     set tUserId attribute of the object.

    -Static Public Member Functions

    static createTicketUser ($extern_id, $permission)
     create a new ticket user.
    static isMod ($user)
     check if a ticket_user object is a mod or not.
    static isAdmin ($user)
     check if a ticket_user object is an admin or not.
    static constr_TUserId ($id)
     return constructed ticket_user object based on TUserId.
    static getModsAndAdmins ()
     return a list of all mods/admins.
    static constr_ExternId ($id)
     return constructed ticket_user object based on ExternId.
    static change_permission ($user_id, $perm)
     change the permission of a ticket_user.
    static get_email_by_user_id ($id)
     return the email address of a ticket_user.
    static get_username_from_id ($id)
     return the username of a ticket_user.
    static get_id_from_username ($username)
     return the TUserId of a ticket_user by giving a username.
    static get_id_from_email ($email)
     return the ticket_user id from an email address.

    -Private Attributes

     $tUserId
     The id of the user inside the ticket system.
     $permission
     The permission of the user.
     $externId
     The id of the user account in the www (could be drupal,...) that is linked to the ticket_user.
    -

    Detailed Description

    -

    user entry point in the ticket system.

    -

    The ticket_user makes a link between the entire ticket system's lib db and the www user, which is stored in another db (this is the external ID). The externalID could be the ID of a drupal user or wordpress user,.. The ticket_user also stores the permission of that user, this way the permission system is inside the lib itself and can be used in any www version that you like. permission 1 = user, 2 = mod, 3 = admin.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - -
    __construct ()
    -
    -
    - -

    A constructor.

    -

    Empty constructor

    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static change_permission (user_id,
    perm 
    ) [static]
    -
    -
    - -

    change the permission of a ticket_user.

    -
    Parameters:
    - - - -
    $user_idthe TUserId of the entry.
    $permthe new permission value.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    static constr_ExternId (id) [static]
    -
    -
    - -

    return constructed ticket_user object based on ExternId.

    -
    Parameters:
    - - -
    $idthe ExternId of the entry.
    -
    -
    -
    Returns:
    constructed ticket_user object
    - -
    -
    - -
    -
    - - - - - - - - -
    static constr_TUserId (id) [static]
    -
    -
    - -

    return constructed ticket_user object based on TUserId.

    -
    Parameters:
    - - -
    $idthe TUserId of the entry.
    -
    -
    -
    Returns:
    constructed ticket_user object
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static createTicketUser (extern_id,
    permission 
    ) [static]
    -
    -
    - -

    create a new ticket user.

    -
    Parameters:
    - - - -
    $extern_idthe id of the user account in the www version (drupal,...)
    $permissionthe permission that will be given to the user. 1=user, 2=mod, 3=admin
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    static get_email_by_user_id (id) [static]
    -
    -
    - -

    return the email address of a ticket_user.

    -
    Parameters:
    - - -
    $idthe TUserId of the entry.
    -
    -
    -
    Returns:
    string containing the email address of that user.
    - -
    -
    - -
    -
    - - - - - - - - -
    static get_id_from_email (email) [static]
    -
    -
    - -

    return the ticket_user id from an email address.

    -
    Parameters:
    - - -
    $emailthe emailaddress of a user.
    -
    -
    -
    Returns:
    the ticket_user id related to that email address, in case none, return "FALSE".
    - -
    -
    - -
    -
    - - - - - - - - -
    static get_id_from_username (username) [static]
    -
    -
    - -

    return the TUserId of a ticket_user by giving a username.

    -
    Parameters:
    - - -
    $usernamethe username of a user.
    -
    -
    -
    Returns:
    the TUserId related to that username.
    - -
    -
    - -
    -
    - - - - - - - - -
    static get_username_from_id (id) [static]
    -
    -
    - -

    return the username of a ticket_user.

    -
    Parameters:
    - - -
    $idthe TUserId of the entry.
    -
    -
    -
    Returns:
    string containing username of that user.
    - -
    -
    - -
    -
    - - - - - - - -
    getExternId ()
    -
    -
    - -

    get externId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    static getModsAndAdmins () [static]
    -
    -
    - -

    return a list of all mods/admins.

    -
    Returns:
    an array consisting of ticket_user objects that are mods & admins.
    - -
    -
    - -
    -
    - - - - - - - -
    getPermission ()
    -
    -
    - -

    get permission attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getTUserId ()
    -
    -
    - -

    get tUserId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    static isAdmin (user) [static]
    -
    -
    - -

    check if a ticket_user object is an admin or not.

    -
    Parameters:
    - - -
    $userthe ticket_user object itself
    -
    -
    -
    Returns:
    true or false
    - -
    -
    - -
    -
    - - - - - - - - -
    static isMod (user) [static]
    -
    -
    - -

    check if a ticket_user object is a mod or not.

    -
    Parameters:
    - - -
    $userthe ticket_user object itself
    -
    -
    -
    Returns:
    true or false
    - -
    -
    - -
    -
    - - - - - - - - -
    load_With_TUserId (id)
    -
    -
    - -

    loads the object's attributes.

    -

    loads the object's attributes by giving a TUserId.

    -
    Parameters:
    - - -
    $idthe id of the ticket_user that should be loaded
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array of the form array('TUserId' => id, 'Permission' => perm, 'ExternId' => ext_id).
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setExternId (id)
    -
    -
    - -

    set externId attribute of the object.

    -
    Parameters:
    - - -
    $idthe external id.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setPermission (perm)
    -
    -
    - -

    set permission attribute of the object.

    -
    Parameters:
    - - -
    $perminteger that indicates the permission level. (1= user, 2= mod, 3= admin)
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    setTUserId (id)
    -
    -
    - -

    set tUserId attribute of the object.

    -
    Parameters:
    - - -
    $idthe ticket_user id
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    update ()
    -
    -
    - -

    update the object's attributes to the db.

    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $externId [private]
    -
    -
    - -

    The id of the user account in the www (could be drupal,...) that is linked to the ticket_user.

    - -
    -
    - -
    -
    - - - - -
    $permission [private]
    -
    -
    - -

    The permission of the user.

    - -
    -
    - -
    -
    - - - - -
    $tUserId [private]
    -
    -
    - -

    The id of the user inside the ticket system.

    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classUsers.html b/code/web/docs/ams/html/classUsers.html deleted file mode 100644 index 4083fde9c..000000000 --- a/code/web/docs/ams/html/classUsers.html +++ /dev/null @@ -1,641 +0,0 @@ - - - - - -Ryzom Account Management System: Users Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    handles basic user registration & management functions (shard related). - More...

    -
    -Inheritance diagram for Users:
    -
    -
    - - -WebUsers -WebUsers - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     check_Register ($values)
     checks if entered values before registering are valid.
     checkUser ($username)
     checks if entered username is valid.
     checkPassword ($pass)
     checks if the password is valid.
     checkEmail ($email)
     wrapper to check if the email address is valid.
     validEmail ($email)
     check if the emailaddress structure is valid.
     check_change_password ($values)
     check if the changing of a password is valid.

    -Static Public Member Functions

    static generateSALT ($length=2)
     generate a SALT.
    static createUser ($values, $user_id)
     creates a user in the shard.
    static createPermissions ($pvalues)
     creates permissions in the shard db for a user.

    -Protected Member Functions

     checkUserNameExists ($username)
     check if username already exists.
     checkEmailExists ($email)
     check if email already exists.
     checkLoginMatch ($user, $pass)
     check if username and password matches.
     setAmsPassword ($user, $pass)
     sets the shards password.
     setAmsEmail ($user, $mail)
     sets the shards email.

    -Private Member Functions

     confirmPassword ($pass_result, $pass, $confirmpass)
     checks if the confirmPassword matches the original.
    -

    Detailed Description

    -

    handles basic user registration & management functions (shard related).

    -

    The Users class is the basis class of WebUsers, this class provides functions being used by all CMS's and our own www version. The WebUsers class however needs to be reimplemented by using the CMS's it's funcionality. This class handles the writing to the shard db mainly, and in case it's offline: writing to the ams_querycache.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - -
    check_change_password (values)
    -
    -
    - -

    check if the changing of a password is valid.

    -

    a mod/admin doesn't has to fill in the previous password when he wants to change the password, however for changing his own password he has to fill it in.

    -
    Parameters:
    - - -
    $valuesan array containing the CurrentPass, ConfirmNewPass, NewPass and adminChangesOthers
    -
    -
    -
    Returns:
    if it is valid "success will be returned, else an array with errors will be returned.
    - -
    -
    - -
    -
    - - - - - - - - -
    check_Register (values)
    -
    -
    - -

    checks if entered values before registering are valid.

    -
    Parameters:
    - - -
    $valuesarray with Username,Password, ConfirmPass and Email.
    -
    -
    -
    Returns:
    string Info: Returns a string, if input data is valid then "success" is returned, else an array with errors
    - -
    -
    - -
    -
    - - - - - - - - -
    checkEmail (email)
    -
    -
    - -

    wrapper to check if the email address is valid.

    -
    Parameters:
    - - -
    $emailthe email address
    -
    -
    -
    Returns:
    "success", else in case it isn't valid an error will be returned.
    - -
    -
    - -
    -
    - - - - - - - - -
    checkEmailExists (email) [protected]
    -
    -
    - -

    check if email already exists.

    -

    This is the base function, it should be overwritten by the WebUsers class.

    -
    Parameters:
    - - -
    $emailthe email address
    -
    -
    -
    Returns:
    string Info: Returns true or false if the email is in the www db.
    - -

    Reimplemented in WebUsers, and WebUsers.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    checkLoginMatch (user,
    pass 
    ) [protected]
    -
    -
    - -

    check if username and password matches.

    -

    This is the base function, it should be overwritten by the WebUsers class.

    -
    Parameters:
    - - - -
    $userthe inserted username
    $passthe inserted password
    -
    -
    - -

    Reimplemented in WebUsers, and WebUsers.

    - -
    -
    - -
    -
    - - - - - - - - -
    checkPassword (pass)
    -
    -
    - -

    checks if the password is valid.

    -
    Parameters:
    - - -
    $passthe password willing to be used.
    -
    -
    -
    Returns:
    string Info: Returns a string based on if the password is valid, if valid then "success" is returned
    - -
    -
    - -
    -
    - - - - - - - - -
    checkUser (username)
    -
    -
    - -

    checks if entered username is valid.

    -
    Parameters:
    - - -
    $usernamethe username that the user wants to use.
    -
    -
    -
    Returns:
    string Info: Returns a string based on if the username is valid, if valid then "success" is returned
    - -
    -
    - -
    -
    - - - - - - - - -
    checkUserNameExists (username) [protected]
    -
    -
    - -

    check if username already exists.

    -

    This is the base function, it should be overwritten by the WebUsers class.

    -
    Parameters:
    - - -
    $usernamethe username
    -
    -
    -
    Returns:
    string Info: Returns true or false if the user is in the www db.
    - -

    Reimplemented in WebUsers, and WebUsers.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    confirmPassword (pass_result,
    pass,
    confirmpass 
    ) [private]
    -
    -
    - -

    checks if the confirmPassword matches the original.

    -
    Parameters:
    - - - - -
    $pass_resultthe result of the previous password check.
    $passthe original pass.
    $confirmpassthe confirmation password.
    -
    -
    -
    Returns:
    string Info: Verify's $_POST["Password"] is the same as $_POST["ConfirmPass"]
    - -
    -
    - -
    -
    - - - - - - - - -
    static createPermissions (pvalues) [static]
    -
    -
    - -

    creates permissions in the shard db for a user.

    -

    incase the shard is offline it will place it in the ams_querycache.

    -
    Parameters:
    - - -
    $pvalueswith username
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static createUser (values,
    user_id 
    ) [static]
    -
    -
    - -

    creates a user in the shard.

    -

    incase the shard is offline it will place it in the ams_querycache. You have to create a user first in the CMS/WWW and use the id for this function.

    -
    Parameters:
    - - - -
    $valueswith name,pass and mail
    $user_idthe extern id of the user (the id given by the www/CMS)
    -
    -
    -
    Returns:
    ok if it's get correctly added to the shard, else return lib offline and put in libDB, if libDB is also offline return liboffline.
    - -
    -
    - -
    -
    - - - - - - - - -
    static generateSALT (length = 2) [static]
    -
    -
    - -

    generate a SALT.

    -
    Parameters:
    - - -
    $lengththe length of the SALT which is by default 2
    -
    -
    -
    Returns:
    a random salt of 2 chars
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    setAmsEmail (user,
    mail 
    ) [protected]
    -
    -
    - -

    sets the shards email.

    -

    in case the shard is offline, the entry will be stored in the ams_querycache.

    -
    Parameters:
    - - - -
    $userthe usersname of the account of which we want to change the emailaddress.
    $mailthe new email address
    -
    -
    -
    Returns:
    ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    setAmsPassword (user,
    pass 
    ) [protected]
    -
    -
    - -

    sets the shards password.

    -

    in case the shard is offline, the entry will be stored in the ams_querycache.

    -
    Parameters:
    - - - -
    $userthe usersname of the account of which we want to change the password.
    $passthe new password.
    -
    -
    -
    Returns:
    ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
    - -
    -
    - -
    -
    - - - - - - - - -
    validEmail (email)
    -
    -
    - -

    check if the emailaddress structure is valid.

    -
    Parameters:
    - - -
    $emailthe email address
    -
    -
    -
    Returns:
    true or false
    - -
    -
    -
    The documentation for this class was generated from the following file:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classUsers.png b/code/web/docs/ams/html/classUsers.png deleted file mode 100644 index 85efb81d93fecf204cc81a426b84b4385b167b50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmeAS@N?(olHy`uVBq!ia0vp^Q-C;tgBeJkn7zgYNJ#|vgt-3y{~ySF@#br3|Dg#$ z78oBmaDcV*jy#adQ4-`A%m7pb0#{Fk7%?y~nt8f7hEy=VoqLh*umXo`x9^|-{`Z;{ zZtQ%im7Q4>*(<&7`r?Ltd6V7b%&c#kgb46DFuuyt_*JUpFqOIEyy7hnn{ubC%Y{Cj zpS_Uf#1?^vldD^tB^56E?%BaFU^hEh_wm#A61bJij7ZS zFRxJxImftC$?2)g1T7VjRr~=BOd<>97^cqEeI&-f1?GV?%$U}zh=d_w|1Od%k{oaGWq@U54xwWO64itTNiL$_5IB)Z{<0?i)yDP z3Yjc&UJ?KFUg)hN&pn5a7fH6{`|@4qS-`-$;zNL3+5($5tog=rb*9rCq=2Ey;OXk; Jvd$@?2>`e`wS)iw diff --git a/code/web/docs/ams/html/classWebUsers.html b/code/web/docs/ams/html/classWebUsers.html deleted file mode 100644 index edb9aed56..000000000 --- a/code/web/docs/ams/html/classWebUsers.html +++ /dev/null @@ -1,1509 +0,0 @@ - - - - - -Ryzom Account Management System: WebUsers Class Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    - -
    - -

    handles CMS/WWW related functions regarding user management & registration. - More...

    -
    -Inheritance diagram for WebUsers:
    -
    -
    - - -Users -Users - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Public Member Functions

     __construct ($UId=0)
     A constructor.
     set ($values)
     sets the object's attributes.
     checkLoginMatch ($username, $password)
     check if the login username and password match the db.
     getUId ()
     get uId attribute of the object.
     getUsername ()
     get login attribute of the object.
     getEmail ()
     get email attribute of the object.
     getInfo ()
     get basic info of the object.
     getReceiveMail ()
     get receiveMail attribute of the object.
     getLanguage ()
     get language attribute of the object.
     isLoggedIn ()
     check if the user is logged in.
     setPassword ($user, $pass)
     update the password.
     setEmail ($user, $mail)
     update the emailaddress.
     getUsers ()
     return all users.
     __construct ($UId=0)
     A constructor.
     set ($values)
     sets the object's attributes.
     checkLoginMatch ($username, $password)
     check if the login username and password match the db.
     getUId ()
     get uId attribute of the object.
     getUsername ()
     get login attribute of the object.
     getEmail ()
     get email attribute of the object.
     getInfo ()
     get basic info of the object.
     getReceiveMail ()
     get receiveMail attribute of the object.
     getLanguage ()
     get language attribute of the object.
     isLoggedIn ()
     check if the user is logged in.
     setPassword ($user, $pass)
     update the password.
     setEmail ($user, $mail)
     update the emailaddress.
     getUsers ()
     return all users.

    -Static Public Member Functions

    static getId ($username)
     returns te id for a given username
    static getIdFromEmail ($email)
     returns te id for a given emailaddress
    static setReceiveMail ($user, $receivemail)
     update the setReceiveMail value in the db.
    static setLanguage ($user, $language)
     update the language value in the db.
    static getAllUsersQuery ()
     return the query that should get all users.
    static createWebuser ($name, $pass, $mail)
     creates a webuser.
    static getId ($username)
     returns te id for a given username
    static getIdFromEmail ($email)
     returns te id for a given emailaddress
    static setReceiveMail ($user, $receivemail)
     update the setReceiveMail value in the db.
    static setLanguage ($user, $language)
     update the language value in the db.
    static getAllUsersQuery ()
     return the query that should get all users.
    static createWebuser ($name, $pass, $mail)
     creates a webuser.

    -Protected Member Functions

     checkUserNameExists ($username)
     function that checks if a username exists already or not.
     checkEmailExists ($email)
     function that checks if a email exists already or not.
     checkUserNameExists ($username)
     function that checks if a username exists already or not.
     checkEmailExists ($email)
     function that checks if a email exists already or not.

    -Private Attributes

     $uId
     The user id.
     $login
     The username.
     $email
     The email address.
     $firstname
     The users first name.
     $lastname
     The users last name.
     $gender
     The gender.
     $country
     2 letter word matching the country of the user
     $receiveMail
     configuration regarding if the user wants to receive email notifications or not.
     $language
     Language of the user.
    -

    Detailed Description

    -

    handles CMS/WWW related functions regarding user management & registration.

    -

    inherits from the Users class. The methods of this class have to be rewritten according to the CMS's functionality that you wish to use. The drupal_module has a webusers class of its own in the module itself.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    -

    Constructor & Destructor Documentation

    - -
    -
    - - - - - - - - -
    __construct (UId = 0)
    -
    -
    - -

    A constructor.

    -

    loads the object with the UID, if none is given it will use 0.

    -
    Parameters:
    - - -
    $UIdthe UID of the user you want to instantiate.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    __construct (UId = 0)
    -
    -
    - -

    A constructor.

    -

    loads the object with the UID, if none is given it will use 0.

    -
    Parameters:
    - - -
    $UIdthe UID of the user you want to instantiate.
    -
    -
    - -
    -
    -

    Member Function Documentation

    - -
    -
    - - - - - - - - -
    checkEmailExists (email) [protected]
    -
    -
    - -

    function that checks if a email exists already or not.

    -

    This function overrides the function of the base class.

    -
    Parameters:
    - - -
    $emailthe email address in question.
    -
    -
    -
    Returns:
    string Info: Returns 0 if the email address is not in the web db, else a positive number is returned.
    - -

    Reimplemented from Users.

    - -
    -
    - -
    -
    - - - - - - - - -
    checkEmailExists (email) [protected]
    -
    -
    - -

    function that checks if a email exists already or not.

    -

    This function overrides the function of the base class.

    -
    Parameters:
    - - -
    $emailthe email address in question.
    -
    -
    -
    Returns:
    string Info: Returns 0 if the email address is not in the web db, else a positive number is returned.
    - -

    Reimplemented from Users.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    checkLoginMatch (username,
    password 
    )
    -
    -
    - -

    check if the login username and password match the db.

    -
    Parameters:
    - - - -
    $usernamethe inserted username
    $passwordthe inserted password (unhashed)
    -
    -
    -
    Returns:
    the logged in user's db row as array if login was a success, else "fail" will be returned.
    - -

    Reimplemented from Users.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    checkLoginMatch (username,
    password 
    )
    -
    -
    - -

    check if the login username and password match the db.

    -
    Parameters:
    - - - -
    $usernamethe inserted username
    $passwordthe inserted password (unhashed)
    -
    -
    -
    Returns:
    the logged in user's db row as array if login was a success, else "fail" will be returned.
    - -

    Reimplemented from Users.

    - -
    -
    - -
    -
    - - - - - - - - -
    checkUserNameExists (username) [protected]
    -
    -
    - -

    function that checks if a username exists already or not.

    -

    This function overrides the function of the base class.

    -
    Parameters:
    - - -
    $usernamethe username in question
    -
    -
    -
    Returns:
    string Info: Returns 0 if the user is not in the web db, else a positive number is returned.
    - -

    Reimplemented from Users.

    - -
    -
    - -
    -
    - - - - - - - - -
    checkUserNameExists (username) [protected]
    -
    -
    - -

    function that checks if a username exists already or not.

    -

    This function overrides the function of the base class.

    -
    Parameters:
    - - -
    $usernamethe username in question
    -
    -
    -
    Returns:
    string Info: Returns 0 if the user is not in the web db, else a positive number is returned.
    - -

    Reimplemented from Users.

    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static createWebuser (name,
    pass,
    mail 
    ) [static]
    -
    -
    - -

    creates a webuser.

    -

    it will set the language matching to the language cookie setting and add it to the www/CMS's DB.

    -
    Parameters:
    - - - - -
    $namethe username
    $passthe unhashed password
    $mailthe email address
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - -
    static createWebuser (name,
    pass,
    mail 
    ) [static]
    -
    -
    - -

    creates a webuser.

    -

    it will set the language matching to the language cookie setting and add it to the www/CMS's DB.

    -
    Parameters:
    - - - - -
    $namethe username
    $passthe unhashed password
    $mailthe email address
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    static getAllUsersQuery () [static]
    -
    -
    - -

    return the query that should get all users.

    -
    Returns:
    string: the query to receive all users.
    - -
    -
    - -
    -
    - - - - - - - -
    static getAllUsersQuery () [static]
    -
    -
    - -

    return the query that should get all users.

    -
    Returns:
    string: the query to receive all users.
    - -
    -
    - -
    -
    - - - - - - - -
    getEmail ()
    -
    -
    - -

    get email attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getEmail ()
    -
    -
    - -

    get email attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - - -
    static getId (username) [static]
    -
    -
    - -

    returns te id for a given username

    -
    Parameters:
    - - -
    $usernamethe username
    -
    -
    -
    Returns:
    the user's id linked to the username
    - -
    -
    - -
    -
    - - - - - - - - -
    static getId (username) [static]
    -
    -
    - -

    returns te id for a given username

    -
    Parameters:
    - - -
    $usernamethe username
    -
    -
    -
    Returns:
    the user's id linked to the username
    - -
    -
    - -
    -
    - - - - - - - - -
    static getIdFromEmail (email) [static]
    -
    -
    - -

    returns te id for a given emailaddress

    -
    Parameters:
    - - -
    $emailthe emailaddress
    -
    -
    -
    Returns:
    the user's id linked to the emailaddress
    - -
    -
    - -
    -
    - - - - - - - - -
    static getIdFromEmail (email) [static]
    -
    -
    - -

    returns te id for a given emailaddress

    -
    Parameters:
    - - -
    $emailthe emailaddress
    -
    -
    -
    Returns:
    the user's id linked to the emailaddress
    - -
    -
    - -
    -
    - - - - - - - -
    getInfo ()
    -
    -
    - -

    get basic info of the object.

    -
    Returns:
    returns an array in the form of Array('FirstName' => $this->firstname, 'LastName' => $this->lastname, 'Gender' => $this->gender, 'Country' => $this->country, 'ReceiveMail' => $this->receiveMail)
    - -
    -
    - -
    -
    - - - - - - - -
    getInfo ()
    -
    -
    - -

    get basic info of the object.

    -
    Returns:
    returns an array in the form of Array('FirstName' => $this->firstname, 'LastName' => $this->lastname, 'Gender' => $this->gender, 'Country' => $this->country, 'ReceiveMail' => $this->receiveMail)
    - -
    -
    - -
    -
    - - - - - - - -
    getLanguage ()
    -
    -
    - -

    get language attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getLanguage ()
    -
    -
    - -

    get language attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getReceiveMail ()
    -
    -
    - -

    get receiveMail attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getReceiveMail ()
    -
    -
    - -

    get receiveMail attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUId ()
    -
    -
    - -

    get uId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUId ()
    -
    -
    - -

    get uId attribute of the object.

    - -
    -
    - -
    -
    - - - - - - - -
    getUsername ()
    -
    -
    - -

    get login attribute of the object.

    -

    (username)

    - -
    -
    - -
    -
    - - - - - - - -
    getUsername ()
    -
    -
    - -

    get login attribute of the object.

    -

    (username)

    - -
    -
    - -
    -
    - - - - - - - -
    getUsers ()
    -
    -
    - -

    return all users.

    -
    Returns:
    return an array of users
    - -
    -
    - -
    -
    - - - - - - - -
    getUsers ()
    -
    -
    - -

    return all users.

    -
    Returns:
    return an array of users
    - -
    -
    - -
    -
    - - - - - - - -
    isLoggedIn ()
    -
    -
    - -

    check if the user is logged in.

    -
    Returns:
    true or false
    - -
    -
    - -
    -
    - - - - - - - -
    isLoggedIn ()
    -
    -
    - -

    check if the user is logged in.

    -
    Returns:
    true or false
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - -
    set (values)
    -
    -
    - -

    sets the object's attributes.

    -
    Parameters:
    - - -
    $valuesshould be an array.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    setEmail (user,
    mail 
    )
    -
    -
    - -

    update the emailaddress.

    -

    update the emailaddress in the shard + update the emailaddress in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $mailthe new emailaddress.
    -
    -
    -
    Returns:
    ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    setEmail (user,
    mail 
    )
    -
    -
    - -

    update the emailaddress.

    -

    update the emailaddress in the shard + update the emailaddress in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $mailthe new emailaddress.
    -
    -
    -
    Returns:
    ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static setLanguage (user,
    language 
    ) [static]
    -
    -
    - -

    update the language value in the db.

    -

    update the language in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $languagethe new language value.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static setLanguage (user,
    language 
    ) [static]
    -
    -
    - -

    update the language value in the db.

    -

    update the language in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $languagethe new language value.
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    setPassword (user,
    pass 
    )
    -
    -
    - -

    update the password.

    -

    update the password in the shard + update the password in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $passthe new password.
    -
    -
    -
    Returns:
    ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    setPassword (user,
    pass 
    )
    -
    -
    - -

    update the password.

    -

    update the password in the shard + update the password in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $passthe new password.
    -
    -
    -
    Returns:
    ok if it worked, if the lib or shard is offline it will return liboffline or shardoffline.
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static setReceiveMail (user,
    receivemail 
    ) [static]
    -
    -
    - -

    update the setReceiveMail value in the db.

    -

    update the receiveMail in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $receivemailthe receivemail setting .
    -
    -
    - -
    -
    - -
    -
    - - - - - - - - - - - - - - - - - - -
    static setReceiveMail (user,
    receivemail 
    ) [static]
    -
    -
    - -

    update the setReceiveMail value in the db.

    -

    update the receiveMail in the www/CMS version.

    -
    Parameters:
    - - - -
    $userthe username
    $receivemailthe receivemail setting .
    -
    -
    - -
    -
    -

    Field Documentation

    - -
    -
    - - - - -
    $country [private]
    -
    -
    - -

    2 letter word matching the country of the user

    - -
    -
    - -
    -
    - - - - -
    $email [private]
    -
    -
    - -

    The email address.

    - -
    -
    - -
    -
    - - - - -
    $firstname [private]
    -
    -
    - -

    The users first name.

    - -
    -
    - -
    -
    - - - - -
    $gender [private]
    -
    -
    - -

    The gender.

    - -
    -
    - -
    -
    - - - - -
    $language [private]
    -
    -
    - -

    Language of the user.

    - -
    -
    - -
    -
    - - - - -
    $lastname [private]
    -
    -
    - -

    The users last name.

    - -
    -
    - -
    -
    - - - - -
    $login [private]
    -
    -
    - -

    The username.

    - -
    -
    - -
    -
    - - - - -
    $receiveMail [private]
    -
    -
    - -

    configuration regarding if the user wants to receive email notifications or not.

    - -
    -
    - -
    -
    - - - - -
    $uId [private]
    -
    -
    - -

    The user id.

    - -
    -
    -
    The documentation for this class was generated from the following files:
      -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/autoload/webusers.php
    • -
    • /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/classWebUsers.png b/code/web/docs/ams/html/classWebUsers.png deleted file mode 100644 index 8aca4ddb0b262efdc8094495b843448de949273e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 428 zcmeAS@N?(olHy`uVBq!ia0vp^Q-C;tgBeJkn7zgYNJ#|vgt-3y{~ySF@#br3|Dg#$ z78oBmaDcV*jy#adQ4-`A%m7pb0#{Fk7%?y~T6?-UhEy=VoqJH|kOGg3=iG|-MhR?PTb-MS$#KkkE_!G({GDkW^Y;@o+g&?_V?xT!|V2PcwK%t zYt_xY)^AM?J%4*?<~}~_IO7&2k%imZoiv&c-Kw3E|Klug;+wLTPjX(Z8*dAqs@4!a zmglYU&dy1&E1>0srSHrd%})QEBxSSAJ7$)mT6=g-Sw-*Xc=6}%bjQ~2$1F=vUh#Gfw*2d% z!L@>CM(fKKL+e`AE2+MsJ=_aU-FgTe~DWM4f4c)sa diff --git a/code/web/docs/ams/html/classes.html b/code/web/docs/ams/html/classes.html deleted file mode 100644 index 33b1ba697..000000000 --- a/code/web/docs/ams/html/classes.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - -Ryzom Account Management System: Data Structure Index - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    -
    -
    Data Structure Index
    -
    -
    -
    A | D | F | G | H | I | M | P | Q | S | T | U | W
    - - - - - - - - - - - - - - -
      A  
    -
      H  
    -
      P  
    -
      T  
    -
    Ticket_User   
      U  
    -
    Assigned   Helpers   Pagination   Ticket   
      D  
    -
      I  
    -
      Q  
    -
    Ticket_Category   Users   
    Ticket_Content   
      W  
    -
    DBLayer   In_Support_Group   Querycache   Ticket_Info   
      F  
    -
      M  
    -
      S  
    -
    Ticket_Log   WebUsers   
    Ticket_Queue   
    Forwarded   Mail_Handler   Support_Group   Ticket_Queue_Handler   
      G  
    -
    MyCrypt   Sync   Ticket_Reply   
    Gui_Elements   
    -
    A | D | F | G | H | I | M | P | Q | S | T | U | W
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/closed.png b/code/web/docs/ams/html/closed.png deleted file mode 100644 index b7d4bd9fef2272c74b94762c9e2496177017775e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VuAVNAAr*{o?>h22DDp4|bgj*t z)u^AqcA-V@guRYpb17F<&b?_~8HV>~XqWvB;^$!VVSTy0!eQcJp_yD7TIQA>7dijs YXf6~H5cs^Q6KEiVr>mdKI;Vst0NsWqGynhq diff --git a/code/web/docs/ams/html/create__ticket_8php.html b/code/web/docs/ams/html/create__ticket_8php.html deleted file mode 100644 index ba969a5eb..000000000 --- a/code/web/docs/ams/html/create__ticket_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/create_ticket.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/create_ticket.php File Reference
    -
    -
    - - - - -

    -Functions

     create_ticket ()
     This function is beign used to create a new ticket.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    create_ticket ()
    -
    -
    - -

    This function is beign used to create a new ticket.

    -

    It will first check if the user who executed this function is the person of whom the setting is or if it's a mod/admin. If this is not the case the page will be redirected to an error page. next it will filter the POST data and it will try to create the new ticket. Afterwards a redirecion to the ticket will occur.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/createticket_8php.html b/code/web/docs/ams/html/createticket_8php.html deleted file mode 100644 index 8b9fd9b2f..000000000 --- a/code/web/docs/ams/html/createticket_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/createticket.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/createticket.php File Reference
    -
    -
    - - - - -

    -Functions

     createticket ()
     This function is beign used to load info that's needed for the createticket page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    createticket ()
    -
    -
    - -

    This function is beign used to load info that's needed for the createticket page.

    -

    the $_GET['user_id'] identifies for which user you try to create a ticket. A normal user can only create a ticket for himself, a mod/admin however can also create tickets for other users. It will also load all categories and return these, they will be used by the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/dashboard_8php.html b/code/web/docs/ams/html/dashboard_8php.html deleted file mode 100644 index 593ae1be9..000000000 --- a/code/web/docs/ams/html/dashboard_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/dashboard.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/dashboard.php File Reference
    -
    -
    - - - - -

    -Functions

     dashboard ()
     This function is beign used to load info that's needed for the dashboard page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    dashboard ()
    -
    -
    - -

    This function is beign used to load info that's needed for the dashboard page.

    -

    check if the person who wants to view this page is a mod/admin, if this is not the case, he will be redirected to an error page. next it will fetch a lot of information regarding to the status of the ticket system (eg return the total amount of tickets) and return this information so it can be used by the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/db.png b/code/web/docs/ams/html/db.png deleted file mode 100644 index 63cb4c92bc242b230225fec89307e0bbb87a538b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205565 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

    0C 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 diff --git a/code/web/docs/ams/html/dblayer_8php.html b/code/web/docs/ams/html/dblayer_8php.html deleted file mode 100644 index 278d76934..000000000 --- a/code/web/docs/ams/html/dblayer_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php File Reference - - - - - - - - - - - -

    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  DBLayer
     Handles the database connections. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/deprecated.html b/code/web/docs/ams/html/deprecated.html deleted file mode 100644 index 932150748..000000000 --- a/code/web/docs/ams/html/deprecated.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - -Ryzom Account Management System: Deprecated List - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - -
    -
    -
    -
    Deprecated List
    -
    -
    -
    -
    Global Support_Group ()
    -
    should be removed in the future, because getGroups does the same.
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/design.html b/code/web/docs/ams/html/design.html deleted file mode 100644 index 5c3f1db25..000000000 --- a/code/web/docs/ams/html/design.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - -Ryzom Account Management System: Design Info - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - -
    -
    -
    -
    Design Info
    -
    -
    -

    -A brief introduction to the design of the AMS

    -

    We will take a look at the current db design, the way the classes are designed, the way the WWW version works and how it was reused in the drupal module.

    -

    -The database structure

    -

    My project started with the design of our database. I had to think about the advanced AMS features in advance. This is the reason why there are still a few unused DB tables in the design, the plan however is to use those as soon as possible by implementing the extra features.

    -

    The tables that are unused are the following:

    -
      -
    • -ticket_group
    • -
    • -in_group
    • -
    • -tag
    • -
    • -tagged
    • -
    -

    The idea for the ticket_groups was to provide the ability to bundle multiple tickets together in groups, this could be used for tickets that are alike or are in a weird way related. The idea for the tagging was to provide an extra system that allows to query tickets based on their tags (datamining). These features can be easily added in the future!

    -

    Let's take a look at the 'used' tables. The database structure is shown in the image below. For each table I made a matching class that handles the info of that table.

    -

    Quite central you can see the ticket table. As you can see, a ticket has a ticket_category field and author field, these hold the id of the related row in the ticket_category and ticket_user table. There's also the relation between a ticket and it's log entries, this is done by the ticket foreign key in the ticket_log table. The same counts for most other tables that are related to the ticket, they all got a ticket column used as foreign key.

    -

    Another thing that you might notice is the separation between ticket_reply and ticket_content, this is a 1-to-1 relation and this makes it easier to search between the replies if we only need their general information without having to take care of the content. The ticket_user is another quite important table that's being foreigned keyed by the others. It holds the permission of a user and the externID links to an ID given by the CMS(or our own www version)

    -

    Most things are pretty clear and straight forward, you can find the MYSQL Workbench file in the ryzom_ams/www/html/sql folder, which might give a better overview and can be used to update the DB easily when adding/modifying features in the future.

    -
    -db.png -
    -

    -Technologies used

    - -

    -Information regarding the structure

    -

    As you might have noticed, the ryzom_ams directory contains 3 directories: the ams_lib dir, the www dir and a drupal_module dir.

    -

    the ams_lib contains the following important dirs/files:

    -
      -
    • -autoload dir holds all classes of the lib
    • -
    • -cron dir holds the cron functions regarding email and the ams_querycache
    • -
    • -ingame_templates dir holds the templates that are being used while ingame
    • -
    • -smarty dir the smarty files (http://www.smarty.net/)
    • -
    • -translations dir multiple .ini files, one for each language that's being supported.
    • -
    • -libinclude.php php file that holds the __autoload function
    • -
    -

    the www contains the following important dirs/files:

    -
      -
    • -autoload dir holds the webusers.php file (which extends the Users.php file in the lib)
    • -
    • -func dir holds php files that contain a function that is being executed after filling in a form.
    • -
    • -inc dir holds php files that contain a function that is being executed before loading a specific file.
    • -
    • -templates dir holds the templates being used outgame.
    • -
    • -config.php php file that holds configuration settings
    • -
    -

    the drupal_module contains the following important dirs/files:

    -
      -
    • -autoload dir holds the webusers.php file that uses drupal functions (which extends the Users.php file in the lib)
    • -
    • -func dir holds php files that contain a function that is being executed after filling in a form.
    • -
    • -inc dir holds php files that contain a function that is being executed before loading a specific file.
    • -
    • -templates dir holds the templates being used outgame.
    • -
    • -config.php php file that holds configuration settings
    • -
    • -ryzommanage.info drupal file that holds information being used by drupal
    • -
    • -ryzommanage.install drupal file thats being used for installing the module
    • -
    • -ryzommanage.module drupal file that holds all functionality that's being needed to handle the AMS in drupal. (read more about it at the wiki page)
    • -
    -

    Important: the func dir and inc dir in the drupal_module are almost empty, that's because the inc/func directories of the WWW version can be copied to the drupal version, they are exactly the same. However, because the drupal_module isn't completely up to date, the settings page doesn't has the extra fields (like gender,country,..) therefore the ingame template file, inc files related to that are still in the module.

    -

    -How does the page loading work?

    -
    -info.jpg -
    -

    -How are the classes being used?

    -

    Like I mentioned above, each DB table has a class related that handles the data linked to that table and has functions working with that data.

    -

    The private attributes of each class are similar to the fields in the DB table. Every class also has the following functions:

    -
      -
    • -function __construct()
    • -
    • -function set($values)
    • -
    • -function create()
    • -
    • -function delete()
    • -
    • -function load( $id) or named similar
    • -
    • -some also have: update ()
    • -
    -

    These methods are being used by the public static functions of that class, which represent the 'real' AMS-functions, the ones being used by the inc/func files.

    -

    You can reference for example the Support_Group class's information, which shows this setup!

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/doxygen.css b/code/web/docs/ams/html/doxygen.css deleted file mode 100644 index cee0d06b5..000000000 --- a/code/web/docs/ams/html/doxygen.css +++ /dev/null @@ -1,949 +0,0 @@ -/* The standard CSS for doxygen */ - -body, table, div, p, dl { - font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; - font-size: 13px; - line-height: 1.3; -} - -/* @group Heading Levels */ - -h1 { - font-size: 150%; -} - -.title { - font-size: 150%; - font-weight: bold; - margin: 10px 2px; -} - -h2 { - font-size: 120%; -} - -h3 { - font-size: 100%; -} - -dt { - font-weight: bold; -} - -div.multicol { - -moz-column-gap: 1em; - -webkit-column-gap: 1em; - -moz-column-count: 3; - -webkit-column-count: 3; -} - -p.startli, p.startdd, p.starttd { - margin-top: 2px; -} - -p.endli { - margin-bottom: 0px; -} - -p.enddd { - margin-bottom: 4px; -} - -p.endtd { - margin-bottom: 2px; -} - -/* @end */ - -caption { - font-weight: bold; -} - -span.legend { - font-size: 70%; - text-align: center; -} - -h3.version { - font-size: 90%; - text-align: center; -} - -div.qindex, div.navtab{ - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; -} - -div.qindex, div.navpath { - width: 100%; - line-height: 140%; -} - -div.navtab { - margin-right: 15px; -} - -/* @group Link Styling */ - -a { - color: #3D578C; - font-weight: normal; - text-decoration: none; -} - -.contents a:visited { - color: #4665A2; -} - -a:hover { - text-decoration: underline; -} - -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: #9CAFD4; - color: #ffffff; - border: 1px double #869DCA; -} - -.contents a.qindexHL:visited { - color: #ffffff; -} - -a.el { - font-weight: bold; -} - -a.elRef { -} - -a.code, a.code:visited { - color: #4665A2; -} - -a.codeRef, a.codeRef:visited { - color: #4665A2; -} - -/* @end */ - -dl.el { - margin-left: -1cm; -} - -.fragment { - font-family: monospace, fixed; - font-size: 105%; -} - -pre.fragment { - border: 1px solid #C4CFE5; - background-color: #FBFCFD; - padding: 4px 6px; - margin: 4px 8px 4px 2px; - overflow: auto; - word-wrap: break-word; - font-size: 9pt; - line-height: 125%; -} - -div.ah { - background-color: black; - font-weight: bold; - color: #ffffff; - margin-bottom: 3px; - margin-top: 3px; - padding: 0.2em; - border: solid thin #333; - border-radius: 0.5em; - -webkit-border-radius: .5em; - -moz-border-radius: .5em; - box-shadow: 2px 2px 3px #999; - -webkit-box-shadow: 2px 2px 3px #999; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); - background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); -} - -div.groupHeader { - margin-left: 16px; - margin-top: 12px; - font-weight: bold; -} - -div.groupText { - margin-left: 16px; - font-style: italic; -} - -body { - background-color: white; - color: black; - margin: 0; -} - -div.contents { - margin-top: 10px; - margin-left: 8px; - margin-right: 8px; -} - -td.indexkey { - background-color: #EBEFF6; - font-weight: bold; - border: 1px solid #C4CFE5; - margin: 2px 0px 2px 0; - padding: 2px 10px; - white-space: nowrap; - vertical-align: top; -} - -td.indexvalue { - background-color: #EBEFF6; - border: 1px solid #C4CFE5; - padding: 2px 10px; - margin: 2px 0px; -} - -tr.memlist { - background-color: #EEF1F7; -} - -p.formulaDsp { - text-align: center; -} - -img.formulaDsp { - -} - -img.formulaInl { - vertical-align: middle; -} - -div.center { - text-align: center; - margin-top: 0px; - margin-bottom: 0px; - padding: 0px; -} - -div.center img { - border: 0px; -} - -address.footer { - text-align: right; - padding-right: 12px; -} - -img.footer { - border: 0px; - vertical-align: middle; -} - -/* @group Code Colorization */ - -span.keyword { - color: #008000 -} - -span.keywordtype { - color: #604020 -} - -span.keywordflow { - color: #e08000 -} - -span.comment { - color: #800000 -} - -span.preprocessor { - color: #806020 -} - -span.stringliteral { - color: #002080 -} - -span.charliteral { - color: #008080 -} - -span.vhdldigit { - color: #ff00ff -} - -span.vhdlchar { - color: #000000 -} - -span.vhdlkeyword { - color: #700070 -} - -span.vhdllogic { - color: #ff0000 -} - -/* @end */ - -/* -.search { - color: #003399; - font-weight: bold; -} - -form.search { - margin-bottom: 0px; - margin-top: 0px; -} - -input.search { - font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -*/ - -td.tiny { - font-size: 75%; -} - -.dirtab { - padding: 4px; - border-collapse: collapse; - border: 1px solid #A3B4D7; -} - -th.dirtab { - background: #EBEFF6; - font-weight: bold; -} - -hr { - height: 0px; - border: none; - border-top: 1px solid #4A6AAA; -} - -hr.footer { - height: 1px; -} - -/* @group Member Descriptions */ - -table.memberdecls { - border-spacing: 0px; - padding: 0px; -} - -.mdescLeft, .mdescRight, -.memItemLeft, .memItemRight, -.memTemplItemLeft, .memTemplItemRight, .memTemplParams { - background-color: #F9FAFC; - border: none; - margin: 4px; - padding: 1px 0 0 8px; -} - -.mdescLeft, .mdescRight { - padding: 0px 8px 4px 8px; - color: #555; -} - -.memItemLeft, .memItemRight, .memTemplParams { - border-top: 1px solid #C4CFE5; -} - -.memItemLeft, .memTemplItemLeft { - white-space: nowrap; -} - -.memItemRight { - width: 100%; -} - -.memTemplParams { - color: #4665A2; - white-space: nowrap; -} - -/* @end */ - -/* @group Member Details */ - -/* Styles for detailed member documentation */ - -.memtemplate { - font-size: 80%; - color: #4665A2; - font-weight: normal; - margin-left: 9px; -} - -.memnav { - background-color: #EBEFF6; - border: 1px solid #A3B4D7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} - -.mempage { - width: 100%; -} - -.memitem { - padding: 0; - margin-bottom: 10px; - margin-right: 5px; -} - -.memname { - white-space: nowrap; - font-weight: bold; - margin-left: 6px; -} - -.memproto, dl.reflist dt { - border-top: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 6px 0px 6px 0px; - color: #253555; - font-weight: bold; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - /* opera specific markup */ - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - border-top-right-radius: 8px; - border-top-left-radius: 8px; - /* firefox specific markup */ - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - -moz-border-radius-topright: 8px; - -moz-border-radius-topleft: 8px; - /* webkit specific markup */ - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - -webkit-border-top-right-radius: 8px; - -webkit-border-top-left-radius: 8px; - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - -} - -.memdoc, dl.reflist dd { - border-bottom: 1px solid #A8B8D9; - border-left: 1px solid #A8B8D9; - border-right: 1px solid #A8B8D9; - padding: 2px 5px; - background-color: #FBFCFD; - border-top-width: 0; - /* opera specific markup */ - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; - box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - /* firefox specific markup */ - -moz-border-radius-bottomleft: 8px; - -moz-border-radius-bottomright: 8px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; - background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7); - /* webkit specific markup */ - -webkit-border-bottom-left-radius: 8px; - -webkit-border-bottom-right-radius: 8px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); - background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F7F8FB), to(#EEF1F7)); -} - -dl.reflist dt { - padding: 5px; -} - -dl.reflist dd { - margin: 0px 0px 10px 0px; - padding: 5px; -} - -.paramkey { - text-align: right; -} - -.paramtype { - white-space: nowrap; -} - -.paramname { - color: #602020; - white-space: nowrap; -} -.paramname em { - font-style: normal; -} - -.params, .retval, .exception, .tparams { - border-spacing: 6px 2px; -} - -.params .paramname, .retval .paramname { - font-weight: bold; - vertical-align: top; -} - -.params .paramtype { - font-style: italic; - vertical-align: top; -} - -.params .paramdir { - font-family: "courier new",courier,monospace; - vertical-align: top; -} - - - - -/* @end */ - -/* @group Directory (tree) */ - -/* for the tree view */ - -.ftvtree { - font-family: sans-serif; - margin: 0px; -} - -/* these are for tree view when used as main index */ - -.directory { - font-size: 9pt; - font-weight: bold; - margin: 5px; -} - -.directory h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} - -/* -The following two styles can be used to replace the root node title -with an image of your choice. Simply uncomment the next two styles, -specify the name of your image and be sure to set 'height' to the -proper pixel height of your image. -*/ - -/* -.directory h3.swap { - height: 61px; - background-repeat: no-repeat; - background-image: url("yourimage.gif"); -} -.directory h3.swap span { - display: none; -} -*/ - -.directory > h3 { - margin-top: 0; -} - -.directory p { - margin: 0px; - white-space: nowrap; -} - -.directory div { - display: none; - margin: 0px; -} - -.directory img { - vertical-align: -30%; -} - -/* these are for tree view when not used as main index */ - -.directory-alt { - font-size: 100%; - font-weight: bold; -} - -.directory-alt h3 { - margin: 0px; - margin-top: 1em; - font-size: 11pt; -} - -.directory-alt > h3 { - margin-top: 0; -} - -.directory-alt p { - margin: 0px; - white-space: nowrap; -} - -.directory-alt div { - display: none; - margin: 0px; -} - -.directory-alt img { - vertical-align: -30%; -} - -/* @end */ - -div.dynheader { - margin-top: 8px; -} - -address { - font-style: normal; - color: #2A3D61; -} - -table.doxtable { - border-collapse:collapse; -} - -table.doxtable td, table.doxtable th { - border: 1px solid #2D4068; - padding: 3px 7px 2px; -} - -table.doxtable th { - background-color: #374F7F; - color: #FFFFFF; - font-size: 110%; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; -} - -table.fieldtable { - width: 100%; - margin-bottom: 10px; - border: 1px solid #A8B8D9; - border-spacing: 0px; - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; - -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); - box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); -} - -.fieldtable td, .fieldtable th { - padding: 3px 7px 2px; -} - -.fieldtable td.fieldtype, .fieldtable td.fieldname { - white-space: nowrap; - border-right: 1px solid #A8B8D9; - border-bottom: 1px solid #A8B8D9; - vertical-align: top; -} - -.fieldtable td.fielddoc { - border-bottom: 1px solid #A8B8D9; - width: 100%; -} - -.fieldtable tr:last-child td { - border-bottom: none; -} - -.fieldtable th { - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; - font-size: 90%; - color: #253555; - padding-bottom: 4px; - padding-top: 5px; - text-align:left; - -moz-border-radius-topleft: 4px; - -moz-border-radius-topright: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom: 1px solid #A8B8D9; -} - - -.tabsearch { - top: 0px; - left: 10px; - height: 36px; - background-image: url('tab_b.png'); - z-index: 101; - overflow: hidden; - font-size: 13px; -} - -.navpath ul -{ - font-size: 11px; - background-image:url('tab_b.png'); - background-repeat:repeat-x; - height:30px; - line-height:30px; - color:#8AA0CC; - border:solid 1px #C2CDE4; - overflow:hidden; - margin:0px; - padding:0px; -} - -.navpath li -{ - list-style-type:none; - float:left; - padding-left:10px; - padding-right:15px; - background-image:url('bc_s.png'); - background-repeat:no-repeat; - background-position:right; - color:#364D7C; -} - -.navpath li.navelem a -{ - height:32px; - display:block; - text-decoration: none; - outline: none; -} - -.navpath li.navelem a:hover -{ - color:#6884BD; -} - -.navpath li.footer -{ - list-style-type:none; - float:right; - padding-left:10px; - padding-right:15px; - background-image:none; - background-repeat:no-repeat; - background-position:right; - color:#364D7C; - font-size: 8pt; -} - - -div.summary -{ - float: right; - font-size: 8pt; - padding-right: 5px; - width: 50%; - text-align: right; -} - -div.summary a -{ - white-space: nowrap; -} - -div.ingroups -{ - margin-left: 5px; - font-size: 8pt; - padding-left: 5px; - width: 50%; - text-align: left; -} - -div.ingroups a -{ - white-space: nowrap; -} - -div.header -{ - background-image:url('nav_h.png'); - background-repeat:repeat-x; - background-color: #F9FAFC; - margin: 0px; - border-bottom: 1px solid #C4CFE5; -} - -div.headertitle -{ - padding: 5px 5px 5px 7px; -} - -dl -{ - padding: 0 0 0 10px; -} - -dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug -{ - border-left:4px solid; - padding: 0 0 0 6px; -} - -dl.note -{ - border-color: #D0C000; -} - -dl.warning, dl.attention -{ - border-color: #FF0000; -} - -dl.pre, dl.post, dl.invariant -{ - border-color: #00D000; -} - -dl.deprecated -{ - border-color: #505050; -} - -dl.todo -{ - border-color: #00C0E0; -} - -dl.test -{ - border-color: #3030E0; -} - -dl.bug -{ - border-color: #C08050; -} - -#projectlogo -{ - text-align: center; - vertical-align: bottom; - border-collapse: separate; -} - -#projectlogo img -{ - border: 0px none; -} - -#projectname -{ - font: 300% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 2px 0px; -} - -#projectbrief -{ - font: 120% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#projectnumber -{ - font: 50% Tahoma, Arial,sans-serif; - margin: 0px; - padding: 0px; -} - -#titlearea -{ - padding: 0px; - margin: 0px; - width: 100%; - border-bottom: 1px solid #5373B4; -} - -.image -{ - text-align: center; -} - -.dotgraph -{ - text-align: center; -} - -.mscgraph -{ - text-align: center; -} - -.caption -{ - font-weight: bold; -} - -div.zoom -{ - border: 1px solid #90A5CE; -} - -dl.citelist { - margin-bottom:50px; -} - -dl.citelist dt { - color:#334975; - float:left; - font-weight:bold; - margin-right:10px; - padding:5px; -} - -dl.citelist dd { - margin:2px 0; - padding:5px 0; -} - -@media print -{ - #top { display: none; } - #side-nav { display: none; } - #nav-path { display: none; } - body { overflow:visible; } - h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } - .summary { display: none; } - .memitem { page-break-inside: avoid; } - #doc-content - { - margin-left:0 !important; - height:auto !important; - width:auto !important; - overflow:inherit; - display:inline; - } - pre.fragment - { - overflow: visible; - text-wrap: unrestricted; - white-space: -moz-pre-wrap; /* Moz */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - white-space: pre-wrap; /* CSS3 */ - word-wrap: break-word; /* IE 5.5+ */ - } -} - diff --git a/code/web/docs/ams/html/doxygen.png b/code/web/docs/ams/html/doxygen.png deleted file mode 100644 index 635ed52fce7057ac24df92ec7664088a881fa5d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3942 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 A+yDRo diff --git a/code/web/docs/ams/html/drupal__module_2ryzommanage_2autoload_2webusers_8php.html b/code/web/docs/ams/html/drupal__module_2ryzommanage_2autoload_2webusers_8php.html deleted file mode 100644 index 6cd2773c7..000000000 --- a/code/web/docs/ams/html/drupal__module_2ryzommanage_2autoload_2webusers_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/autoload/webusers.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/autoload/webusers.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  WebUsers
     handles CMS/WWW related functions regarding user management & registration. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/drupal__module_2ryzommanage_2config_8php.html b/code/web/docs/ams/html/drupal__module_2ryzommanage_2config_8php.html deleted file mode 100644 index 612e717e2..000000000 --- a/code/web/docs/ams/html/drupal__module_2ryzommanage_2config_8php.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/config.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/config.php File Reference
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Variables

     $cfg ['db']['web']['host'] = variable_get('ryzommanage_webserverurl', 'localhost')
     This file contains all variables needed by other php scripts.
     $cfg ['db']['web']['port'] = variable_get('ryzommanage_webmysqlport', '3306')
     $cfg ['db']['web']['name'] = variable_get('ryzommanage_webdbname', 'drupal')
     $cfg ['db']['web']['user'] = variable_get('ryzommanage_webusername', 'shard')
     $cfg ['db']['web']['pass'] = variable_get('ryzommanage_webpassword', '')
     $cfg ['db']['lib']['host'] = variable_get('ryzommanage_libserverurl', 'localhost')
     $cfg ['db']['lib']['port'] = variable_get('ryzommanage_libmysqlport', '3306')
     $cfg ['db']['lib']['name'] = variable_get('ryzommanage_libdbname', 'ryzom_ams_lib')
     $cfg ['db']['lib']['user'] = variable_get('ryzommanage_libusername', 'shard')
     $cfg ['db']['lib']['pass'] = variable_get('ryzommanage_libpassword', '')
     $cfg ['db']['shard']['host'] = variable_get('ryzommanage_shardserverurl', 'localhost')
     $cfg ['db']['shard']['port'] = variable_get('ryzommanage_shardmysqlport', '3306')
     $cfg ['db']['shard']['name'] = variable_get('ryzommanage_sharddbname', 'nel')
     $cfg ['db']['shard']['user'] = variable_get('ryzommanage_shardusername', 'shard')
     $cfg ['db']['shard']['pass'] = variable_get('ryzommanage_shardpassword', '')
     $cfg ['db']['ring']['host'] = variable_get('ryzommanage_ringserverurl', 'localhost')
     $cfg ['db']['ring']['port'] = variable_get('ryzommanage_ringmysqlport', '3306')
     $cfg ['db']['ring']['name'] = variable_get('ryzommanage_ringdbname', 'ring_open')
     $cfg ['db']['ring']['user'] = variable_get('ryzommanage_ringusername', 'shard')
     $cfg ['db']['ring']['pass'] = variable_get('ryzommanage_ringpassword', '')
     $cfg ['mail']['default_mailserver'] = '{imap.gmail.com:993/imap/ssl}INBOX'
     $cfg ['mail']['default_groupemail'] = 'amsryzom@gmail.com'
     $cfg ['mail']['default_groupname'] = 'Ryzomcore Support'
     $cfg ['mail']['default_username'] = 'amsryzom@gmail.com'
     $cfg ['mail']['default_password'] = 'lol123bol'
     $cfg ['mail']['host'] = "ryzomcore.com"
     $SUPPORT_GROUP_IMAP_CRYPTKEY = "azerty"
     $TICKET_MAILING_SUPPORT = false
     $MAIL_DIR = "/tmp/mail"
     $MAIL_LOG_PATH = "/tmp/mail/cron_mail.log"
     $cfg ['crypt']['key'] = 'Sup3rS3cr3tStuff'
     $cfg ['crypt']['enc_method'] = 'AES-256-CBC'
     $cfg ['crypt']['hash_method'] = "SHA512"
     $TOS_URL = variable_get('ryzommanage_TOS', 'www.mytosurlhere.com')
     $ALLOW_UNKNOWN = true
     $CREATE_RING = true
     $AMS_LIB = dirname( __FILE__ ) . '/ams_lib'
     $AMS_TRANS = $AMS_LIB . '/translations'
     $AMS_CACHEDIR = $AMS_LIB . '/cache'
     $SITEBASE = dirname( __FILE__ )
     $BASE_WEBPATH = 'http://localhost:40917/drupal'
     $IMAGELOC_WEBPATH = $BASE_WEBPATH. '/sites/all/modules/ryzommanage/ams_lib/img'
     $WEBPATH = $BASE_WEBPATH .'/ams'
     $INGAME_WEBPATH = $BASE_WEBPATH . '/ingame'
     $CONFIG_PATH = dirname( __FILE__ )
     $DEFAULT_LANGUAGE = 'en'
     $TICKET_LOGGING = true
     $TIME_FORMAT = "m-d-Y H:i:s"
     $INGAME_LAYOUT = "basic"
     $FORCE_INGAME = false
    -

    Variable Documentation

    - -
    -
    - - - - -
    $ALLOW_UNKNOWN = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $AMS_CACHEDIR = $AMS_LIB . '/cache'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $AMS_LIB = dirname( __FILE__ ) . '/ams_lib'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $AMS_TRANS = $AMS_LIB . '/translations'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $BASE_WEBPATH = 'http://localhost:40917/drupal'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['host'] = variable_get('ryzommanage_webserverurl', 'localhost')
    -
    -
    - -

    This file contains all variables needed by other php scripts.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['port'] = variable_get('ryzommanage_webmysqlport', '3306')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['name'] = variable_get('ryzommanage_webdbname', 'drupal')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['user'] = variable_get('ryzommanage_webusername', 'shard')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['pass'] = variable_get('ryzommanage_webpassword', '')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['host'] = variable_get('ryzommanage_libserverurl', 'localhost')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['port'] = variable_get('ryzommanage_libmysqlport', '3306')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['name'] = variable_get('ryzommanage_libdbname', 'ryzom_ams_lib')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['user'] = variable_get('ryzommanage_libusername', 'shard')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['pass'] = variable_get('ryzommanage_libpassword', '')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['host'] = variable_get('ryzommanage_shardserverurl', 'localhost')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['port'] = variable_get('ryzommanage_shardmysqlport', '3306')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['name'] = variable_get('ryzommanage_sharddbname', 'nel')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['user'] = variable_get('ryzommanage_shardusername', 'shard')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['pass'] = variable_get('ryzommanage_shardpassword', '')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['host'] = variable_get('ryzommanage_ringserverurl', 'localhost')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['port'] = variable_get('ryzommanage_ringmysqlport', '3306')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['name'] = variable_get('ryzommanage_ringdbname', 'ring_open')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['user'] = variable_get('ryzommanage_ringusername', 'shard')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['pass'] = variable_get('ryzommanage_ringpassword', '')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_mailserver'] = '{imap.gmail.com:993/imap/ssl}INBOX'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_groupemail'] = 'amsryzom@gmail.com'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_groupname'] = 'Ryzomcore Support'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_username'] = 'amsryzom@gmail.com'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_password'] = 'lol123bol'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['host'] = "ryzomcore.com"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['crypt']['key'] = 'Sup3rS3cr3tStuff'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['crypt']['enc_method'] = 'AES-256-CBC'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['crypt']['hash_method'] = "SHA512"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $CONFIG_PATH = dirname( __FILE__ )
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $CREATE_RING = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $DEFAULT_LANGUAGE = 'en'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $FORCE_INGAME = false
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $IMAGELOC_WEBPATH = $BASE_WEBPATH. '/sites/all/modules/ryzommanage/ams_lib/img'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $INGAME_LAYOUT = "basic"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $INGAME_WEBPATH = $BASE_WEBPATH . '/ingame'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $MAIL_DIR = "/tmp/mail"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $MAIL_LOG_PATH = "/tmp/mail/cron_mail.log"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $SITEBASE = dirname( __FILE__ )
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $SUPPORT_GROUP_IMAP_CRYPTKEY = "azerty"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TICKET_LOGGING = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TICKET_MAILING_SUPPORT = false
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TIME_FORMAT = "m-d-Y H:i:s"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TOS_URL = variable_get('ryzommanage_TOS', 'www.mytosurlhere.com')
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $WEBPATH = $BASE_WEBPATH .'/ams'
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2logout_8php.html b/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2logout_8php.html deleted file mode 100644 index 5bfd6bf13..000000000 --- a/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2logout_8php.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/logout.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/logout.php File Reference
    -
    -
    - - - -

    -Functions

     logout ()
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    logout ()
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2settings_8php.html b/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2settings_8php.html deleted file mode 100644 index 6c4aad8c5..000000000 --- a/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2settings_8php.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/settings.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/settings.php File Reference
    -
    -
    - - - - -

    -Functions

     settings ()
     getCountryArray ()
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    getCountryArray ()
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    settings ()
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2show__user_8php.html b/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2show__user_8php.html deleted file mode 100644 index 089184d66..000000000 --- a/code/web/docs/ams/html/drupal__module_2ryzommanage_2inc_2show__user_8php.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/show_user.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/show_user.php File Reference
    -
    -
    - - - -

    -Functions

     show_user ()
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_user ()
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/error_8php.html b/code/web/docs/ams/html/error_8php.html deleted file mode 100644 index 18103076e..000000000 --- a/code/web/docs/ams/html/error_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/error.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/error.php File Reference
    -
    -
    - - - - -

    -Functions

     error ()
     This function is beign used to load info that's needed for the error page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    error ()
    -
    -
    - -

    This function is beign used to load info that's needed for the error page.

    -

    if a error_code session var is set it will unset it (else 404 is used), and it will return the error code so it can be used in the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/files.html b/code/web/docs/ams/html/files.html deleted file mode 100644 index ac4afa38c..000000000 --- a/code/web/docs/ams/html/files.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - -Ryzom Account Management System: File List - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    -
    -
    File List
    -
    -
    -
    Here is a list of all files with brief descriptions:
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/libinclude.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/assigned.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/dblayer.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/gui_elements.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mycrypt.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/pagination.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue_handler.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/cron/mail_cron.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/cron/sync_cron.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/config.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/autoload/webusers.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/logout.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/settings.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/inc/show_user.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/config.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/index.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_sgroup.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/add_user_to_sgroup.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_info.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_mail.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_password.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/change_receivemail.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/create_ticket.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/login.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/modify_email_of_sgroup.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/reply_on_ticket.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/change_permission.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/createticket.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/dashboard.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/error.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/login.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/logout.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/register.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/settings.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/sgroup_list.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_queue.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_reply.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_sgroup.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket_info.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket_log.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_user.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/syncing.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/userlist.php
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/sql/install.php
    info.php
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/forwarded_8php.html b/code/web/docs/ams/html/forwarded_8php.html deleted file mode 100644 index c63feb786..000000000 --- a/code/web/docs/ams/html/forwarded_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/forwarded.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Forwarded
     Handles the forwarding of a ticket to a support_group. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/func_2login_8php.html b/code/web/docs/ams/html/func_2login_8php.html deleted file mode 100644 index 42c3b2cfc..000000000 --- a/code/web/docs/ams/html/func_2login_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/login.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/login.php File Reference
    -
    -
    - - - - -

    -Functions

     login ()
     This function is beign used to login a user.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    login ()
    -
    -
    - -

    This function is beign used to login a user.

    -

    It will first check if the sent POST data returns a match with the DB, if it does, some session variables will be appointed to the user and he will be redirected to the index page again. If it didn't match, the template will be reloaded and a matching error message will be shown.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions.html b/code/web/docs/ams/html/functions.html deleted file mode 100644 index 15739f418..000000000 --- a/code/web/docs/ams/html/functions.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - $ -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x5f.html b/code/web/docs/ams/html/functions_0x5f.html deleted file mode 100644 index d3ed223bd..000000000 --- a/code/web/docs/ams/html/functions_0x5f.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - _ -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x61.html b/code/web/docs/ams/html/functions_0x61.html deleted file mode 100644 index 71b75926d..000000000 --- a/code/web/docs/ams/html/functions_0x61.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - a -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x63.html b/code/web/docs/ams/html/functions_0x63.html deleted file mode 100644 index e54bfdd94..000000000 --- a/code/web/docs/ams/html/functions_0x63.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - c -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x64.html b/code/web/docs/ams/html/functions_0x64.html deleted file mode 100644 index ccb18fba0..000000000 --- a/code/web/docs/ams/html/functions_0x64.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - d -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x65.html b/code/web/docs/ams/html/functions_0x65.html deleted file mode 100644 index 5b0059440..000000000 --- a/code/web/docs/ams/html/functions_0x65.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - e -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x66.html b/code/web/docs/ams/html/functions_0x66.html deleted file mode 100644 index a3f6b19ed..000000000 --- a/code/web/docs/ams/html/functions_0x66.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - f -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x67.html b/code/web/docs/ams/html/functions_0x67.html deleted file mode 100644 index 6545e7d84..000000000 --- a/code/web/docs/ams/html/functions_0x67.html +++ /dev/null @@ -1,461 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - g -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x68.html b/code/web/docs/ams/html/functions_0x68.html deleted file mode 100644 index 50b2e6fd2..000000000 --- a/code/web/docs/ams/html/functions_0x68.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - h -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x69.html b/code/web/docs/ams/html/functions_0x69.html deleted file mode 100644 index 10bdba341..000000000 --- a/code/web/docs/ams/html/functions_0x69.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - i -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x6c.html b/code/web/docs/ams/html/functions_0x6c.html deleted file mode 100644 index b3146013a..000000000 --- a/code/web/docs/ams/html/functions_0x6c.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - l -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x6d.html b/code/web/docs/ams/html/functions_0x6d.html deleted file mode 100644 index 69ab3be22..000000000 --- a/code/web/docs/ams/html/functions_0x6d.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - m -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x6e.html b/code/web/docs/ams/html/functions_0x6e.html deleted file mode 100644 index 78bc0f4c2..000000000 --- a/code/web/docs/ams/html/functions_0x6e.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - n -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x6f.html b/code/web/docs/ams/html/functions_0x6f.html deleted file mode 100644 index f33e2ca29..000000000 --- a/code/web/docs/ams/html/functions_0x6f.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - o -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x73.html b/code/web/docs/ams/html/functions_0x73.html deleted file mode 100644 index eb3fce49c..000000000 --- a/code/web/docs/ams/html/functions_0x73.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - s -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x74.html b/code/web/docs/ams/html/functions_0x74.html deleted file mode 100644 index 737b1e6f0..000000000 --- a/code/web/docs/ams/html/functions_0x74.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - t -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x75.html b/code/web/docs/ams/html/functions_0x75.html deleted file mode 100644 index 76a7f2de4..000000000 --- a/code/web/docs/ams/html/functions_0x75.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - u -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_0x76.html b/code/web/docs/ams/html/functions_0x76.html deleted file mode 100644 index 4eea14d7c..000000000 --- a/code/web/docs/ams/html/functions_0x76.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all struct and union fields with links to the structures/unions they belong to:
    - -

    - v -

      -
    • validEmail() -: Users -
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func.html b/code/web/docs/ams/html/functions_func.html deleted file mode 100644 index 95c9509f0..000000000 --- a/code/web/docs/ams/html/functions_func.html +++ /dev/null @@ -1,158 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    - - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x61.html b/code/web/docs/ams/html/functions_func_0x61.html deleted file mode 100644 index eecdf704b..000000000 --- a/code/web/docs/ams/html/functions_func_0x61.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - a -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x63.html b/code/web/docs/ams/html/functions_func_0x63.html deleted file mode 100644 index 4601329e1..000000000 --- a/code/web/docs/ams/html/functions_func_0x63.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - c -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x64.html b/code/web/docs/ams/html/functions_func_0x64.html deleted file mode 100644 index 1b13f2d4f..000000000 --- a/code/web/docs/ams/html/functions_func_0x64.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - d -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x65.html b/code/web/docs/ams/html/functions_func_0x65.html deleted file mode 100644 index ccaad6ae0..000000000 --- a/code/web/docs/ams/html/functions_func_0x65.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - e -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x66.html b/code/web/docs/ams/html/functions_func_0x66.html deleted file mode 100644 index 5db22a523..000000000 --- a/code/web/docs/ams/html/functions_func_0x66.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - f -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x67.html b/code/web/docs/ams/html/functions_func_0x67.html deleted file mode 100644 index 1737c3390..000000000 --- a/code/web/docs/ams/html/functions_func_0x67.html +++ /dev/null @@ -1,460 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - g -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x68.html b/code/web/docs/ams/html/functions_func_0x68.html deleted file mode 100644 index 9904982e0..000000000 --- a/code/web/docs/ams/html/functions_func_0x68.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - h -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x69.html b/code/web/docs/ams/html/functions_func_0x69.html deleted file mode 100644 index dc34cf2ba..000000000 --- a/code/web/docs/ams/html/functions_func_0x69.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - i -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x6c.html b/code/web/docs/ams/html/functions_func_0x6c.html deleted file mode 100644 index 714735a9f..000000000 --- a/code/web/docs/ams/html/functions_func_0x6c.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - l -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x6d.html b/code/web/docs/ams/html/functions_func_0x6d.html deleted file mode 100644 index d9e0a3d0f..000000000 --- a/code/web/docs/ams/html/functions_func_0x6d.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - m -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x6e.html b/code/web/docs/ams/html/functions_func_0x6e.html deleted file mode 100644 index e63e0096d..000000000 --- a/code/web/docs/ams/html/functions_func_0x6e.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - n -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x6f.html b/code/web/docs/ams/html/functions_func_0x6f.html deleted file mode 100644 index 052a9e878..000000000 --- a/code/web/docs/ams/html/functions_func_0x6f.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - o -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x73.html b/code/web/docs/ams/html/functions_func_0x73.html deleted file mode 100644 index e54b1d413..000000000 --- a/code/web/docs/ams/html/functions_func_0x73.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - s -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x74.html b/code/web/docs/ams/html/functions_func_0x74.html deleted file mode 100644 index 01dc511f8..000000000 --- a/code/web/docs/ams/html/functions_func_0x74.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - t -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x75.html b/code/web/docs/ams/html/functions_func_0x75.html deleted file mode 100644 index 8461fb53c..000000000 --- a/code/web/docs/ams/html/functions_func_0x75.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - u -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_func_0x76.html b/code/web/docs/ams/html/functions_func_0x76.html deleted file mode 100644 index df3e6c9d6..000000000 --- a/code/web/docs/ams/html/functions_func_0x76.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Functions - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - v -

      -
    • validEmail() -: Users -
    • -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/functions_vars.html b/code/web/docs/ams/html/functions_vars.html deleted file mode 100644 index 3e1822ad5..000000000 --- a/code/web/docs/ams/html/functions_vars.html +++ /dev/null @@ -1,334 +0,0 @@ - - - - - -Ryzom Account Management System: Data Fields - Variables - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - $ -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/globals.html b/code/web/docs/ams/html/globals.html deleted file mode 100644 index e47399641..000000000 --- a/code/web/docs/ams/html/globals.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - -Ryzom Account Management System: Globals - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -
    Here is a list of all functions, variables, defines, enums, and typedefs with links to the files they belong to:
    - -

    - $ -

    - - -

    - _ -

    - - -

    - a -

    - - -

    - c -

    - - -

    - d -

    - - -

    - e -

    - - -

    - g -

    - - -

    - l -

    - - -

    - m -

    - - -

    - r -

    - - -

    - s -

    - - -

    - u -

    - - -

    - w -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/globals_func.html b/code/web/docs/ams/html/globals_func.html deleted file mode 100644 index 72b667802..000000000 --- a/code/web/docs/ams/html/globals_func.html +++ /dev/null @@ -1,269 +0,0 @@ - - - - - -Ryzom Account Management System: Globals - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - _ -

    - - -

    - a -

    - - -

    - c -

    - - -

    - d -

    - - -

    - e -

    - - -

    - g -

    - - -

    - l -

    - - -

    - m -

    - - -

    - r -

    - - -

    - s -

    - - -

    - u -

    - - -

    - w -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/globals_vars.html b/code/web/docs/ams/html/globals_vars.html deleted file mode 100644 index 3bf8fc1ea..000000000 --- a/code/web/docs/ams/html/globals_vars.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - -Ryzom Account Management System: Globals - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - - - -
    -
    -  - -

    - $ -

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/gui__elements_8php.html b/code/web/docs/ams/html/gui__elements_8php.html deleted file mode 100644 index 871ced11e..000000000 --- a/code/web/docs/ams/html/gui__elements_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/gui_elements.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/gui_elements.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Gui_Elements
     Helper class for generating gui related elements. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/helpers_8php.html b/code/web/docs/ams/html/helpers_8php.html deleted file mode 100644 index c69ac3d2d..000000000 --- a/code/web/docs/ams/html/helpers_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/helpers.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Helpers
     Helper class for more site specific functions. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/hierarchy.html b/code/web/docs/ams/html/hierarchy.html deleted file mode 100644 index d4224c3d0..000000000 --- a/code/web/docs/ams/html/hierarchy.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - -Ryzom Account Management System: Class Hierarchy - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    -
    -
    Class Hierarchy
    -
    - - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/in__support__group_8php.html b/code/web/docs/ams/html/in__support__group_8php.html deleted file mode 100644 index 3df89eb62..000000000 --- a/code/web/docs/ams/html/in__support__group_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/in_support_group.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  In_Support_Group
     Handles the linkage of users being in a support group. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/inc_2login_8php.html b/code/web/docs/ams/html/inc_2login_8php.html deleted file mode 100644 index 428266ea6..000000000 --- a/code/web/docs/ams/html/inc_2login_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/login.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/login.php File Reference
    -
    -
    - - - - -

    -Functions

     login ()
     This function is beign used to load info that's needed for the login page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    login ()
    -
    -
    - -

    This function is beign used to load info that's needed for the login page.

    -

    it will try to auto-login, this can only be used while ingame, the web browser sends additional cookie information that's also stored in the open_ring db. We will compare the values and if they match, the user will be automatically logged in!

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/index.html b/code/web/docs/ams/html/index.html deleted file mode 100644 index 82188ca7c..000000000 --- a/code/web/docs/ams/html/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - -Ryzom Account Management System: The Ryzom AMS information pages. - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - -
    -
    -
    -
    The Ryzom AMS information pages.
    -
    -
    -

    -Introduction

    -

    Welcome to the documentation pages of the ryzom account management system library.
    - Doxygen is being used to generate these webpages. They should offer a good reference for anyone who is interested in working with the AMS library.

    -

    -More info?

    -

    if you want more information take a look at the ryzomcore wikipages and the design pages

    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/index_8php.html b/code/web/docs/ams/html/index_8php.html deleted file mode 100644 index 1a7125c9f..000000000 --- a/code/web/docs/ams/html/index_8php.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/index.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/index.php File Reference
    -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/info.jpg b/code/web/docs/ams/html/info.jpg deleted file mode 100644 index 9c9f050922ef11093dd81d5668a49420e1d20a24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 464423 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 z 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

    khph>h1mqLxk;uX`d=_GP0=rGnR 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 =+ zsUBH7$ymP+3lK5X_>l@!@nut{GKi_eyS`{@kWV<# zY_gh)yP2%jrW+B%6#+dWAl2pneov)I*Q+VC(A&X=7gTqllDsDrUN+WU!}Z zm;q($&dKAoCOFF`Fq$|se{O%YddR)M_AV6v&aMmG7Z-3MUUR?jPKzZlR#AT=J{c+S zXlF8u>0Hk*Df}#!eaPCx{ZlA1->Ar>C#t>}4jjiPhEm*#N03BC;d~zs4NB5kPJ#T%OLrTT zqs<|8_p!^M+N(+iP65}IJQCbR`gq#olTZPBkyc*wQ zQA#JNmAcSPq;Ppv0g>bX#Si;0-!d@)O7nP+Z)fQ| zjQ0gLXx(%dZb@V6Jv7Bq_6b-J1-a_CI>#YwNCrRjymL)d-xeX$MJjxG%c@$juK7bE zO`7`{FP}$WOq1JdwZl7WyC$u8578Ijr%VbaBNWm(| zIb-4PM}AMk3AmRP-ETx&2ItX(RgPh#%t+e-f%-6=0mxo*>i5Bt@<5ti1@G3(W%8qA zkWH?aYZK$g8bo%g_>ta@X%4#X;Nq1XBnxq@xrDOc5)xsMdcnGan zBQ&N(0oiWv6dBHo((9`3e#C@EDRP=N`lId1U<&;p z+R<1l1HFSd!PHVf5 zI2b9qV74bmiw z0(W{+vQkC^$FA=28uc?bMAN6UTM{7?o4$0=Y`6;Mq(&77eGeN`QX)!Q(_(l&9b6`S zfbpgIws==on_jW*aO_!RXiqA|=$0a8bdiZiBTFDJ+RAkRE&VQt-T3mPV|V z{jEPk`a9V!9#1;ihkH6gZ1btd?r)stDb)KS@}wzx89%hq)ct)Y=Q67!R~dR&P*!07 zNBY}~V}$R+K$ku)_I_$+$zcgJvbpG3gzh=-^gb!yd$A^B#e)X?qTAS|YJ^ODWpYI- zU_?T=ph*bQTVJ`+XQ`>OobF?u!2&+Dh|YCAomEt+DoFSQEy~KY<084|- zi6t-m6w6wCJvYZ%v|gjkcYNX(bz$AGrBjex0A(!A!<}6Le+-*wTu2vF#kxqg!;*;- zoO_!I!WJWw0N_w{lDj*WwxSo~-;De8fPT~)bdJ)<3jcYy-!qi&kB?`KaE}o^ImYyY zlBBhaEg5w2%ZQ0w2p{r^!K}e5_ZVD$D*azYYz@358lw)PRlPwgd1j7$gNquSrJXy1 z{g<9N`V-wOet7rwVG#1;{)fVs=Xa|g7_a4rLgUl;cTEHPeqZ>-@1C^IF3Ch;Z@GS{ zi!jAklm69c@6pr~L=>K=K}J(K)R?u@n3(dG7Vs48W;G+k6MGUnuLb4m=(nEyoK zYwSwOW_b@`h%Nr6oZzQ%4)9sa7**n!}c+ zzJDcGpR}f03esMF9v#?JH7R{1ID?ANEITVCKBEgb)s>4Cr7iQ6?$G7hT#mW= zL=thNe2|ghm(J30Ct)T|*TTVh1kf$RI}*u_SvFO;c~4T3lvqwT$>9k)OXHv;@4f>Z z%EaHP4p1p`&%?wbY2ZLQiA9b891WHGr7<)D=ewf_?k*_~$BYU`X|%5Le)#W+vHN03 zt%mjDB!Khcis4yMBswb)DpZ~PXAx+R`Q5J?xQ;2G z@T_7QJZgPqSgTq1Z>40p-&&g zQX?v9TySb{*@%?bh|)3}UQi``y?CtI{#%V}vGeX8T+f)Mb8uMqY}iIo{{OGTF^lpn z;x?@P`ogWm2i)loF{gNeXjUb~?Fy>D!jyjND)rlw{4yTRL`X1tn1EV0`g^h-&ciKS zphioY9S--3Nw2=c=Rl;O#i#GFZ1Gt9tZrM5Pm9o_RIguf+;ZZj~FNZ;a+>jN-3$&~%bD(pnbq-yxflMG*O{uhy=yCh7g{1gyjgdwH>u{~f> z8^F>F`tN=|Z~oePA>}b{zJH!N6L&;dwJuAq?mo`NIY-)+S9H}Rox_D5e8@jRF2lf( z1C$x_sMjWeIDB_U6aFqlzVVx1rhJ?2CijLSb^YDJ*c9yuoEvT9AvLgQp{|5O`Tq^#VDEF8QBm;JYZy30LA8JEPY^7`peb7-z+A+#4wg?~)!2D$rUOJ+d zNzU@v#hV=ee7nqum{oOasS4-M!G8jL`rH4H9?5@#C;rXQ{5|#_F1P$KO#d<3DBMZ? zJO1Cq!x#A*zxFix`xwvQq`5p0v1+y-4+?X^6&qx_`1U`dwV0K=3>l?o!l<`Zmp98F&3y$``Q4+^NH zVrRFg&phA7UR_OSD&}N^&-7j9z4*9_wg*U?QM!{!JkT;endZdWJ5Q| ziH*=>wo&QFPTLCjn4Va*W7Igl#_Dx)-H2W?;;8WAPbnI30qyn6$%Z6~nmJ+ZDC3?yc&v^V@BAT$}+fVoK zA?^(!K4P_!Z-$c6snj+}?M4Q*_m>5yf$=e5QJ?tRFSiUPV_$gFT(iZ6TpBM8s%wg% zZ0)v=@H(LBVTP?Z>xLjTa5ox8XY<|r_f3`x+V*UTb&W+!j%Vc`0Mr;2L88aPI#KHRihIPE*U#~Ng|8-Ah;7M8VqvL?LLuudcQIEHf z1IiaagokctwUT4=oFHp|6kfoyI?4$Qo7IiYO+Bw@=}?|ec#B&e!|2mL`jk8JSS9X1 zBCHgVIobl6KZ9s=4XhrvDC&0b(j}5d&k$Ra*1L)?<2Q;;sc^+_E`bOtb$ z>xmM~(5SGaPb+Dh{v;FWOp0ko9``;SNE$Q3T4&SVn{2=`3EGyb;qBt0uw%fho6z$i zb&ze)*nYKAX-|F9(qg!Pa>~~rd}uqy{Z^LFlEUOHGsO@**kYqHF2kRINNamWoAJLh!M(m^o4l8T`#v+N1; z7S3|m8ZfvhknqNTvw)$J`v~cZFxJ$bZOe}B(^|=uSbn{Nnp!;V@Zx3so{6^kc*0DT z8AVbdY$^V%?N>iOpi;ji>5qkmOKjA^-9aWI%Nr@R#@I!;_G5;J#*{znhyOOs&Q{e{ z|1A|qQMG6hsSW!BqLoK_OMOx$uQ+#_khfYmr`}hjI%N3z#9(>ZmTtYx_DEF{hS#(; z6|cm721|I&ndjRxb7n6PikZqw*I)A|n6Zc42hTrxB6a$gH-KgG68u$5N3WjAA|qV0 zwS6jVli1$TIfRT#zD&xE36)JdgZet5i9hRum>6(debFK~4(H23&4ryB)pWGvcu7^j z(#K=VZ}_x7i*z0D!4-L4S`wb?2_ zhisD8rBn0Kb6QmEPRuPVTFsrHi5m8?*lb&4b`eF1Vi&jaycDrpTCNH1t8rDSZ6)IZ zXZI?}kQ6g7Y^xPC5Da)eP!*kgbA-t|xn;j~j*iQ(RzbNnONDG%WX@LF7k)GBSiCIM z0Iw@)oK`r+_17?NB61=dezDr}No*Vl8t$}YcQ5)i>X;L14!ET#Oo23r8R0>qK=*ETZ?sbSy*W}?BEGPG$8-DjnfJ95r#9}#cR9J+Q!gGb*a zItobcj(V+1fp5=E;h$-kAQo8dd4ieV#C&mp>#LHQ3-30C04hdq=GSco^@|JiACcLd zZD5q+{>KAkDo1L{I4ARG&q0cR0QwKAbBw>yv&D`*8J^au>Z@rw+~uddl_`7D_BLdY z$1s(fg0!f?n8Qe0*_Ps_J{=HoOOY}$^8D+91VSvoLO`&hZ2yosl9!;hWoWYT%Fu>6X=gwV_V?LrFO+B+M>sl zpGNZcPlPS-WBGG9J9zQN5Tv_mx?dK)hsx%em>THhQ}@|K8yP)^*uTk0VCC-V8eq`S zRK&vyFlxWw0&?car8F5qq@EO)*h9-~xotr{ctvndvvEO}h@Xypt+@_DbQU}T4ea&$ zm|r#5fp^1lCbM06K-)9Nh5_4bZ*q^h_^@Pq{fuZmS0U`nfy=(YAx+G9ccxpOjECKL zh9SSI4%bE*7_HqDY|^dL{khv*U!5CXrEIcT&W0i{Av~g$O}0K4y;t-zUCcvtYGmIj z-D>5|JKCj3#Cp3YIDJ#5+h25+*yEB{=F#^mO~+rx&7+mt4rDRoy{88Z4IjB=?~F;} zWN>k9yzYVoj7h$f%$P$gn(gnq-)S7|TR=EZTZL!F;om|WX za@ol%`K3emn_un@{FNU4S*u53sx1~@a0S{CiP_?LWC}H=?LWiCCZx%JJ}-A>tUb|^ z<5$jc_f>(4JP}(i%+-AD!ENVH>!JL;1Qb^~X2|f_RI;M!>seh89u6Qe&fock=3UevNqxG3!M1I$>VhNyN5If zmrn_vQxjy+A&HQr-}lk{sdHMd{rfSY_17Oqb$({|9&8>Q^rok#gyP`=Z%4!md2bhE zb998JTE5#zTI}`fYt!%hV*2`Y)%O?~iHW`_LYfPr>KFHIxyq?}xdShlWf+NLCL>=x za<$&@>!@LE$qPvEUL1v$tJ;vBwZgIPIeR$=E$vkff3i5AaS)A5PKAmsZQ!k@bzp%L zUt9WT{32%;F3iP;I$9hb{q9_?Hcczp-TXzlM6$LJrt1%8m+s+eNO!U98ID z5CkgmxeZ_zIO(vtnND%}1(_|R(omIksmx(DDSZ4|6s134P&;ha{2 z__HU}|M=NOpjFT{x$5$r0Tq-(sq7yAYE11pM{GW5ctPOid(7k>j|I+bL3dFc9&y60 zH$P^-KjEq5us7qxkTnB;Z|dQLa@J$rF?I;)yc74S zwxF`Hp=`@BHOJ9U|F+o~f>c~w0=Woeo|3B4BapXg&nnOx>R>53&z~6fQ5xee)DkKm zs#U}6QRx)tt_N9w8$fNITQa47p3>vO#BZ@&G(c{Cg_8LyQki?se0BJO0_F=1UIbQ!`yP zNVT?n{RZO~Nv&NYLpvGp$xTk3?U?%OKLE)-+b@M?B?@MxGz5}rLhYv8xIz+XLOIi# z`_Lai8<4?sWQcN_mk~aq3ZF(vlUoGDHmrAgi%kxV4+ma@n;x>@55K2ZO6l3ixN@$@ zV?ES}rEw$Q^gm})Ppxe5ZNp-g%ZO^_86r)1>e8>pzx1uJ%N{%<$qP!{k~*rl1;64^ zIhRR{RwYhjs391p&Z{%Gx2mTaV{6>EUpN)w8?(CW>iwFHZv@kh2T?3y{N_}X6zIM+ zJ?kDE`Fd&of`P_0KJE1w>|JPx-}>f{6`u)gq5m?Xl5+)GDT@Z+x&vfJ+aItVM!V^L zsFRlx>z?e&51Bh}-cmTYGz2gD_Se$s2sr|x)gOSG{Sb*jFrBzNt2UKI`TXZ)$6~~u z$%7&Z#Sl{PJ;7}&DKB>W{jfM(YLcVHfqs(BE(S}3Wbsy2I-#a0G;cy#&(CCj{-Nl= zE=2+1^8gFfbniT(Er8R(@SIcK3kqMWTh7X1TRz5cnQ!yU0#6thG>7fxb4CpqYuYSq zZL8LEyvmkYS{F`?M{qfs7Lynfh^O&dL#=x0+$z%b2dwjsjcJ^JFuzRmaMG z2Wl~Jued6Ar!ZEfgh@4z0%#5C&K{dr-a1(-DrYrK##P~bWbSNLC!Ld?6sP*dtd$7Y zp2{U17w#cSS&8$=<~|_d^yV%9E11AL39jLhgo1HhyQztPA;C9rwfj^gOg~*}3JhSb}W)g;emWhL~Aj z6-T*;>A{Rhk@mpmu=W9~xl0#r_T#MBl1AD>GFW4SM3NC&z1x&`0Kes&HCvh(8x;q$ z#WCOwTnCIJl6CqkJKN$2`ti&L(N~ z%_n5Qyr#b#_^Z9hN@vre*(p#H;K60EB3AZH-l4cxajX_)H@L@0L7N$GPU!?`FnvRm zG@&qqo*Uk^fmiLN&w5U1QN!5mSIQw4%f{o{Lf-HPqdgyKt6zs-!M%aXH5Bpw-V zYe>KsNHP0)=m@L>Kn6$M>B_WSdnCqAvX4(#z(wu_Bb-Fd9Yu@E&?KX07s!7m1{ z)zseChkd=3P&345b1lbe?F84E0kbw~X5B7pNsAK*8e*W(fX5GN;H#IsM=o;CBRO4< z9we63yuJ@&bcKAqZ5Ajj^aGmJkKh@vHeefyWQXzUKV|W5poU{b=~Sw8{|mE3+t&E= zjN)IlhGF$JK?6cVCnFnC5vUq{z7(93R5 z&WXl?lg=LhMRcQV%w*?2vK1u|LuqJ4X7byAQ$2G^OCH!lE&}fWN7*j{UGN~daq|!g z4*4cOW}T-(MhtdvlN0`spKZg(?vh^{2KnBM>Ya~eDfjSRl9dhSDaMBc?3c!JMMOf| ze$4{g)R6Yrysnq5680~#7q{k_Wy5{k7$EKhrj4u3Qp&u{+Rx~iKq;UmFSUw!iP~r^ z;e+!XZy?z4@@kH_&6CZ(`7vs`jt0dp?}sWkg6Y3OVVjbD8I%dooWpM|dMr2u14x+3 z0_0U5H)v#34YenvycV(1-k;FYnQg4g65LZ^9I+5{+W=_y^Gb??7lksG&5BhhhKwm+ z)yZ@kIg|+U!Tk%Kpso4I4$&noJSGGg;krvu3f0`!_;s}AY)o=;l|aOp$lgXjyJYRo zur|Nc>EQZ8T2a2ls$3N(6JtE>khVEUf%pjn4-6O@-fP3LH$$wd zyD7SYubU(H*(a$@ud`1c{LyJQ z>K@&!Y4XTOOGDZOb($o2k`_l>WRAF%F6fCjcB`*?VaNaqRtYX6XDPx#1jB>3g$8~4 zBc=9>_c;==8AZ!_^+}Rl!c^v(d7Ogz3)GlF-#eLxBMr0Pg7ikowO!?Fm3^v~YDpgT zB4Xk-V+vIQ5{1Xx%i}l9^)dedh?emZP}GvQLH?SxY;#q7nO*-U_lxa*@6qO zkgQ{vKln}!-j0ZYQtGMm>T4ex<3nYpUx)X7e=>V)*l>7pd-^Wu_QmqY=JyIT8T;Iq zVHbNHy_f2a;+A@EKDjp9T>ZWJ94pm|ybT<@vt&E{oNXQypY%P;w`*%g)?%qpVl}vZ z4lFq1+9Bjzc~nQQRJFsu_BP;jpU`mS{A*#H{@Tws&J1Z~7?{3#j~EeWvMqNtq|<}? zaQdB-ruqQ)r&~=0g`z$RR|bB$pS*fYG0}OZzWoc;|XyEz+lb( zy>aL}?~$yv#e4lO$w%KX4|mx#<}1r;@wH?{m>(HqlkZV_e^vfVz z#cjLZgtBF!1&`9D<|%Y-`fx%pLB?*|&$Kv_Oq)Vgu#|#>fTjI!t!uI;vxECw%$SG^ zb>k~v>Z2*dgvb+66c&d@mn=(4h?)j$i$jX6QeliE*R)AQu$9&@N>DDzG+G}As|hK< z_4`CS`(a&Uspgg&5~-~(mv-K^&+~uH7gVx9k?cIhn_lC~bu;7Zax(rx8)Ia0aDC52^Tw8j(D zI``aE*!&2J?Ce1aE$RIO{=a2i{7>V;f0XV2P8X;2g;PBs+f=LPb<9Y#!c6zj^H7V~ z^MRlPfh0gZO1PwsO}acO&TveMTs)$7T#GO>txhsXgCSE1d^60=I#QCcax?t&GVYOl z$J9W5YfvjIVr{ltIL#`%!qAR)_M|J~ldMGDn`(0djtCM8unR7LgL4S#DS=Lzp(m27 zN4Bq&*27!$RL=C&Vsc?t_xXVX)Bxi6+_-fA@t_)FlJ1}G4Z}# zdkU1-P$E~ir0ne~U1YT=Bq3-Y2Ih@0Kmim*vX$h# zWfH4s!Pd$2mA$x@bEAj9QG<BxH0c=J>CIR}45x5)xyu&>?Aqr_$6i4W2YMp-G zd^R?klN#%i)LD(`T%DUZmmAX_XOrfhhYoq`=rfi(bjkz+uBYr$@AGm^-6g9O%2z(? z&KiZx(lMtV=qJESmnxL~2b#M!khW^Whu8)1 zSa;ur9gpeYlS~qqKBO6@x+sv5(R!AgpD8X|C0Izs2Pe_7LAzo`=AaUD>gZ*?6*>4w zYAg2u^K<7BD0*hK@>h*mvSvG3xwl36OO;p{ZaX4=&5BcDeleleyfWUkRhX6ImQhyV zuVQk#Nx-yaJ_fD#R1h(1%bSFmMUOxS@pa4eovbMLTItEnTI^=<3nd)p@i!%1)^Ty2 zI^4D??`iY2fJ#m!06+q;7}F?x)km`2MFfAVwsic;(sDd$>FEr7UmxAU05hnff*244 z0=`9j9{x!taE~-G-Ra9{1I{u_wiv=mB$Ruz?!L|=O0FD9BB=b$ai&XEonus66R^E+ z@6+v8tTcI|8z&3|E=x+$oFzG6&P88ok4M93`~An2kK(xLE8tS-RCImon2rJVouf?t zhe1eMEG(}L#TTm$+o&k8K`B+qSy|yw29iImTIDCF4JnVmLSet!J2xL{>bkXDtc{c< z!mRj7^OJo%=1TO~`zd(LRR*D|O^V$0)BE$@_2tX?c@|=2y=~YOVr8$xLrzlv6&hBh zN*t*O){yt&NmpBaxi7O`8QYzps&9&q@NTHQ_h&cRMz2|B`R@uM?vH!$o8KOgrll)I zjcFz(qdrMypRFe{AV%|ggfB?m25bw4l9i-W0Ifj830GXt-1QrzBl7~TezyTB^_+$^ zA7?!4(@@Mv(dK~p8yS6|*F!RnNf%jDo$uQ;lc#*rqpPEM`NT50dNogZ)=3GWV8c`A zBkfzNM9O+Nv&I}O6X#5xR&ymJkmup3eD-HTP%sevOQYL6ZumF5Vp-6-h`t1za&%2a`}?*}qiqf=;!#m=jZdob<2SlIL_=j;w_9R^}Yu zQ?4_4)sfEhe1=fr<+BG%LNw*0b)Gmp7ob0A%xd&W`w4w__^BSYOlP?*wD8;Zgwfcl zz#QY^ZQclObAhr9l{M4BDdD2h&VVfyu^wFroy%gXQ;zd5Uip)7Qqu=ioZuPtmB25Z zFW)^b&?$W56B>VOQ-O%cA6T3q_e4{i3TU0mNm z1=YHi9l@o9GJ+D#xL=pN6Kz-!bIDd%%#-8k-xgn&vmavkTuIF&*k?C^KmA8lAeHTb zyg?(cCrXY=Zvxz+Suvai-SQ;?lwnKCU?Xg>MXqNm{YT8}RU|~*J%OGjmE{#%MrY|- zy{=`hN&LJX8&OC6vJrV8{wiK-hQxnwS$)e1no7#H#RdzoZ(L!1Pm-?$Rp6Pa`rXky zpMOn?%^;Z9Kmo0I*LbNTV*uqm!1j0a8fp+1M{SG2!&AGV+Vl_T$ zH#{m=JgFxEW~qGjwx_*c@dqz!W^!t~T>kXpZAPWpqj>_hisysz`cQbFbeA_#M3VC} zqmFEOY}SZWL!rKqYLi|2XN~=duOkBfHUWEl>%Sa|DGjHhcaNwxbhq@$*lnX)rHqA~ zdC0}no=uK2zhKo=5eJhDjSP1j7JVVo=s92mE+wW*!rU2tD@f9w4iIi2MX(ZX)ZTSd zqOjk7#4zS#Tgu?Q=R9R7zvqzU*tiE3L8?xC)dQ*P<4z#NA*y^r45oMsf zD4l|^TSgpFLMT*8phUV<5C7Htc+iM&CQrSRba}@16>dC!wf?dXL40;3%X?QJX*{se zw0-#J8(88~hSQ48Tv4pT`SG>)VwGR3^|STUMLMm6Uj}DV*3}C>B7eJ%cm&m+vle`J zixi6(Z8YLFnG_?gIGgw$Zi3`sEbS=2$Pdw}--QbnE}M1@&(s$~`P1VP&DF^a4jOf+ zEZ$0?WXaz%cLu3|kyrwQ1dKi|<0(y@g1~Al3*(&6JGjhws#mjxsOqM~OHiM6KBG|< zcCC&o7lz95XbW*0kwjlTpDNmC%^6I`od5ilck-ed@~L=1(BmMPtI_Dd-(ieY^9dqF zOf$2Qj1D$VW*~6orgmsN!B|b31tn|tvac@f62#+jY5O}Jkjv;VhcV(#6@SLQ(Heci z(4zOr=HS8gWamQ?TEydPJIxXh(5AAI@22(C^P|?X=6x{mqnp5k@RE?5J$T6S>C^gm zKhk2pU%ZI_{tv(rYf8~&*!JKH==GE7^A`cNNFE;a%6y1Ue}kbw_Y>pmT2wwCmqLlG zN5&kKr3~w^JXm|V>JmCr6Dl>~nr#0zk=&rWxh$p++sd(B{8CMCF#zI|jXR20`AS{J zVuDJ0mm3)wvG2u6e4oaa+{&NGkWc@eMk&gjbUQ0sH#6I5@2Zj;eKqtvnYnBo#sTj@rO#X46oPQkyza_^=F2U``Q7Zv)t}Aq)oJJOsWxeyy=G<7H^U!0T6F zJt>!{%0_84Lx2w$WF(|nDSq{e7xFZ8HS*&2+3=am>Ye$^A8g+p1&Vt@pZjl?ICpwm zaCBf$5zQZa9G=9+d0RNG6T{!$u#jEPwbl7kocMHsCx}}`&oyZ7!}Pq_1(zo!(dUmR zV@93-te;#JdKEq$JWQlqP7!OuQ{=60&2`OFmRPaK&{WC$C__tL1r#cd`GtKRS&aTV z)6k7Q&9*Y`JcS&dRfdlkhPOs~G|6Ui_*5PFWqWjMQmNt$SGs2x2`Bxs4NWrZ$9`o6 z%@0q(eWoiiPk2jdFMbcwJ=UWGMTJ`Lfh-&%jJ% zTUcS+yw_D>F1lvqai~v31_vFn7hPwkgZ^Pp@mBk16f!S!bTbK$5(ng+3S+)yZ~KvuVJT3uZRwF#WI>@Z?}YB03shwhW5HtW7;v}`kate7 zMWUkYp^<%N?KjOrqZ0+cC_Uraq=IEJ(TMp$9svfj`^?ID-groVm9`DV4QOvO8lBW_ zV)TGDtQuuc0Hb(vpE2=g_Ft;IW5}Q+dZm!X^vfR$I`5E8LG^-sNm`wL=!CW_SC$+% z-6dk{V_BbkJe@@%M>gD}$`kY6=dp5PT{dBbR=1fIo`y}=uQM7Lm4fshC9U?3u+&@L zvabh>Y}V!gs1w$oEpx3+n{M<^38CV$LW+Dz3L%Ujm*4UolSQ#GX`MR|ld^0;Wc!lD zLG|O3lwXR?X=mrYDMDhcCcnV8jb)zJ-dr&;aJ%_OV3~mF zV?YNg&Y=H@KXO@?HD0|!Ken1gWpFcfIs|(AXyE0Y@K*XD(J8A4WvC%}=UdoR(B^O~14#8)djHY&OASnV&+EwxF2hOYj#%D4bi|rZfmb(kwkW?T$#ARJ=3QPXd0%Tb$!68L zlF}20Dxd15UR(P6&domnbx&rG%E#&;e`~{iAp&wUT>k*zV?tt*{{FnQSSms?!U4OOp+1DyeVdtK(l6Kx|n?QC+O^4w*!v zgd+$JIq5(7@4wKqr&aRkCiTz$JpBE=|6P4|{}s1pFO11*pYn}f?!CWCjKGk($_fuq zmOuR&%9AS(Z->-ay)SBGqv9^m7Uh`56q9 z#c6T?HNx3IUqSuy<_pd2hLN|udi#Rp4c^&i!1IV}ujG2S{#r$C0!dCIgjAu9jySj~0IOJA+(2yh?aMXlT=#`wS&}68{vq-s2Hf>CVqln&VbG zPs8XB5r6E~sog92i^1k7uKhm34BcmD5+#XeVtjZPGBkT3^2ge^tegjt5!q_PB%vPM zuNB!umxnmwc_J->$e;XXmZLq^Vm!DEYnKv8vK@C(30NJmBG+hUND#E+f(?kd8^jrG z%1qNIHN5=A-Yzb-1sO4IK)u~O5nZlvF@6J!uAcXoPR_~*`ub6Pj1>O8BKbaIe%wGw zL(!Y+D5t*%or2xc>MK8QKw%4*7o5q0sR0tGY7NC4GKy8w@!CyrK|4nm$q z?`;tG;xqs3(e-Do8gL4Q`0%<|_x6ts+_5MfJ+XZwD=-E@>cO9kyGq^?KSQ(jH!Z>T ztYP=+LPxF3y=7{8wwBh6AobR*O&Ou+Fq{zWQ-#4+-`j<@634AT<74)5S=vXo!t{pz z_Gj0qd{;yYfQ@bhzFm9{-#m5*hZ=}G5(;D$4d&eB?R!}N%&~nUt0*|iP#=;^YhtOb zS+`5cQxtVHrYduMX|pYkwdFP(MbOB0&^X6iGDRC+FI;fhS!%)H+d@)Bv9c6DRV0Ay zwGWv8K)46xil&ufYP!~THM;Xv)!fyd?SV&HCr`nGWt|c*ogtfBA6ed5NQMHC= z{#4va4nX96&C6mqSv6DGw#Lf8PppPg8zpuKpS2iqUlMl|HjxFpnj#U$9#{E`CR`B@ z^RVjtlX8qzcz}m&5T#|e)s;D^um)R|@f}yL4-MsFq)568?-t?ng{Qgq(b$o+@O;c6 zm9AJN0?T?VZEnlp`pTu4k7)iQm|R6~qh3It0-WhlG@+s{Y|F83Z=fwnr^nr|V}sGI ziSS-vizD0)e{r|={DH~4;msDhof|3{Ednx!I6ZnJS)wDGlb*J_TIMI2dUzxh`ZOwW z(04mR4Br-XyQ22=BWn6TG%Wo9+iCM6lFQ3pDJ|`Yd2$?i;dX`v8*I^8>>{h6F~d*v zvo0-7=Q5(-vyQskc;=#i1N$`(7&HoO8VGxi}KaVfq)5#5wQ@{1s+?N~AGI9tVAuQ2^gt*t6H!=FSAd&=wt0RZ^9>vv%f{xE$ zWk+|K@ilpZvm}=E4235cnjKSLe=um$9PX>qeqzbfqUPaqojj091l7>f7(QR!T=|y>um9AyT;#o6C1R%( zXM9YIUiVMhNKDuO&)*}5NFL2Uc0=pbk6lLhuLm0BT!KSP zn-2|zv40gM=hHJ}k^D%K>@2Z3ear{%iK$WWd))(fnxNQ$8LdL52`76!8{^y`_r<;(o^l*%`JRLAbmQ=m%CDE!5E& zVuKvdgDpLa(;tl+Q5Dx79`cl*FH7>!TXoO3h~vmC+47}p3~nDt<0C%Fila!@tmFvs zoM@AZ!#fliOyYfn+^B9=)B+}qnth2y$Zb)4^Yh*$g!OD7sGfkf(#Vp5Xkp734!P_j zhxnwNfDPVop@pYRT57n32Rl`J_e4IhA&Su{3(|aJ_d`D-;?A zpKtYVmcBkPp8SQP8+lShcro(p)*R9SJyf?5r_x#H$W(XJIW24G$o9vF_SXh5MzGo? z$Ll9%R2%Qs`piihhtgfJFN1zgWEk>z^MhM$V9=A-H_ht8KneN;pG>hxB0K#r+zd;a=?r@Vi7lX5Mx2*xwnUfI?;?QJ zqI)H@@wl`Rau3`7G#Mz z3-yG(3IA@dRa(F86yXCc>_U1Z63B_2;S!jmKh5$1)zNN#B42xFewv<;tCFtKcp(?m zv;bLAD3)%PS_3zVmXnO;FKDz4R=C=wf0=L39GjJZ^~(AALT>OcriDd!?$^eHOUeGo?YD%HKMH>fXMXUJJ_JHV0V z;G;;Pu<<$x3iw_?guWij?RFReofDry^5am>#cmFHWjPu+P+=9gtm^gnY13uRStG)K z(ykq|ebg}tw)vRHf9hem{c-#3U)Gc7<#9=IhZY>I{%E!+yIcfPSMskY)!q?!BlCue zN*FOi2TeyJ_L??yTGgGB~vSS)~B=37-#@*q6*2%87D*0!6aAz-e<#6-0SR zoumc;WND+Kc!aE4H*u5ff@|Cbs~Nh*rk^!(Z^MKOb3huC?=?GvdQ?D}4)mmr4x`j@ zU$uuG{7OLnTxYQeMyhBtENCMwTmD#n*{9YK!VWv!cJf~)QXTj!bKOn2NqdrgK&=^D zQ>J;f)|}o5{8i#%mvsbK>DpdhRT7fm-hG5yRgwD%mJbjy?2e#plh$Ql){drJuvOZ?JU!p0ud^bgB>QbY2rXW}m)v{vI zmg%P7@jV+|_?kegg#Vq=erGUfy>-$czbmb2!({ss5?Cep@*jXPDaF6SaHjUjgUN$l zjYkDQYkjZ0jrQn-D=MqGSq$R(#y3Eg2NiO5SuA|*F}%09N(#cp%VNBCkEtFB7kIyj zvaDHNQqz6u?bs(8^bNI7lQpXu!LFsQRb*OJw%oNqXp^BYXRjy9KNLthI@H-B=g}JJ zV=u%YAG>#_!=Ejx&2LtBLIke>=u(%!BE=H&`jsHbz#Shov2cq3LqL0TQqkK(lF6dy z=}iwgFiZaImU=-B7c>?ydN|aWR$n&R#+`?IbvEcxj%_0Oq3nG?1s{P|qF`HSFugumOd2=vkc*cql`kzfJ}(~CGpaL3!-6@& zo?tDYq*gd=p59f_IayD6p_O>S&uw}v8^qrb-#hct+?n^M?6LxZ1#loXMx#dVsly(% zlVY#!SIdE$tdajg-dhH>_5SU?L5mj&R-_Pu1S<}KLXiXsQrs!Uo#I--B{&2KS_mGj zxL1Gx!QG*FfdVa1N~!%0&pi7-`~07o=gir&&wh3CBC}?#xz}XY%02fz-|uyOu10gs z8Oj}h@*fN%BTaGk?bV$E-OJ1U#Y<5&8efwMUnwMN+kq-et6Z#Q0_}W_dNymkgd6VB z(yLfKgsW>MLAeP@2ZHw)*A2vVJ1fN~>moLl>_un5XT0CWs@YN|d)VxPNzpv?J5$zC z>0WFCj+%fxbrsBN)&z(43a&WEvOxMXGaIn29Y=pNUzquzF6&t$-(MT)a%L0L_x7RhI{&Q( z|LR}6jP~#>iKG?OQ_p9W)vZHU35Jtnt*zp&n_3={gY4RB9i*p5a^>pBU1D_(=+LLe z*FHDB;RBj)RCZAonygJLte3DHakht&(o_!M+xRPOo-0~QIe>$b?>b=-ie-op4OO%&r-PP@1-I+B>nivYHLM#+NfEzB`)O1v}vf| zb+9aGkJ_Zc-KMR42B9>Pdo|`ug!h z&7P=4z3mQxNYmcXa zvUOKTI_lxKK`Kc0y>=-_^IDNyuzjcHvq3)u7)se@u)ZXl7q$BD}ClRMt=oJ7wgJ>Z&>N` zGiK|ig`{HL=jP7G*` zuUj!80Rjc0iYmnV3LED{{NFTT>_^7c%$&hHyW^_2%|WJjEgox#V3R@{K)!HAo!p3p!W;%$G>V zq=pZ?|FFH6dq(I7U~L|B>5S03?)(WNC9Kv*cfn^dT>M)X6MmRQcX_?do-R3Z#9(i8 zMXrl9-)ZhcW6yQCdWt?^?Y7M|w3GmHlxy;RO3A5u-j;B%g)Z*7=_ZSgog>qb_vb8}^O?tiFkrcIzsS~k3`g|SXWT|zFcY>_7j6%R z@0zT9)GjPdFPnJGyaan3*`V?hS%PZ?5x^~wABwVyxM|YibFXx$YKJ&~g?rY_^svy| z#Y%A5(4Ml2jam-ZD~0u?L}1BIYWDiPupuhE;nG`NE9@Eg&@a5f3I}gUYG=Z&`XNbZ z7fNV@BUVH*Qc@>BrqrD)wN#6)3&xx(9X_Lu4^l@aWbl@i)9$ew5=O-Y7${Y82kIvO zma1c0$d`VZrIm2)o0@HZ!)22-zt+c1@)f)wZzvLUPNLgyAK zM)L}8*tt-3p0X}BPG+{O_~dKaJ)DShadG$^8y>T%f-(rrv2<-v{~yyt;ZnFG&Pgxe zI`uMA8Aje8PaPm1FXpj7Jw!(x@ICuKU9)$oENg>F5|C-hLXo)!+}12oJo@HFqz9{f zx7DrfIU8xtf4#Q*8K>_q+g>oIjeP%jv-&n^crX0f?^9d&HY#B$Gd{yTqd@qGl}P?h zecL+HqtemnGK)@T?rcegmX?qTL7m4*=Z^GP-jeAH^*fZN+04 zL3-6{2PUC;4+vSus0D?>VLEo#x&!gz4M z=3ZRI>0Q^w51PZ`T`$<8GId*`DDW#LsLJ*Ri-faUrdd$=pRBkT6L40>If;Rv3Wtg^ zF#?kJ=LGEA_HsrtyBzycI>Rlsk^CM7U*W2a0Alw(@f*;>=vcRWd{CLAZfnJZ5Yc?9 z6|XC6PeMhYLbvG)i)fA>6BS0TQ=?73+_UH0r|Ivxl8H%UZ?UU;9dpa zQ|k^V@QO-Q+{+a-or^1f-!BwpO$v*{RVi8dAbG65zs82r#hWX9*aImXH2M}v}`ubM+!6MBAiK8#^nv-KDDTrxwiTI zVFu-C`0*;m+#9&6IyMK zWO*A*(m>0zTLBODGUi3P-^1d|;vhvD0wdZhg;K7|xP5d44Kv^FVP2p9$H`0GCCeJ zSfHM5`sTZNJDwHJGx3IGae!q=XPArO$xPb@e?9useN_p(M1T?NPcts0;W&AXVDEEE ziq?mi>Sj1Cr@;mz2vwk6oj{XYtxa^iZ;>Ob2leo(bcfGow+rY+8rN6Pn5%!`RFKMd z5v((Coq+4<>Nw(Cf2ljGnsUw=;%F}{)a@;~oaqv?y^Pbqb=uA~6RnP4KJLvsjvscq z=EV#_gAzjBy!h5=8?h-~knT*ONPXwx)rJRNQ};RA`=dZc3dAx5Q$5b-V&v_&eW8?_@WPM0$DE7<~1Jb1JkefM#!6^- z^A3mLwi9hisw=I?YsIjZCd~uy0wxc#bZGqYV}&@zZ_dYQ4j-qj_UXDn7fx*^vE+Ci z-ZywogXmCVO(OzBAnBuGLG~Dsy7(v&3GdEyJL0socG%>XV!%aZ0_yA1iy?y=gCbYl zu~3_tYF$#L8#`c7jvz}vUKYrAX2FRDw^OW!~JhCzL9DgHs7|6vg}qF)wPyd_JIvT2ZyHd6wXiXEXvn6rY|ZkCC~Bx_9J;l zYhQ477Lz6-GFm#m*U2{}ZdjO~n*Z;i(DyebY~i<->L-s+i_6S%hW(arE^%N9#(OtT zm>=>!btFugOpttBY5y~NO?o-zckoJ~Un`m*`Es~u&2BbTJxe<)Z5?~~`*i!8et~Fz zh3lDH$%XRh%?=u<`-$v4cX>j?*mG9GOxUqEP<2W~YVg8UQqPzZFX?8Um6UFL?~-BD zF&BvM?d?yk*#2#DW!{}~FBoXkL@epPZdLB_<3ed&B`i5wb8mcqwdQ&!eah6pWW8FA zMK3TY68`;ho3(%hw|QhMk6uj8hDRJ>Kdg4`-^JJ-~UlJ zPb4(?352@qf~qH%2}TL->@pLRq6xl?BFJ|(PX^iLqF-jlC?UN6;5wqZ1X}@+VP~O zOMlBR$`TcFgdH|{X9Dr*Y-Zw<-|BbXV6Z~fO%1KCkF9ummK2L-;gxf}F$e&z!_OhX zkBQK&ik`-;F>kQ?3syM8H#)-e57S(e$%^1N-%{Qvah|BtS%!2(W`r^~5R%2+#_x3D zOsXepFQGNa)>^(@EcJ^0YP2m*4b&{UjK;I~f6Avw)RBjD-kBtz5qY;X!FCM%LUZ=A zX~F2Mo$2a}31jX`fd3{7>A>!usUsnun~EeVS`=2ai2+lwsxXNPdQjo z*0AxunCm=0rHrDAbQ40;5cC3$M4G?bE#OD|Ik2c9Ye(RO{;e(?`1*3F; z-y4fSs-U$tW99Kf-FsBgX&!J&t*NB4lyLZK zA!{+TiczqxCAdsnNUBUuD@1d)G)7Y?j)Igb^fbv5u~#uT?LoDRWiQjod$NUo(Vl-6a9|A}u?{>nGYIi#cIeO(9#+8+!d9hrA(YbVVqjIl+ z{wI(H=p3E+v|N;nSelzoad+zWeZ2dpzgnz+Kd1fo2k{du(w=y%>F5-s1xD|=A?gG% zc{~QEg=lvUG0;S=f_V1t+n2)5ACO)(1SUT~UO%Ee8IZVUvnvs#Z_r&@^;w&eUDsR~)J)!v%cn`_?KF>=hFCi|%-+69o!!)IQ zn|02N_as>eoRj}LC-CW$K8i{D=JF)R;4XvaQOE=eV!#DJ4=pvV>OXs}HAwe(?{4{R z!7|+^BAx0^DAUT^-n2e3tdg4p`($z;AzVP(8;#u_#mlOIj=JDEa(tOiODzUs5v08@ zz3X{cP2OhcnhJ)Fd<|?>}`PvxmW%rJcSP+ z*C{?Xnnzd!F2<*sIOUi^c&f2j4sr2h2eQOup6WE$^Ba-dST;P*qYdBx$0Hx<)o;eI za2AFl{sx}1l{SNu>bNCh`T7w9df6XbqVM8+HEd;Jn+lH?4r2jTLU^E_Xd&OT^Sohq zBQ&vs@+dh4_o~rda%`Q?loA&psjF0|{Q3rF^b|k_@L09Mqd)xB{~9GwnGfMN9Kq>= z6O8A$RXG}BxyefauW0YI+Mx<*ca?5Kcc(u1HAaxnuj<)aef4`Voba zATqY&a$eZ_)lWSs$zI^>od=GPtX6UeQwfMb|rCMX4$u;(U2C^u701+%Y zII|^4GP`ss3!B$2;U_9&TAf3a?Mr{YCjL71?CwZr$wDwM{G(XRtx?RCe~7!G3%pyi zD!q8^+C0)D6quQ%w*+D4id<1J_>f~Ud?Af{-wCqo#L+^p#BxRI?}}$Od8{4iDz3`> z(nv@Q_7Aj?l$7BWe2?_c;DR@trIb{!fr+W)k?61Lj7ropIw zWcV>Vl+hEE)keb0%pD9i-Pw|*iIW3(v%`Ze<%eAJY3?Nt`%}-ku}FwI=j|R*EjB#fKd(;iAW}merEltJd-l$Go z5LS0E^D--AoFFl=v}+$u*%zBHDIPw*36`lwCq)_3?5U{s1V3PNQ`t3huNEv);}{hr z6X2>Q6EH+mGxOeuc`lEEJ8NxmokJBoeROo(+7C<;98bvPZ}3sSsQ-#JDGU{Z9Zdb z<{?ym7hwotO2QUISKlR2i%iZlln4)`HP&cJE+Cf}-MEh!(f?6mIjS+N+S9yL&oYYL z1T<2U_Uu_bbl%%ItkiVOP?|J&Kd5x!Yaecrjt*mO-Wlzn`Wqyk4D3P5$a}{0Wsf%b zPJzkR8(i2syoq`Cm5*dEV~AmIaW3<>)vlh8wG)bdSGoNP9rcBCx8hCH=MN^oo)$Jd z4!b^G>j-k|zfl$Z=#9=}qB)v1&)y55(q_HUI!DaViR_#X2VdFnn;k7 zea2QERXmU6_H&Ka2(=k=ZWEAm^GCEJzGl20?)Deq7;EbB3oOj1^b zpjr4H^-l@)L=)9rzgjH`?_>E#!|v3tWwi!0ykhMI?H_SlVTrGCuss?sE=#;6p|HGH zjeUXk@z{Yc^J+5IJ~U@?RTzh#MwmqY>Iic->qnC>D36h$sOU7=`1XZSLr{Lf^3Qxx zDaR+@tpyj1AJYjxtE?s05JElch0s_n+Rc za&pLemW$6N@m`TLq3y`X%T$Hxh2}7lVJNO=uqVZy%s|=RR&b$_mi^`;S^Oz`G zBI5GjG(W1n(88FdYa?1bOW5p2o`Oq*ydm!&w;D-nrMRK81lvfn?!p`Ixmx~M&(d6? z0dweRmye8sGAG%)&DUd0pbT8JCH`dOaqb0H;h;Z-Y??sMM!x-|Vd5fRz{+W4skH_e zsm>FOtXnS~BM_aaWFYhYFV^p0L;oXvru9Nvtq-!cP`T#`cH+~VHmzYz!gpy>pLX-vd9wVSw%kfFU#d1|-$Si; z$$2&NCr;!N!w_I$d3Y@)vv!MLL7=fNKh=Vksy7`s(r#(F*q?T)uhcxoa9Hl;*BP2! zs^lcsY)&t~QW6{Xhu*J6XyuDvZi&vKwNJ|%Q`iQ0Opz~-MQ)`l%~gchi{xEx(OySm z>)nI1kI=IN!5EcHis~0Z>6MQP`dinY!-S zY$;wkWUs|8>a2g@Mlou&HjP?gnUKwXM|E{tCqDGkjwr28J{Jm&d%ECAzeCkEczh{JzV+}hjl>pl9>loa~ zXo$6cP2wXO`~5HRFp0H~PWOZD3o=(Ya0d;QF?^++AF6%1-C9RN%D+_wewpg2<+J{~ zhnG8ehj++=)1ShD_yfLsN7cu6beuwM$8(a}^H#R(??0%=)VuTEeR7f>E!gZqcX7IC zV3ManR=Gcdgc0Mw^N_SRc&DDEgqj=~{u!UD;?$PeiX}ZQIl@}jyZn^qLD=&#@P{VK zjUs6n9vGp9s=N%*eQ#z>ZdzWOF{j<9aosXY=OdD4M+)jt$f_nEW$!!CA+bjpQvaR( zH!bRkz(zkrPQ{*8I^9A-5Lttk5(nxk)8DT4#KclNd>fCU7Sf;UV%AwFxt1-IG)L-M zeTTm)$I)X2SOPAef1n0L{|gYXJorejgibZxJ7#U>IjtdUm?x@Uz|1)7LUK z4(K7dx@JB(_Tb2fjb8g-B`QnzEcht7NYX|O(2V?u@$(3!3 z=omw4p$D7#E1Epyj;ihXj_w=${rTFg&E(l{@$D|y%yyb@Qfz%)3 z0wuJ0!@L~pEFOb&@07u^*Q8g9MIs0|{#fjMsS*D3?|{KpKj*}3Gq`tC0ob2_qAWrO z4jgxI{SPt-Od}${7+7^GR5)oC(iK{_0yX}!^!aq|F z=X_<;V-5*EpM1`G@)4=q;x33YyAjqg;{FJn5&d3SQ_-*+5r4+Y`Pnh#D%LyJRvAwf zQljB^Ekv1-TCI!;hE(h8!YOWHNQC6bC!tipUBQuF1~%Gv*Ob#=$3oLuxXXt#Kv zCl4LZ3(IDdeMu*E+1ExhWfk&MwJaT*pbLKh7K!}@sm8@IZ4-YzrBG#=0MqLmLN#sl z4LAaow!dHf8>91omaHnpfAi_tk~t1va}~P;Gdf`$MBYS_nF`lreqX)5=$tR;7EDD3 zMp&^JbG+xD(>d~(@bZ!f@(lH;f#drZPtwyV5o4R1k9-d7+&*RaljU)wAe+JP62gdT zworgf3TVOgWv~D9oWD-<1~yJ7TH1=7<)fZoQ+O*_ZALe6u`lq|%{3Z)BT=dZp^4a+ z7A&e3Ya{DxxGSOzdwVC>B>`90VLg^ba~VA+$Q^Mbtv=^21O?bQRF#*O^Vu^FS!3hO zCSqs1GE>h*r`b@JyXX-eJYFIwnZD8$Ql5dBP>l7-93mpWW?zk9lK*Ar;!})jvS|n; zYfoQHuv{aHGG%SE=(!<$8;deH#0IPMNzHqe&?-~cvlov|7Vugl?A{lnqm`v`E{ z+&fdv^TLpILQ5{d2DFanYw_zO&!#dW(1D)IHoLax zWK$v3n?K)$Ufyx_lsOx@xl1`du5fwoGL8>Gph&?fWcZSn~0Qd;Tn z1nGUY841j?ksyyhDw8?R|A8$MUp?Bc(kpD8vPev#j+6kRv`8DHyQ`g)g9#=MmO&yS z*=~-hd6_N`SDtF4QO$R0H1@?huA8o>#UiulxZ+oMR~|#EgMZ}2vkSA4sm|ZqB(t?8 zG%LJ$J+Z`YVAo1-eTfDV0xkFmTnd^s@8|RY@_59Wdv++;qt&>rXm++yVDVmgh_?FJ zhmjrz0en;PljHq-LB0*x!ZLX28OzV4_)DsG;m#o=%f-SS{+SB{6RJpe_nE+hPnpHh z63J$PkXGt3wELZdQwZ=xv`AG}N%ft~lRSgr>7wf8;8EBKjjG);!T?a~mA$s0oHL zt+y(fVuUSfQH0$h6efCG>;U$DKNJN(PjE5WM_VLx{;hSyprKeW>tTTwCAXKO%NxnM zgB{Rzd%1y@W1*~qB>IlqXhVK(@(aW2*6tp3-QI<&V(ZjIe+cXdgxpWg$}wRQPiz$ES2`ql5mbQ0ZC_Mes- zi+|7hIN%+fEFPP^KmK4viL?f61vL5rJ6?b&9I05gTIH{vmZq`VLCU2|JDS7DAa*=Lrbhdl? zTeM-R-B`(5X3|t;#PnL{t;5cn7~H|9yzN-3V!^x_hCC5Hp4NU6F&GRgmeJd26gaYU z2hz@x@V2~q#fV_ohM2;RBj9A4x`vijY;3$K+I#?zoi8=-sGX8TlgYhImh6fykeUuA zOU2mH6-FmX*DZy3#yThZxR53)%FX}SpPUpPPqwk8il|dLKt_-5A9YMFt^AuA^uNYiT1@7k}M?b((Io)O|rvDRBDf>DYq5SZPW z@auN15#BGV+hAl#)&v8&nx4pFJd=?SGz_a)w#rFm%tH6aP^Fn_y}x9nUWGK#uYfDx zegd4DcPrOQxOco7qvcR#?Bb?4(`xT!UWt(jD?&V|foke;%6S)5R)NSv1@8W8QpGUTZLnwe!+M(n%z2Mz}Z64D!OW~Oe z#u=~e`T{~4GYDJBbWOURLwbeW+0KkkO6J)@ZT__OibHr|*e1B%Z8pvB@keIONxD5O zHg2Z7oai&A;1=Xu*K+bmCmU$kH}##|EYCBRQ1t_{7b@RT;dt@yTbMKQKMW)P z03_SK-<7v$DGjzbKKmqMRphEs~sP1;wO`n(74>SeCS(x|c@JzKSdz?5M`$=c$n zhh37qvTLHBgmJsSl9-yZ%t)%tOw}Jrn(EpV_}%p6D5rDvT+M0pu)%`ZNmOjU==tWz zg@+ebxv;GXO6E4RQryGTI-d#59FGt1p%O84G+*-@7zAAfwkjn`2o=<7dtb2&r}(xG z1)M6f((kCsD-O=48+ba3=&{xPfn`~|XZ;dp^^pWFEnn<&#>s8Z&hajxKY%hYF~>8y zy^$oQz`Se52j8DOSxTTvfCSlWst{a|`OcZ>o~GiMQ(Sx%1=X)C6LPbhC?%G!ZzRUv zrN=pz>icY2b?6Y>rW+6Eync4eBZvw6(Ze(0phf3dM7nx>$pMLTuba(*WwZXa@0WSA z(!y=BrlOAUl*~zYA=o!+d`yyPpi?kXIACQUqrT8wr;97UFFi ze^zStUg|*zy-??K zv!MM5n*7T81!po9!N!7J#fip!>SDMJonw+B=7d;>4X4VkHT%a;aKbLRQO}^9)SE)d zU8_*)edh1Ia#qduQN}y>ZUc$r;^vfh8_2#x1kQgwk4$vQaa_i&W4bKnvNDE_4J2o^5_K2=adX}t-7!sX zHt~s>wF+LCSudG$Y{UiE;voX>K18Ec~N7zj5 zGWetR(xC)h>R|>wjY&v44Wf1#hN@TRl7?tC|;}7hzhrb!2zK=Bj8A}_z_oC7UxED z;Q~*H8Zt)fcW;1H==bGEnZTrO_fIY%H0CD^cTsl|)9&3k;J^>9{@&kL`u_4ioPXqB zY$@Mu^-f)cOMPGXZ+7D478}0xe!F-#aUPqDAS-Uif>oN4m>4fXI!W>Rby(C9?WDd9 zV=@WD#efM7Dc*}eg&EXfQe0;)oJk>R!d$;$9FDhJ9msAjS7F-M9lp=)vm#$8eTgb`^pM-qXE z*yh&y?C|G~fw64#@Wy59;TWs<8H&ZdvQ)4EJ=mx%NT@?rI0`~`#$Zg)`$FCB4>7W% zN_SakWMtyKguzZT$*L$qmDu&4bQJxV#kFh+!AE#!SdRExQnmklO56CuLu zq|$wNE}$j{2&a#>r+|Y<#K;PKlL-NIp>UXB(O7yfPjL|zDjOU{PoW|Em> z!U)n^8wp)y%Wc^lUiM>R_b`7m)i3b`k!Wus#Pvw^eny$B+If(uu!rHB?mYCX|1Vl6i$Q{eaRWKOrDio+c>Fak?zrfSY z@LQOBoHy|B#Fk;|$g)A%A5gSF;@|!0D#`%*dGD!sKc^2q3cAJt_i+nsnyVclQ zIQVNSuW1Z~qx#`+tOqaw>ji_!*1TPV5Wq1e**)_jQoo2o92+R5eHJ&j`ROyg#uO#K z9d>b*8+L#+Nbzy+@PjZ7WKXmiBr~U5N?zZ%=cLZFdoh3ALGdpz%W>@;LIl4YIap_s zk>V2opdc3W6iqia8?X1Xt)&FCFqRR=JoXf?w$&i!gDw=#^T+G#0E?gm`d5@yNZ46iuwsP0fDR?r7cJo z<9HO?-NIvBoRS4M6XqP!BxeL+G7)_Cou1upP}eRUQeDGa$`!g&MCZw?uQz;Y_Chpg zOU-ubyeSHkS1qqsBPsN3C0(3*g58yHFMii59WO3Wc@R_dZDaoYiM1e>IN4Sgn|ck1ki>8HycQ{xcSN3yF7V~K6T5=E8(+R=IR-0GI%7VcvRB^>e27wBn_5M6C-ocse=5kPk+0QZq?naEBa?#8fU&)==>h3aH(C{nC4r z93lvmGG;^wWPBzjmSk}q7;a`dA@JI%l7`z>`wJ^2+@7Cepl>cTI{L`;}5UQHd#$bhHTQTR4lWKGcyHI?z1IEq1y;} z2)(ZES}rjTXiR+|k&v!K=spXTCAO4XsChzT^US+I4De-fPmm%qIaF25SyFQ z`|AwmiH1CBcw69{=X_36(5bku=6+kQAGeDAN2<0|h} zG^M<$I`!m(B;7G%hmqOhEnW5=^#%e7s$|WCT%V|-cykSoZ8V@YbHg{WY~oQjVud@q zLBhqpfqqKLbbj&ck=*)9SE@1W(xG>dT3Pnc@+z}Yf%C&RJwz>>#7{$PM!^b^F(j=m14e^!gGc_TM;^|7g9^_ zF=>S9O+-*nWvI1$2nd}BP+k?F3+BJ;q>oOYG%2(X$S^4xsv?(tVreok+aV9C?g7=H z$n0!$JM@8r0b-8NU&g#t^B!a9-_NtCA!)ek5UsBoIyF^rw4dYk0>ProI^?Paum8l# z0cFXFhszv~&C=e)w~bp088WUtEPwtDrGxY6kt12t!@Wt?8VeSX=Wb5|CTEQDE+}(+ zV6*$`U1D>69>%eg5}_DUcfb3Q$?LytE?1e4dK3J2mnY47-)JezkI9f`~=!QSY*2UWY*>Z zFV!z#OhFr~sr^E^=B*9idxFcj>9iQmf)}(;V2PQQYuy&SSc;Rawwy~$(1tBUQ5ZHo z%}S}DKlv%LADApDD}IEH5Y87R)Lk3^_GBrYjhKFC3H@1)t0Wu~w{Cre57|$$AV4}F ztBMa$sR=HyQGOR<>;wfTZ=#7|W3-qI>LC`FFgDagymVKpKWD6I7)=|SK_kLq%GCbq z=WLVVv1XSEY;sFqryiji_d$P%1J`X{_m~-#oH)8@?P8hCo|k;CR#jt?y@=@l84e<> z&!**`0eM==FjBoZ5TDhd;5)9_cg8WeKP0itHEOg3fgPOkYo6ePWbnG^hEjGpk4=?4 zQpK4J^DQ`44TT*fKCpuPvPUYAQo@kef+KHM@*CQQdlR>U)*vdO2O9H`enw%q42&Zj zg1i@P=hMs;jlRTxy>Hp8uqe7+;`iIO|528I+fp$9#D&}G=liK|8x?l)z8Ushsy^y< ze2X;s+xz+l)4%oKe#PX@j=r0B`1|$WYgJpXXC9_qD%ft&nd8A-h9=T*lJ`4N@AKaG zXTHxv+Hto|ujvp~r7MSr1e2(hnN?@ynty7tP(`qk?;GZ%f@i??yFvp`b2CYGQG$*N zdj(wUR6c|Zn+U^Le^5y+i-Mw|d<_THF(b(woZe{H0GZ^2y}RJs`$?DnIujl0PKJg) zRrB0RGoP;hwvv&9aGT$UBB|KZd6wwj%v+eQ zbm9<8zMBt_s_P&LNY1Byxs%1lkf;^!(?K%NIH?71rg&_0PP_!b)^`m6hWM^IP=gS9V_~y8opcf|@|&Zp*>^Y}|Ck6Ho-&gd z7|%0%x*6hRnpo3U%a_bBxJ1twWG8hFTf>${=NR&lDE^5at#DsL^w?H369#IB`8(^~ z^HW)^0w;S`nEZCwW2f}bXo=KX=BptyEQ|xtNRYgo-zaiVM7dwkN{d63I90<1Q$3huYSPd7C!H%r(GBv=5-XKH@T$TMC%b?=bbQ0Ws^ciYk zLjZ7ycCO{WG9|9f2WQ|AO|pbH-M4%_T&YNu_W#q%3D7FNl8>P2sSy#-5-Q-2e=pJo z3HFRio+F~ULV(x?T5fGfAL=v|bPR*~`zY|UYWuna=JV+`;(xc1+`pnL&)?5vaEz(w zNQd*exHkE$WZ$MG(`yA)*JCTp!?mim;xOFRfZw%7KfVo@+{Ugy-ksx&93E|Zl%^AQ z=f2?lUq$gl_UHd6F4Ow!6{)<1m%dK7gf|Kt{rnUP>;Y=7kg!&gavY;zvhmK{?uyao zsX^%S)7UV^tn&ELg1Dv{u5O1v13dNNlO5aH&L38`D}(PUe80B8Ye{^C z*xmMeAHyK*oNc9?W@L)YG|3QbpK1JL zxb8iP)*TueSVZr}jsvsagfw*^#W(E?fzG7p#8e+Jho+Fk(*h@0^mPX?;Lq8q{O?2u zJ_t}HUdU2&%K&iB#LR!e<<}z? zcGbuy6LGqfy_Mp`8m(mdONlaY=Q`Bql_i?|Ryql4I&atShje2d@-(HraR6O02Ab&V zbYd!{rnMq)`ZzENr_$yaZF<7OHmNm=WTEOxedB76`piP1d*^Gi!mCh{oXTyIF&bhmEGh>zfDQkO+R)34ytpHrBdKK8Cek7U3&3^bZz!6Rduk2 zjY4z_Sq3fL#f9D-4Fe7h=d%4B)tz$@ygGTAeK2XoEyK3!bJXXv@ z&g;uYDxQ>(C!C5FyONe+7uk&B>Fc1i<|jt<&%NJWVD2O+P}1svniK*CClrg2hP_ZI-gq&Q=OVPOL>6n1h!A#Bg^Gjuuxpfi> zc9@j>^Ny)m@=y^qwd;;O!C0-wyINej+=_cB&2K6tS&<#U!;i;b31rcKVzO zjC2kuZw)@qKUzJM)iH)5Nae_50K_37gFoEcGgi87nr73F>B*zNrA9?%%!Lekj8X`q zlvQ9c2dnaNWmWe}k6(RHi~5^#{*$xn_C@@7aQN|m`P|o-fS1fwvd$k1@UT9O4_^FG z2hqyczh%$RL-)V@@7(zRHkL_F(-JfP8B7fIbdy${x$hrU5CJZ=d(ww|ZNGs=pV|mS z=`ko6Mo?6&`jfF!o(iRBnZO%lw0`)TFSz$%l=4W(0ikND&EY~yH$5L98}hmV1(oWR z1i+NeeL60-Z;Frq&V03(3^9FYzp9#w1de_4<}CWPr0&^Gc33EI&T&l2VO z9NvrTHN03*PNQqwuvdqdSKw}*roA1iCfrX+)~X?eI0jl6hKuV_f1oY{ zQL;@6HZ5?joo=#N5bbeRkdyOz{o)nDr$^uAzFf5s;VzF-azADF^Yu zm*)=4pdHI+yE46OOBk)2zJop0ZLBk`B946@m~*sseG9t(O~$wTOe}={tsJJ5t`P>` z*@P680NV91h!&?}hIr>zsO@N-#OTEH0WaaoE+v&ADTcsJ)&aJYay3u^x$@RX^^8`% zhJZn(d>Z1#yY079YV(o8H$WY&o|qV#VRwinjy6iR1}QT5=%|SykO5Fbb)D!1gkr zVab((%Xj|L)5pZU+PDAL@?4Ht0*XZTcyC=svqeLHhV(g!gh2dQ{j|?F;0v>vUEf;Q z#LTyA?#A=tG9*AJY!fQJFexyQ*2hdDV@VvckW;8DO#@(R5&fAo z|Bp_OYs#YM6oHmgv0C`?Tc*zGAJoi2ydQrM%KX$w&2^`dW@mNBE_|8gI;4{<$4)fQ zeai`IG$y2#zvhE~f{tRIIKIlr&mE(dFxzyu8V^yGco#sI|0=l&R%l=H`eQbcj%xmQ z8p?k4a>A9^+l;psrS{E*FD(r1CP>(-3cjaPkJTUF1H{v&&kM($T$wnol_bREH9fYi zM~Q~zqcSfStvfeF*Xt6+$K*o|Io0-36s_1TUF%E!i4>^fUuw>9Zg=@6du(;7NQfR2 zWcv~mvXuDu8!&5;>+B_t3mwu$CbS-uTSx@*;TA5g0|zMQ0~s9Va-5H>;8vUmEjJDY zAHeJ7Rm%R)O$Yzp@XIoAw51~Jj8>H5|6u+Vb6xO;j|>9kyEoM%9P-;`>vR}g90{H1R<1z2T zKR(6#0mB~q0lzdGA))S6LSs$p<9(&yu|ANh-@5gQ*T72{s7v8DjqsI~4!;OF30S;9 zO`ydalwbIQV}CP*QLB5!Ouu)=YlPIno_BhR+e{yRP|H)ED4Mij(-NDC%+=n9@svoS zh78B(-O$DnrxC5nCLnQ_D()GJ6zSJ6L36o5r7W~YH+K(u-mq{7InUpNk|)8pYlDik z6^83Kpb^Ej7Uk{Q&%RGlczTIhMWV`-{M_ckA9_Hdw|Jkm|`)iJ;|NE5yfjrYE8+qL#_EDGc#WHkQKdUy|SQ7_xyZmyAe zGxq0H{y)5?u~+r^9Aa-E9`BXv&vt9&Wz!H9h-MAutJs($l2(V26g@>V%59~<&$@*= zyakZ^sA6Q*z49RvFN5|@`)ODIhn?I$b;C~E|L}}a_O7_XE-#E2gjJ8(MH;TMz#so= z+YDB_$YJT`0i4EDxvN_Jw~_Bnk^WrPyxSBJyS``rJK-{QSuAaT^is_Q?tj8)N37G;a2iKkWfKExP~QEYKd2hAgSP*P;ldT!W2w z)MPE8KMm6~b_khekCU!4CAb9`_?Cwc%+*;JMI(OHE8-^k1B7i-p6y_(xL0&d$a_j5 zw>kMDk{-45=ZNQB+H4h%pEhEY71DlB=J?#g6)(b?cCw+*xAwI`6b zkfC?X{yVFRawYfEFss3BEc?t{WDh+Q%pO{C8oIN{!7~0!^^|n6a)eBx19cKuTwB8U z0cxCfLT`Z+BLB7AdGBD>peZt*VPspX-AF_usEv(YAw5j_Zp#0KF{|wF?vt$6K_qL# zLyx~fITTr}Qe;vJT+jd)ybHWg)7bGp#{mK*W2Q2U2;Mi_mr;z%VM`) zE2yz5zZXEGunTe$U4+&!!7B=^Xm~fTcN_aYqRajz?!`5!%AM~_n6+BaIKyokZ5@^6 zEWu0XK7Eyyld}??&tbx*Y9T;H?j(r^{ull%+}Ve7j;7q4CQP59Ct@{1BQ+HM*Qir> ziP=T@^(Q7&{v+BaGNQOFmet0mx=CX`ZJo@_1f-L>*r3?BASx3AEn5rX^z`n;UVh*_T&IFV);L{kG82M%*lSoD$_9WAdZDQw33UXHFn)}G=LASvlv}4STP!?NtP`0 zV?VFAw7jTnOQKp~0G&i;U^w#bZC_Bv8FRLq1kiu4Y603gN-)^4;DtoZ zsh-#$JCn^d%P=QRJrQz@sN8Kp{Y4k~h;kT2wB#P`e)TpB)vpkm9#Ye7(ucb>nWrH& z#@SRpSvDuS6`voG7h2%(1*9tJM4Y z%3$sLK*b-aXVubgUqknZUNw!ssW15UxwrPJh2~#{McDJzJM$ANnNN+W{_{_aRGXWY zoA`pbV3s430TO`=zAIMbZSNjTb5kfAQ~S=dSgA5=m}-|M(%9n6K3pa9fjOcS?vYf3 zOG^DEH9RIFV7Z+fvRv8OHS5l8_P=qtteq3N<6nEjSw<8Lm@8`u8Ky}8!*e#R4AeZH zJXngQdTyT0y(O~1&orK|8sjo>8Mqp>v}R@F6dILLhnX3fuI!F-S_jYXX#r8PN}DE|=Y`gUQeO1* z-cJH=YAl8QlY7(lSjPQ*m(j@l2KA?{M(8HzBtbn(fKEqZ$)eqRj{-~WhteiTl}0)? z`*>nZR8_Zdk%6VZDn6q&+>ljE@c}09f(KV^<5@CRrco_M18E;?GJSf}br~oUyvox8 zfBGedM|`wRt!`{5NEpuFBR{GmVhht6V9H?MXM65Cj9L`FI<96GjiF$+%M}w(=Dow6 zRSa)s?h1LyJ?N`9xx2qKbuZ+Or*0F5pVfW&_Q~SIUAp3(NB>3mEyD5l!3&r3kEv{f zOS!cATyM;?Q$s81fFT6*{)52HE)tOi-)?POxgfi;{G?ib6*VySNo%yXc=iuB^YZrbq*9b$J$bZBBeoIBPwsqos?XnBH@;hzy^SsX*X7ig zZ`E^KpOq#$!6!yx)6pA~<7xIL?`;;LKzW(-vUWYYyn~s3>IDG+JV%%fATu&5{G(@+ z+hf#fxFVQZvHy*M#GKUCT-U?DHOj$ZU&I#&g_7*Eb<4BL!giC;8W7S<_1y=5;;4?( z+>cPf18>fJ1x}s9eu;rz3J<@+EZeTo?uI$$jojm#N+#lkBfq=-c?>H=K6+f=zTXR% zE*ELA4n#$8xPSfK^tY$$kSzDOWiy!aZhO2^gMdJn(=otG;u&gHBAL z#rXvLD*+vT-{dOs^D;dYUutgqx3l;2#QF&bQOlE)J4>M<2cI5fq49dKwGhK}?zv8B zR!BN4+o|W0ABdY z@g2C0z>#F`5y*n^b{AnjV(;X!>muUAU6FsPJ=T@>sv(P#WW+d3qZc{Lxy8xJ>WD<9 z$pP7zT(!E;*B6=CJ;(2*0c`RX!LCj-MfT;T2obrHYFk9}1YkfTQG>=Lv6D8hm^2Y< zWrPS@+$u;p$NGdo4rjD9i|pbu4f2GO$j@miD>nefPpe>EAJImmc;I`0(MO6U_rE;_ zw$t~Ur`%ujPOqLy#y%qKl3s00aWL0?2z0?L(hGu;wSZN${DWkL`MZ3qfykT*28_pJ zVvo2|_?hmWT%HB(X;4n2NVF!UB1iT|O^OM&46v3LtT{>ExyzCq# zm99Dr7^mOcRD%|aQOG~Sb7wmZI(z_Nlm4dH0^`f(OfnHit6G*AU$UbcL`JX77;yy= zeS4V6{nm$0-yjo$7?yy*2{|2E(OIVnFxLUg4|;_-BN}~97(~%-DA!q@_HCh;!A0Lo z*OOf-cV57COzyFKOlyB@cA-bIrpCO%T=25~03o%}BtEwh@V2i3cG(+uxMq5+g;DsL zh3))px#YM}-Q>A3(NnpG54)YGSnpOJ2Zb4r*(}YZp^eggk^mzWm01J`2EJ-xdz!(dO5=iwES&And%&(d?omuk} zvCr3q-03&d9>zP`U=hjs^Q$@?&3f38UMPJDV%7pS*(j^gDcbe|D-6u3ynIKGo)8m1 zKwAYqQ)57;hUHlGQ`|S*mmp~+En_7pl)b^ZjIP4Vd8Y$RO0=D>hIv z<#lLGnhD5|;0SEe7$AmUW7Gr-4Op&%w!m(SkDaWl-L2Y#;!h|-w^Y}h+Q$quf5!f) zSfKe6P=xW1onV&E246ym#KW8`w|LxF#YcwF9yDrLd-K5gV9P!p9v(pEjwt7EGlPK_ zw1H~Sxx*(mzL>6I#q~AAXT}M&PT=4O{FWDu5+_2HNfEE@yaE)-Cym^v9fX=h;DIep z4gvFlJ1wn{ii2>stVrTj!qoccPEj_D57t=-HR6sR7V^RI%5QevsiR=24 zvX+)lhAJTgb*!Lc?FSQ+-uY}4BLWx#izAev;87?MsB1yt^>Magb=Y$5-p?;}?7jd! zzS`7j)<_LFr8OUa_LojDiPK=gfYAy5L#in&PLB&_NYm^EeFRAv0w=8(%Y-j_te`*o z);D}-MI_>kR9ad_UNU-$%@i_@N*7^=9Hyp;B#ZkqsM#lS?w{n}u~of#?g zA3u7wwQ1a8hCnQZusF6qMwwx%1=c;gzbNUL;W97Vj(<6)j7<&9YV{=LCr7OQ?GQ#* zJkGk`SeC>?9fMT!EAEY~qkNMz(hzhG7_NRiM(e!6ZxS;cxE%b6U1<`$#~I4DwAT18 zO=7MzFc!LgZdst>{pQlNgYIQHg6QfXk6XbrYP2)rrTZyax?$U1E^SM2Gl$#$?{l3Z zp2Nyz=v0iT2JZtYN_*`%?KqHQZmWX_ApbJX>A^hC*~9!B(^f;H(c4TX3qZk?-g17I z*P5}cJfnoWpb5Sca9Adhig`+EPi|^tb}#UJgstTrkmwADUc^7-utF&Xov^eaM#26F_*;0NWI5d}$R?GQ{7H~&su^;G7U zPOol9s3dAwUb&xZh`h~tU@f{U`9QaSE<_@Xd5ar-mE~vv94UyKRmt|5dYFTU?yTMq ziDsd*<@s7*f`6Fm49~M*xPV(nrM#tIC6%RweiQkaQP9-nv4+6Bc}HD~;dc1le~%y% z$Sw_i@xd?nz~zTt#jC`j-(*yUdt z{Ytog$^Jh(5M##Xw>GG~g5nYL^1)^6(RRC51S2e^K-h4x#9{#j(~&HNg1EN;v4*P- zneT$=I&}@czGwO+~cMd3BLl_>;%P{w{() zB*ovo*>azfKf32GL#5+IBrHU=r<*xVaYVw&>8Ei)B2Qxg75lnW%rZ*R$E+}2AFe#` z_#djhHQ_uD%NJ5h5;4a`B`o!t1|XTYMCWW-6s)QiIQ;8?p5+VE-NmZ4>bb4M>pCaI zqX3-*=+$cIH9I5pqk0hi&66QQIDENKLW`S}MB2o)0JA^HZKKPQp7a0z8-$KHwI38; zsCVp6i88dko5+rNoM~&+0GXzv_&l;-l|=GGI@s%WqVt^%Se(^6b29&+VcX?W{^=jM z4{K<>b%m#CcL|G6iQ6Yz%kE8~Q+4y2%;1YIYxaS~=iU5%{ObL&pm?y@$JQP=BB$&? zK}E=9`Bx$))eu#i1F6C{po}PuleR5sL0iQRASzCqYj@qFxCRj9<2S3y+N_sS({D+dCtMayxFA@`thNmj)J z;VQIHTQ?wi&DkCEA~l60C%STpD{=1&F4M3kf^)~61$QM%gLA1W6+!{nudh#%4IH2z zL1~ZWa|GEx@_hrMqJ2)L9_^k!hjuCKEpgb4tZ}(hB1TPF~XS`!|4>A4svKeUwk%A*C5Y(p5>(wdry zULSW)^8)SI3lT+bMsFqKDv|Uy%G+4|CqMfyV=mS2Btv2BLpP!o{XH4mBT#3&Zk zS}lfj5Fwd?#|YhFDanLN#xs`83|i$_qhWBap^#lK(CNdP!VxMoZA^Y)g>4~KF#nE; z;Np9?b?O1z@(cJ+x{MNB7v;{xoP!Ao+pZ0S@X-h86_BmxLDuE;U(>r5dMog?JV-<1 z^U6oW)6g5M#CC;Oq6H-#+e?g6zb**S)CxUWl;PjB?sviNVGjIVrCmRm9fb`a!h6<0 zvW))y6&6B)87hO$Iq{NuIXhmM$l?TX(y`jQE63+T6l#M1Ws_spOZ%sSc)NsxRR>0$kLs>)rBbv5qMfGGJz zvLBj`wDc7V$nU3+&{ziv&R@^T^Pec6l+bBL<3&bAjn`uB|HmL;@{Jz&@riWa|0xe; zaDmN9Rzi(vE#Mqn;l$G z47c}baF_54?}GS;jdeWq2eKs70}#QL+|Cl%9Hm!9V#_G;al0Pw@1Ek~xvo3PauniR zFnsHpfio|BoAJD{!vE7VTa?$KXSZXX=7`|2Q!K%QPJToIm*LH&U9km+%vmjpxJHQo z*_br_pxa8Q89Oq+F3^zAppOltm>oJHofrJIju&PsWuzX-N4+Py@#?C>?F4~i(K3Ri zzH~h{9))Z$N+*JSuU?s(JJ$ZyiK}uCB5ttNX=nw)ERL<3sA-_oa&LUSdVx5$Kbxcr zyFbm5ra90vjXq(AkyeG=M&bGOHW2v8<hbzR^B1gMzt?n_0S#pfBm#SdY18kh(P1_v$ znD_@(919{b*St=`VA8pc)HL40 zbyurDXInOH=1ID!%DL~q=mciT_MJgM;+sutR&nEgQUHRp6hx8jg?+)!UHIsIxCVndjazsbj?{<`}=<_7W!*tu?+ zX!9B&M5?W>pjqlyJ^Z{w%1=NkcY&AMEDy!KRMDN{)^NJS%(K;f!{zCp-)&8A zEfVj?k+{D2=>i#>y_J;mr3y_9W@n+sfS$mr{a!XtSE5#|T*;-ZKFEoO&okWj^unTX zL8R?xLdNSl%N=B0yPVc>B(vtdPUyJ&pn2rM0|`A|6QVLq;2+=Z(H46$l{0}_+I{h6 z71)zn!TD*Rg-Al)7Ljs2rIsf0kzW)Yez|@$(T?RP&uGCz;F=KWR|HJq((449`CWM>3?{tuTC~*6@34dT~M9eD*jx)PlqAy>B?5(N@n6{z=&(f z>+8HDtELbixBG0d=g#xq=Bb{NR4_ep+B|Y%FagQSaZ$t5Qh*6i%RJ4N#>HfJ`^@}u zqU8}-=>`w7v!K5JJeCLb4hx4nk>%U4vZ>7;(o(RQmzitd3)1o5yk}-ud>v_PcZQc> zU?E0r%C$A7{yAKWINLoZ*DGHqYq4j=&qG);EQ@!pSS$=!Jc~=pQAnH46Eq>X^_Vp! zBN86BFvM)umpEKfd=lR6eOXv8NG)gUr9jq{QU+YpRB&LB4~gBnZ#ycd>T#E=nr8cx zFxo4WjWfNjHLH9-{k(DJ$RwvT+Mo~Mi$V0J1Z6dhuY(?FjYB?3_yA^{ET|JuZaZBx zzJm8p62Y9q-U`<_|OV_7FB%lI*eZsr?T5Uvh|w&eY3sQD|W-m(phd6W1F0;lwh19 z(J&N|<(nlL`5?5r>QloVYfGa_3i?*B_G)XP+GDiKkbM)Ihc7Prw9nSb$J0XoP>gHx zpt!CG`M0q2tZ#?V#HhbkoP%~W{~H+$^Rpo()NLFdl=fYQF)V9ebcKYv$pYtk7@`e0 z7Zkmi=BP_6_C$P*zr#JeoljD#iT7JghgqDrP`hQOH2Ai2!+!UNmv#{YGdIXuUah~){UWy>=TXwn9Q0_~Gvlrv?< z>7ur7KaOSP6T&g>-8%ptYUAFzX<7}~=z2&)eV3}cKbfvn)qP?gfq~6tcXn_<8#f?{ z8#McQakXZ}W?&@`b%dj>WV$X%%2<XYW-gpV=xf{nny)!0J1 z*Kl69Y4OW0!9Su><1);t7FzD|Y?X}C;2@8z@ZYkSFwB_*=zfF3q@;sMm_gOMxX5q0DF{Ez9(>jn`Y^!k%*=o`~jK(D(;0wi)g zpq+9Xjx-X+w)Xgn?o=|Umq+LtPqVi_WX%_uE~Arw=G1@~Uj#iN{A9#bgtfXs4g;99 zP?H8)CCACoOaIzLEIY9AHD7%dL3RN5U=I_CoY%wzV*Lk9JRNSZmffw~dd*7pvTWA> z)+@U^bgI)t*E+Q*akD7n+iP%|VB?4UW~U0-@0YYw?{g&*g$pwbd&xS!$~R6g+=nA) zXweGJkK|9O9Ogba?TH`Lf-2M0|dc zRb!#dFwHxjJ7bATi?0|990ThqNp;lyULT~^E`gV zePxp0jmjF$vXHH2lh!<5j}TS)s}Q968CPL}GZV`G$`43&oJv=ULc+9DN?uSOf{ZVg zmPGG@zHF65lUu)?w=t|fFOhVTo(w)eFzuv?^0_|wA(`Sf@c|q{X(oJNy&fYW+Al*3z2+tU-%Us3xK6Yn>quvYHMMR9B}V{ET#J?tf74(`+JtD zv+kGyt&LBy>q)<$1Ai~e0~j@I?v==sRV$uq0-raflkz`%l}NzDhXa+|6J5=#N0L1A zCr8-XNmGQ|L)G{{!oe3t6zc@sZt#p&nL+*bxj+<(FoPiVL!!yIe$5Lp9w*{hG>uigOr8KHh<0g2h z`v{-&*ip@k6t%Ibh@fY(3P11Z3=1nqM?JSOd)pBovO9i#bpH>JuJqN=h2hD2>4Tyz zp2z!a8Hh0e3jCDvMPXh{0BoO2Ko*7M^F;GEilDteCyA>79xM17NhHa#%Ou&tKK!xlgO!!x-0!(PXX_(GoHnH8Ji%=d)R%*VFT;)JA*qhf*V^t=!c zn5>3RmSLxLO_%?}@sz_}37sSAPmX`cN~XHqLS*cy5u6-Yw|}l+`;7)b%+Sv+?e)vJ zT}RYxR1rz*TR?UUDbnaXz^tA*XLPF;oMt~3o(Bo^2<0feLJp)>LaI25#DE0QoY0&F zo=v10Qg4KWss_Yf-z-oQOYcZK|h66LcnR zb;5LQOp`;CO(hoa^L07BRs!Pt<)#O~Nq(+L2c{9$bg33|LGV>?5;CDsU6qPWAz@N6;- z%)gh-atXzOZOPt(9{=Vzs7ObI1Ba*n9MQqt9Fu#`-#k;AU*XXn4_;w%0ts4~S5mBR z^0+dGvIO#_4j2QCF5r;)KtU8Hc`!>?x%k6$bLw7ilS>9Vu650W!roKg6L62u8<<$c zEx9Y2WnNNaCAcAjfIUK{EP`z9w8=sseL-OFq+5x3gR|RL-CC5pl#)t<&yvHyL(L+Q z?ADny--HJ&qk`k_#X>EH6)51orTNyF_8;!?P1v7FL`#%!1VolSWahbw)yeB=2SQ5R zotvjeE$vx5(6GS|YtsJ74X?2x>G?sn+HMc!8MF2;_J8!KrZTiy7un%xY$o9&2%GY| zuCF1{O_q*sIdlzc-Lr~+CwqTX7UUh?W5P`fCS{&m^42olR-_0~hO@kXw1ZOMd60@# z@pZ3f;qM4gRxddop!a@@c0|d(Xv%ArHS}vX|H1J|=sSRAvnmC!gX#TkTT7&rQg01P zl_Xcx(Ni)-tT9}Q>OBUy3Hk7#DS_2Nk80{o$cI#u1E7P-R#pCxwO?x!7sOMKiPFK zY~HNU=nNk*xy5J-cn#p_*@Q;sGc=kW2;j5o7FWX6LedTx-q^&{v6nx_|7_``(b|;` zmHueEhH{n8Kjp1W$La|0Bl+Op$TG2Sr;SSO{%3h5^VdhCphj+NWi4L_(43WdLCGrriy&&^H{cizT206-(i^W!bh^wWx2Q z+t*#>=gdVT#PNB&(y?H?$%2Pems@2a)lftdQAN{E!B?haW)w4+uUeN1(y?WKv{5c{ z!EW0*i`&mWNv!49YCL^d_RH=WeWFen%G04Q4VS$6Whq=sbxe-C%Blxc?nZGCXF{sJ zQqk*Op6zJhs97Capi97g!0EZ`E5mR{}gpvsopJZ9I{$RWf!CjR?t^LB^9_NjBJA<#Ik>fD4k8rU1=<%R=meCN7AqO1A!Ts zGP9bS8(&56cz8LaW3#fv@%WEkSZ~}3GXntV|Fxb`e@c-63KDEmi9rE0_>As99NfFq zW%8wWBhcR6gS78`vhBeU21Th&29oIe=&~DnI{dX+)1J9@l92JSs8Jxy!(h9p_a5>` z^9>*5lm1>l@VUh+sb9?%aX$ay{iArE@SWUI{Tl}s{{A~rTG&d!H@*Mxgu`Y78@@%@ z=vOTy|L+BFvVPwXjH3fI0;(fGr%`4P_5(z#!5Y4*Ge5&x#8m| z^<2X)%l?Ky(|jp~$L=e#r=3W$=&JzX+_0I@-%cS4vF-vdC{ta9rY8?fG7Y*34QB`C zBwk@&H{U*Qwv(!dt%l|4WfL_n`|49hAa6(#rUuR5i!`TCJJ!Wl4WjO;2x$Eqo zE*W=OABe6|@rcOEeT8>;G=X}Twco_Ma6Nt=;G6Az@vG#5iF*y8YgR{H^gwDBi0XCt z4{x0~)b;hM(|Woj!m7{y_MO~VOXuN5P|5&hW3&vDb-hqPT6Vm{0U=8dw0ubi0F}@J z!p#AcFsJ?h@MNxG1Xz>w?Su5!nAIbW_3we+kt+QULr1dRmV#1*q^g)uP1y#FH4~y+ zl7bZ){7=M^ha`D8-g- zQp^1AUPDR>@x0SoY7u#l5v}xoVVqyhN^AAvH;3cH0FnVvQT&ZA?2rp}wRsgnpHigb zSky09;vFe%mMzv52cR-IR-~AA+!*|Rr(>xQnb(KhbkraIQk@pVqP4ew($sbj-T&e^ zomDY;_5l{2NFoS~e$W!~qeJh*ZoT{S%ZL{vAs~F43Z^*V*=Nj!!RnM$ex}9c3zNXI z70wQQrfU;%yl*h@M`F6GnZ@!hgW?QBM(db+@46(F@reb$MrgHFmaA;USYWrt=!CI) z;e?cMYWPM-93&s(bY$o7=eVV4<;s1S0UYv2;_IiDsT$CJ=p2JPIlU{QVr?EL57N~* zB~VUh>FUOpV2(NDw5Rf{B{*5^(;B{L5nr@);_l-Z>FzMfF-FBN2{*^}*An zp0qd zNT82#dH9z8l-!GXGEZ0`R}IsTWF2ux@yV%HQGeek?JR{lm<80XYb9A>?G;kwAtnzV zy0OQM8F%(@sNKHT82eqvwTKmu-~x*5NPiI$O8kYnKbIEUOpW~3&a6D__AakpFex6T z;ULXtvsdbj=QB#gyoOq_Zf1|^@_+tZNX)l-7A>xPNDU-lcey95U@lZ%@uiD3o%uF0 zt#+NByo{@WWE*P>(E1r!H*8ks1X#Q3!SgV zz0=^lMjLf%hI{+N6htv_cqI393MJk|4PRh7VtO4?J*lkv_6^L z9Oy;844o{TlF@fg)#p@CVVA>xHig0X@Jz&W6nkGpHZMQv7hjtago6W`M>NJoT+(ZO zR#xWxEA7RWQIx1`EeFm1wYfJ9L4>pzkRalmqeSSJGax{z?I&=z)8cnNBuP_6d3;6d z(vTYNUZcHU2Mq(mEO_x!i?JGc3KN|V#G@2h;m!ZR>Bn&Rv`&g00%j!fXR(ys;Ei-$0YKa>rIt=LJ;~(iHdzFpYF7zBu0SByjA^K zh<%1Is~K;GwGF#e?3AJ#HYo~^Mj`Z#f4oh@4qMNYq+POK^IcCFS*;Ji`}Pit1eG&f z0S*(|iz-dSWSy9Oc?VA7k6K9y!3Yw^zun8dEiymOed49NJ{1jgW^pHLm5H}ObDG-~ z4s=YoVX@`jT*IZD(7AUCn7Ia-;^=dgO*Kmq-xg_kUq8^$tBCsyW2%Z-jdupnz>QDY zKtF!-L9739;264b**$8yi?}`o&N&&7Xl}*Bw*DU;hj?6roV|A0o{)w1$Cjy>pCGlE z#BKKk_sYT=1y(vybFBYqWH+jJ;Ny9_i^KBfZV!7AaDkiWC@(EFd5ZeV=}`r{Ocb3^ zh?Kl*W_ofhi4h*&&H?_OUc2cxpKo)?uXLMN`0ux;k()^>y?&GX8P6r;K^Fx5{e zqhV2~>gjDvb*fpVrP~7fPpH`QB;Aq1wpt`jC=5=QNeh8)z8q*JHri$O=t*dPEu=e| zv}uMO|8={eWf0Qs_)xGHeD;+krktJ}3eKd%!;8P?%#Qr8!QGM2I(k8ZszP7>_bj3) z2@#dQQ&)QyDQI02QjNH+zloYb`FZ?u48D=%=feBB4_CH9G@4T=#<68At{ z%7b;VZ#g$HMYTnt=H-d`L)Br|nNlp9z0R|vs$twU7C}HSPiAqbHZ@2N0_O#A+PH6Ca z2W=wtB*4>z%1P#pAI8E}#sbM{+Z^AeJO$@Pr?r&kO#bZz7ia+DDux+!hMYO`vrJQA zbaeE}T3mLDf6;EXJ86zZY6cS~+q&BDlI{T7ZF^~MTYbq4|8lz=)TF&dp;{+79u)5( zRm=b5+se6Pvk2E3a)&7+yP-6f4=?{K4+dZ?d2GQimTB@V(V7!H<4TZ?%!qc8;j9#kI6=y z$D8+LLE`Do@7|#WPS}?mZvdxW+m{pwrnv@>tEUx~PpfBf8{Z*^($1pvE~PispvQ)T z9M2r9jlW#d@gT`16B>^UrD})8V;<>89gDRyv61@C=hhbQF#pjedt=2Eh-HIDCo6Y0afC4fG@PG?#vBi*f_ z2v_*Q_#$@WlE&iWwXEhej^7-4lJQlptmPe#+)mKtxd-Xanwc@J`-CDm^*cw>pIxyy zHNd1>mT&Qa5xMkvV{-uhko?EH53>F{e(oijeSBOoXXw1ElMCkVNAo%yTqm9-GN$w3 zIPU-r{)QYV4bYVGnG3Ajq~aY;_}ZZAv#8WYdg%BQ)qbQ`zT=GJJBiFuX2jzOGaq#| zQVoaghjeC4?QNhyPlFb6(W{>|u`WG9aCChR9!{tZ3fh4(aS2whd zCeIC2i(!V=;oXDR(;LU?A9Z!G(U^t<`o)85iWfpx94l7WDY+hTIcYF?qJ|yg8DCnv ze@~ps9U2M~iNQSl_75W?QR)P8V;0|0dWcj&PWS$CgEPBRZrg7&xz|^t1KtheBWZeE z<(b3UApb;60a5yF86jV?Z)ABXjeP7e1AaMwHrP#=dqm5*}Wde>pGqeE1p}3s_@kEe9Z2AP6C$j zY1wT_V&dJ_XbTjiKItL^n2!G6yziQz4b_zg)m^W@^Xry0jPM67K!a}-o~nWj&d#M9 znT>FKI$c=`bOxJ0)#Wu@Orr*^Vs55($#n#XsTTh^jIuu+{Cvft+n!R; z!NvH zzKOGWFum+1Px<9{H+Wj2hkN}bU(8zDOxyQ?W(U-l&IVLtE_RK@a0#UG7B;dvIVD1ekcJ8)#$K!Y)>$&q+mZ1Qd zx>bo>y<==^gJPKmZ%}*D!aYen)jA|*74jO;#TzJ zh;_x!2{D%2dO2pYhE?QQsc5d!IV(oRyuf4oAAh4oy~e&N=91vvY#TA0QY(m!kU0dTfaIZuloB=RUAH@SAqarX>$ zjGVsX-SS=lR`&^7bq_Vdi^V5as+xLdthnf~&F}4wozmwN@3FGh>t6(cay(J=Jxwde zdXWs5?6BG)D#EB}i@VD0^1 zd2s{jv;3+$Ay$F4S021?4dw%Hek>DMQ*!5*16{)`RO$N2p;WtM%yZ9wJ_vkR9{$g; z?_z~mdTXskQIQVZ~W+y-g`zbj@8m9yi z4+2pT1@{q#L^%^?j`?u4dByC*9Nk0ZiNtcIThgBi0`z(=CUG>{gt>c*({FhPybdwW9VummE?@ScC#IAX6( z2WCTiLmfk5lQO~ozFvCA^&>w+UL$Nr~c6}-Ao zP&snRo_lRj_W`{Ia*+$d5P{Z-tYzn4VzajM{H?_R6DkPhUUF>j7dKjhH9tK2Vc%jw zQpC$q;N(*ox>ZUR=d(3kz4WB*e?5i{Blp$XnDo@NCD1A1>DzwtOh125HJz2GatIEdLx1A3M^y6|94|C3yaL%3&#~1^ zMl_vUi8nShVk38w%Gt8W0OgUv)$zW0cIi{w!6`IhT$-g#%m~9)v{q*Hc$^3|Hj@I^eIxeU5W3xWCAM5yW{x@)FMCr zBFj`z=}qC~V}q=M-WY6a#}?6%(KI6^;r6(RTN|E&RCXb1VwI|2NW&R)EHT;v`A0WC zExOj0-^E`XBMK=^=z_rpTWj9+X1Z>uq^nG4eWCX1A*w6Um5D}HN&!j4{sHDBc;2;k z%cSd$w>cJkGq_ci1vc7Be+AcQ&wvy+QRx7BwGd>DY^Dln#no{uqxv zDY&n|@@z0-@1tEgrIwHkqC2|KHwt*mc!|5BnLW@6y+UWy-j4Id-F>7XVM+I-Wj=kx zY?GVM{6REfTCgS3XH3>&yW3)8zvkv%+^K2?*ZVU!oy%z7%iZEG)&LN3MvTCh-xMjC z<@QHh73mGDDFLg!xEgdZenzo8Eswg*dE5r?F_SgBx|z@njC7 zD{%aIuJ-Ep-0Lr%AJ6Ow;y*7jJ$}z0Y>{3=d#pY!X!3qJ8W`5RX1`IwO)5(un7VH? zr93?@14;8(nc|fZqR_*DB1K}o;@~hl8N0!5g?-cfforzh>ctts9I`Uy@tpQL<}Y;- zj#C`f*}3f%>m3*IB93{@9)o)7aYI}`b8%~o-qAe&oipiH!Mb7XS{{BP)A5tHJu?>e zfowA@-sOSJPZrCf0i~h*SenuA5KCKE4?rxBYt%gUY*H%qGfEnJk}jzsundzjej7ot zQ$hK0uI~XeN@iFgDK~2?avP8W;Jb_N%l)%KY3NJ|a`kXa8 z9v7a zpiVxtdQ6$K+L-<|;PULgYBr*}2bTq7fCrK{3pa=dXY5m>3ACj#q&f-~ryv{Q2aG+R z4Zp7;v(oc&kJ*q5%Si^F4Kh)%&Y6*C#m8YP^L(EIxfJ8kPt+PYpk_Q3eOX(_fGbJy zCjS_(WUVZr>SO8LM7+~hQTm2P#_NL_mu=hMsA>~qQ$f~~^w{+Gxy>}#gz7BZSXzwN zNcZxq)&%@JerjAwRTk*#%1pDgZKhqL7X60E)^^q=5m*_{lb+SG@KbWSs`P;t>6k&B zgkhR`=jxrKvk>)(*Sl4Y7CS^19fRxzbwXHt>u`7V0yhr_VL|JS*F@;}#7u`K-lFlt z;@C3pbTR17P@t-*fVIR128a4Xo|)&AQ7g}WaP9K2U;mlBDv#d^eYshyo`EQlgaqCc zA6-h1qtpuf>1x^`=0(brB#A5srlq4tPqa5E?=X75fPti!x2`nB_)(g6G+w_JEs0zq zirggCJ|~E%JeMqvIUwmn3O7UtVp|*&-yg>W3xUSbLqTRNk9#c9WNG zV}48TGyDXU5SJKe_C#Sbt^XH4jO8HzDD|BBUh=USXa)PmrMRXkqvs!hw$FCMD8^|Z z+0%X0R&h~9yShfOsnwv?^#}_N19G5oFcFwy5H`*^(^OD%+Sgwp2-?S8QghXNO!_YL z9chy^t2$-I;lilH{jfRMKb&Xh|-;qax)+_s;yZP8?Eo_fT*2nQr2$C8E za*CwIQpi>^WK$qd#whlv&eEEa%*Qjf_!1WyOkYTC9_rSu)B4TZGFA}DD@^tp+UsNI z`b>pmsClqGmP;COC+GX69pYX(mj_lXO`rl|*x!~_1GSeIZ9Bx0WU<^Cqib;z-;9r& zFigF|Qo9ue+A8Gncl`|>?$xc6zr8?lQRqb zF@`rwDOIExL1e(7@Qlua-lnrTEfj|Vw0L?F$EmM4L63(Qd!UXfX;QP02|RtxtPeG? zYB-8z9=GXgF1D6^2sh9tjQp%PIqB-$W>>jl;!1VCP|G>#1+nMx0T{eePH7Ffm%bI5 zb=bs$WOTgQ4VwF>{L)GCS%Oav-8@}0Ew?G>14~;Du^naGmNxaD%)j~F@ja>FZPiQV z-vdd1t_%JF*7x78&XCi+$4ERcGPvoA5EV|;vb*4!T$W4QWU;%efu89IlDd|o^;bvn zKwY%k>0qK9b^L8SN>VAzb+caTDc?K5PssyhXUMqddM%UU)H1_|+$q^_e7>1c=f4fO zDMNT5*k5ypLnYOLR1ftlZNC$^SD^>1h0A`d6H+0EpIOA?JTouTgI_K=jb+KyLL4q< zEdaSCOd2Xh#yL{zpV+??6!X1lZKy{H`M%ZZk)7EH=6fz^Am;=dzlj$$%e&1Vo4;m+ z+ii}_Pl@4=@x{x%fst1c0{i=XWtYxNdHw)jX0I?C>IRIB;!vAs^Sx*4Ol#E8`I>OR z&5+=1pY+m@P<=cPHtK~^KTk*r?=yP)?Yo>Oyd3$9+oHRM=aD3$0?X`rD}URT|HI# zx4`R&J-q#h%jScv-_k8>+m%S3Cco~Q3y$LioVg2mM#;pPNy1(mUe*nRHOd&$PfLC# z8aJZshoxCEs08H!R|Cvfr457^S$@6^$Qdw0XHp~qr2#y2?3g%m!|dp$TheHS+E*i6 zV*))b9*OR(2gmEHWqNfxEc!|LxvH>7URiP`bK`T%;XOpRBjkUCejL5b_f*}E6V=nRh$QF&kRm;z=U)HM@GA5Vp^S&dz4b&^7Q#m4sQmIDh z8Zd(NwUT?LLSh4(jBC#Q@<(5ME)Pm|me1UUUO($H$?r~$d0@t6@P`WM`lzhA+n;1$ zDeIl7`+Bdc=`>SbEqXujOB84X(1RgVq8gFZHHDVBWPek4!Vwdx)7Q+Ml7c#1c_!Y- z%I5zp2qS=^nX55MaY^1e#7e-D>I566CV>0`D^Q&q-|0l0?1WIKA0X`K=--Rp7Gr%! zAckZ+xGMk;$C$~22+wJ@B*c0TLW2Qky+)xM6l?=Nck=J5s%Db;vI3xrno#`R8sQOjB-ZGZ<_^RROn z-_wE7WI?*3cov&EG}mKeYsOYV`S?P;GOJIubm;Pm4r#oy#WWoD^N84}ECM^JFl0;t z<8?*Rr=BOL!NS(}*9ljnEOTCJRY8Z1Wu^*@ovQpaDy_p1QKzq2F~PIIj#!uRFVQnn zeDz)e^86(hadB2t*JXvobC2DKPjyUYdD8`Ekzm8UM5;q8RA94W>(Qrk+~76Hl**s> z1$nvDx>>7-$Y{V*zEzGILE01osh0Lsfk!(~`5^8T`p=CmBJbIEhj9;D?Q0MMgzVfD zGno%$f`&;yGX4Qd64DluEz-Ro=w2xEO6!b7AOxJ;?rxUP=sTP*;F^pX><=YTHsb7* zO0{juH+~aVGJ?JQ5_%$;H5I11rWjC0;7Q^~JD##Uqfq=3$`zIh znd1XcY`%KmP$u*I#J^^)gfB-DYd3mXa!2-a-n{|;xF5PYazmHRK1i9w+&K_%{UfDU zYw@qa;4*g}*lywzVd`8Gtoxk-Mfr%S`%SN$zIbhM&}s#fyxg9CqE+j>VyCnO5uZW1 zVJ~+dHICQPnq%;P#bMYnt33~zQwUn4WDHQF;$xx3d2G?t+BVi6)C1R^EZ?=~QdA+% zjf|4YcRZ=2_9pZ6O*N!yS)_Ve&6Xvcha_wL?BG?MTYh^ipcgsDYOGKCiP8OhEqOuz z-MKez&k4VGOxE20 zq3>~LHpH4geq6JA(;Y4^`Ty>3MoX8{*UQXcKVp`hcLIZfczM2)yn^-TX^Ux%e8XkH ziQJ9ybT3R(!JzjG4nM$~P5pDJA+&@Tk-Cj)i(yJL%)r5vifnUlgBk+7T7)!fqgnQ< zrTF5prf`LZnF8YeKfI-W4eR_{(@?@f`#?H!1SKfuLEh5j%xn6u=MOS5#;6ejb6GE1 zFzJ)t&zB!8k7*g;K3Gz%GdYyH6^$virR1HMCr1UvPew<$-np9FYK-W$y-Xukw@cuu z#TFRdU@muv6A9vHU>8x&(TfO(?hW?Yr?ZyDS@oh`QIF%C?Ml)<6DA5KjXK0=)N-$Y z>`^>t3Nl1hwo|+iz?QPPl!IQHnbAO6vdRya7$)`E-DRIzT@lcp42>ml5TWaczYRc9 z`;mWRn0zcV-!NH460H2_gmmbDW3zo5a&|%7tNiQNw^KnoJ3~Eqtk56s=L&`vv#7Wv zN`P>1UX91y;oYIdu5g`R;0!TNAk7c#3^i>i1?845B;qUow4{UMx4cD-?&dzBaNg7> zkQ8S5<^3%};M2d(K{&iqJm?3vfU&+cvokSRy7eE7PMshWhP8 z3BLFEbRpWvIA5HVhNoO43RH)knz7`_HcPqInmob(=DYQaKjUmEhEI-0KHeogVQ+Xn z8~64n^D9NOe}H`I*B4Uv;oT2)F+BeO+n%?0-hW*+{{g!8uZTb2ujl^*c#hFuuhGfG z-;Y_!`7TvFU2)bQ&5m94%zpWe;VE6b&|M*4=PSbjp{?FxH==3Rtcc$Kb>{d1&HLMC z$-n#mPp`r_HS2+oZ+|Q6MbU3nVpO_VVEa$?idnBiP)cu-bxKcu8yq03mQ=Xar2(f? z#@mA%s^~C?qm21*1A!V!Oo|Y+B?Se=GQqEa&)E@<{tj!#_!YD|OfeHSJuYqI5A?bI z1ecx<3@gxyE_L`Z2YYEkQDvoj>{B&>v(*)Vn2UVCoj7WM#n^F=p6COY_BKA4EL4wo zza2ToHqa@&(_b>|I0-)L`nCy3gBPrVJbzNBxMBm?J`2F#MX&Pxu0JS(ggO#T7k4)2J{YBN!L(`V~LF%q@?mMzuOV%XGJ?CSs=) z?|X)J$Z&=%PMZ&yFe?06@2?OOkrn|PV?y9m-R0EwuGfjjJvSonl_#;RIst$b4jC9F7tpJoJi)3YF{MsrJ=Z{L3}LIkcs3wez%rvsp5YDW{b>_E?u|JwIEU;6B|e zCi%5&-o0q@r5+9c!hPAzF*t?f(u>e9`jd9q&tICs0_okO@01zJ%omz}-y)TB!tLJQ ztMbMD126II?>kz_YcCpzy8!h?t9})-MkmREG4~=(2%9^ zGcy8}tSF{e%hZnX3#Hkk6g9=?yi$;E#f-^p#fu?jhwp#?1N{GKi8U$vKBTfUCro!U5(%=9HLMIdp zfmKXk88XNqPOO`9NL3I6rjLO{C<8|&Ekk262%>1dy~Pg-Q5#Uqse8G5zWn7Tx4Zp; zj~h(#iOywi8bi?OIo#TRbq4Nm;xPEabFcWcB~8foq=72tBY0KFbBRuUqzsf zd$zdl3vFFR3J4)Kh_fvUJ0|6Ut9!qHs2{3PWgXw~$lXBx^65IB*OoS^&lfymZmHL3 z%jE#Y{LDuLav|mPpKCHGe5!6<@4nY8(OcU_Zt1Nx5nGbJyE_ax9?&}v&5yO8sIJ8) zCUE%6e)0r@R?wqn*$Kx7-VsC^=B8;HYU$%rh_)};(J_Y2R)^+~P%Baq6nF>vV2MPI zEvwXfbr?QCo2Kk6WF2#wt*h}|b&R%!@+aqk>1HS%r0nHWgS)%+FqGhJRR_8x&odDE?chLZ~yO^H=;9IcjijmZ2ssFxL)B%H)z_$zpXH2`n(;btsm=uCM zy(Ko;HZ9I7EUgl|S}j~PkGP^K8aooJe}75*8#n}C8h_9RouM#n%vv@5d1BkL6`L% zv1U20d5r>SLHNr;{{AUQn;hhPK?(qr!p=XD6LID4U`aO8e^$M6dw1_{qf1_({ZlI? z=gsF=H($LMA>to&ANfW8{QMPHR-)bUncPl)xaWM-KLGt8^J5lVeg63xtaPbzOv`&J z)*%A2r7!9jaz4k0XA|iidh(@M6sX28$1^Y1^OfR_#J4K}qo20!X(r_E)fq@uZA#WT zyu%nF@M3yH>f%%4;#6-1NwSu<&~ zef?$?q8}~tzTw(bOd#lJZAUcrFKXm zxc*=Orv@Z;I?_oDVj-pC82BTdoTpd%Sek4QV| zfd{aMne^CW8y^fP%rgJzP`GWU&k2rC+yvm6r_3&-P4IL4|Y>Ho$ta!*eymy2jk$R=vGE_rpR7KWho~F)WCl(I_~U z5O8^=|7=f`_06a*M~{t?827NnI4N+0_6BDXbJV=kr|3|{FsTD_pyR@Y$J4)S+d^w^ z^0ZSiM3Iu~K_s4jsV>)k1FMXx?c|R+ZoRn3r0!C<%A}$vMhV}JbNEWKaqIo%6gjzn znW_6LVZ8Exb~Zk#|0H%M==FcIS&H-XQz`n}&kN^3y(4|N2@Y+;L<)=fW|&s{sDnh1@Tqh&%nD22uNrykVV$R-NCZPItS4I zbk$kvvcjDBhIp1TRX4K9xZJ^xbDxQq_0vrT4|A8TZ?*_wx14k>s8lxAx(*v9pyIba za^+z|>XPlvZ1{pc^|VPmTbGnc%A2+HX(ne)9F_&5Tq;`|GR0Yiup7DLM)BiHz~f50 z>sg1=^(wmKv%9`=^l%G%9u*+B7zS$#FPA0jjVwdYoUZP!9-P6516Rm=h0+)y9V`U z5{M7KRZhvb_=;i<`=Dw__;y-yfnJbzo$e=R&$#W~lCg`(ibbXEK9p75gP2ye`G4tdg?Kb^GS2RIEYxWyL@B;AGRis5`LS=L25f9-mp@0%WR8^M zI@OY>@OO#0|z89-XQ_jIH*C#<|9t^#|AT=0YjE75_5* zjK3(Sb!~eUa$R8N926o;hM5A(k&Vd_9z0!Uaf=`6H32{^5aD!Gni2Zq+acG@_G4rSA)3 zes0d^0ZXTOsNtO}f(HW(Vp|G3qcX=dIugW4`dftd4mTEjpaZX#Tot#2hg~!hTF_JH@l< zgHD}7;p-F1oSP(~+@un7SNt#uzuNPPTv3{J3EPQzN(jYqu5fEmY#**VPBk?SfS%>> zuea2r^jwStu3=+o56OP{ewqePP0I^VZJ8UH27JU=h1d;=j|D#8(|?!nBALUL+MV!J zXX&|{y93YeU^jo~Qx4#%Re&GH!z;8-U~iEH_mgI*cUXV!^NJS(jy6Ay{)f!kcB#v} z`yp$4uo`BA&cxUN-9_{WSA>g=C$?1uJCmx)3OCj|XV4rlE_HLMn-bj_@a3S_Slmtg zDYW&KB z&~<%#ipj48lXuGO&=&}D$}*a&O@`J=5i?o$xG16<)!@~qrZ?9kV#(mTR2{E~)Tf@y z!UZHeS3ZA4ExHaEk?`f<+i9D;hYrSR0y|2ee%~qR0{uIrJWYE+*?w9g!;iQKnF0WD z33#V-*Kw3h`#!4^0qdFH?7j8BTpw>}#8jq7@HNHf%u>-HxJBV+#FjcKd5+qE#1qhJ?8^=8p0rwC6rK~ zWQ=I7bGOp!PC{JQkQ}(NUL*J`;$89#4>O<^9bwHJlf2wW^Bo!fhVy< zgJa3UaVl8=>?gQp#pQm_KA=x1ZIfGue;t0v3uTv~2PkV_g_5&8O@bBWc6XJi?^pM@ zoXMqkPx9?=xYVRjmB*!~Lu)}1Ss2_Ecja)KHVk%HJLS08Bbv?kY-nz0BV^Xpse!b8 zdvT0;Eictq!x&BLj%}q3!z1FL2W;zES20J*rOGEXN0_zo$NAJM0SkSqlBC^F7Sfd) zpUU7Pj-%G+*1LTX)~UMSlEhxm5tt7p#j+12DX#K1C4h42USXthvGb#t$X(t4(5-D! zl!hPR0JUHeL((u`5!mK~hh*R5DM_TAIH3XIH%+fm;|-dA@j^e(6}gGMsORKsTUtiA zGL)Y)J8%9j246k=Nu-rX!XdHmhmX1{dr|tE;`stI#9EmUSQKi?(}jyb_(9qy2iNDz zp0(uoQJ>84Wnbj|YxKZ{Zt|vpKk0L%_>tFkT^gGCq^22Zoij#3K}osCk$+q5P|tr{ z*!IZK>lt%LqJW z{jywZCn5ZlOOZovF%E%^wa!vN()MM!ZMzDyLYbbO8pzEKZidz8ay_j7_E%NjR#=8(R-6HsZ|JkW)-J7WVyU6gdq~BI-G) z|2pYC%~D>GrS(EOc)2K#$PxmmH*FopS{Uwd$~)WRd4xaOx%I*k(4sNDz^MlIE}>eA`D&uTgJnVtUb6q|ish-qk3yXe+;&F=Q5|6wI!*;3jD|LR$cpToZy~kcvWv=Xn0m%RDmBI0%(W{TUK&rN z`q}xmTJfE)X=xRaAALAByWo6$x4}i6Kxkdr=8|c!!7LCDw{T@hNCd@CoCjdjOO+O* z`2N#bJF;!l9oYA3Y+ir0Mzo{eL9RV9-fnI|!@%>}s9RLhkssruegreccmr~xp|4(3 zdZOq~IUkvwwHpmD*=KZ#<)#H-TZ_9E)wh%EsHo`?_}E{0PVN%U^Qu)E zSI=$BC*|6HFCS{RvQ&S-brx`1(3wt(!xW=2$m-AxUaQptSi;7QnPJRU-$ za{&=`Z>bFn)kO~CQ`93Gxe2W6&2nT?Yd34Pin^k55c2Q6G8CbRPWwv&QUeOjX@55= z?P!YS{(+hQcx|*=kLY%Eoxh zLvc%s$->4!B_p$y5X(xFmf-3PN-Kd4;QrCUW;Nk0FBRz`^3W?!O}iWtr9@y|&e1D1 zx0HDn$M5BzCy39)Y?nS{3}|I=SD*5 zuj*~1a7UB-dWD`knk=nTbxd$hL^%+RcIMHhAahEr!WZ<&D9!UNEQM21sCLjSyEiU9$ zXFvL7`&X@ce9)W`R|*9LmFbZUhG~=_O2!i^O`Z5Wi`slCf`5ovr(SWPMvc`ws{-P7 zyrO!n35=m=0wbDbUu;4^GQB3>L3V64YH0a1B(i@_u`*_T@6B7|d%wm-b(+IW+n9pT zLQa>X0yqJZ)FLp0|HlbQFttm3`?#jz70!t;*KFI>L?glJ57{vxq+pCEVe1co7B|OS zj=P9=pC_$@e#E4p$UY(}Z3}@OP!%&|U{^mP=rLexOUI*1fs++iMeq`f>1Nq3Nr!5V zTC`pK)aX_;&=9&{=*Nytr0T^#4IEa>RH5a-vOww6(H_@4koF?*@2LrM_WsL9r?bt3 zlM{J_pOqoA>ICqZ1*!7Nb5T-a+Zt-u)bL9Q^Wec^D9%M5M5=|2b`1AP**}z7_&YcA zkr_(}_&lOnbUnQ6-HZD!QD{3w#M!UxQmxL8PjO@a*v$sdq@1MAhpVmerDcwIMi%mP zyd57=V@T{xtW5SJRpe=9f%PfloyLFod=8b>w2eG^&jrS6uEzAYMWDz`?lwzUQ3-c0#0Ptuj ziNW54fN)E8t0})dy_SfnbF6J!Ge7xI6^KCUV|nPoBrnPNZxLsn?F3yA`fY&lPSi&8 zz%ErbZ5w>`x5^9l)p~>6_33SktwPEQ!YRhZg*}#?P`MAeRC2*dN9#0ru{`P(Si;vz z&dec;f?|`gsSl=NPZsc%F&&g)q``j55a}p^f>DRhB%nVPg>w5~b|FD=mqRIp9z(P^ z8n`G^lGIJwAgO7t2@66leKJ-jtz!Ce%55%%d{VWE3Hd%l$7HX%SC1#OuhPX&j5mL$ zQ-0uNvWscsV4Q84m2juSvjA5j)vYstq?N2CY-Za}+ZDKT(N!x;j~R&CF;SP0wA zaUyB)7$dETC&2K8)Da945kjDNnmd{%p<}`!^-|q1p@fHF@Tri><6$D2^648YC(hF1 z)aC6-^FwfoL~Ph}E{j~l=2}(0fc9M-lS_v3Q$}{jO2EfH6a6srmi%Yc$sNr35woNb zpUI@rRWr}hl2bgJ4n@I#(gTBCf$-Pz(lx)`_6gBmedY@R2}r@L>MU2)*g88`T5L3_u0FfU7KeKibs&VEM-|9G@03wkYG^g10Y`^Ng5xA}WCJ=5p1KJwQfEDq z7D#o`f%4Jt3WJo6Ny4^%Nux~L2tCZ9?8Wp0j-iAx42q+hMRV4bnet|G?OsrGBPVdo z3Vx)OSwUnA-_D2RC3rM{)OM?}B(@E9?9~m1Lek8|>@{$cyDa+It~)L5>bItjG)+Hm zK|5A8H8>BUl=EAE+(l;;&termG%r6P5m9DyGIiqR-0qF+&VMV>CW3Y|C}6m8t-z!)$#MkbOq0G z^k2<^wq7)t(7(-S;S(EH;xQ zZXzrY_SRo#b+}UvFRgf;Iy749iCcu=QGCu-*31>Ufe|`HPc<>dXD@&uAI$3IgKb=$ z^B;ue34e7YeA-J&^=B^SlQy6H!GU;?SkL+UpPqJG!Q_c_yx=SR_tbiRD=IsL=n-fe3gcP-G1f3I~)6J9C_aeYz#dHdQy>Qna6KH$k~x#!Ewho873~ZA$o5 z6~()zapWkDBS;tEDA9ArO{ZT#ljg@#+K`aDU9|~C8K{E~PJod#xRF>=8Btg)K41a| zx(CYEL`4}v)(4IiDD-KUay}_;3!%&lR?;*ht%D;EEfjfE#8$V`G2@-_f0(>e#zA!l z!|9i4=4Msd4dUgtNV#;Q%5N8WKr^{`lsF=M8d!bIvuP7b;27$u)u;NQMPFjce!^en zDr7It*v_S?=S}j<)M87)bR7eFHPWq`9axaT6oc&!UumUYvE|PXHBcTAD@la8oU(CR za^P;=$x`Yn-VW4F_F)VLP6pL7e;16ilNORy=mq;o6!`SICbiEsH=ETl;MJd^9++er z9#^jkp)NiC_T@Im?d_#2$7?Ri?K21>tXRg@8dXH{pyGkV{V@!Tcsm+u&5P~F*@kpN zpO?@f^xWpPS{KCr;pJW!y+>_>MCq{OfuFv*W{J|7*-0kuu(&cw7tFY^F*ly5rB5+- z!!qa;ywSQcqGwhrlZzs~x33$Ms4E_U)S@zYT<7`XRg z?7UDSFg4d=$#bZ7c9d(FeeV<0-yF8b9HHUSER_(G?hBe-mT`NXl?ck)~>5S=x@zxngpWF_I1B`R41Bo;&@yoiKaN`ewrXR-JieBemIE@sBOM)!QK4a3I z6K1xUeC{*?ZH>wap$ILF-tf9^6bAy1uAadK1L$CYPn|SEwCP*1UR6&~U#P~KQNurWdZe6~X9ggu>|e~`DG zV5T+LvMp-UNW~TxNJLvJx!sy_SwS_?SDGq%xKljB8KG_fxDVOFP1;+;$CvZt7tQ#h zkzN+Z)vJ!@X`_l;HdPPD&Xs5>;sEgX9+-^g2{d63;^u3Y$H|KOho;ZROXUfYGu>XZ z#{OVc&~LvF;+zlokLKu9KZxm!FN74nS0j=>8Cgk0G8NBOAbLHRtVi&EoS`Es^~JO>0My(>En z@tqjkoUwca9wqq;qc;k^1;7Jbzg;xUkQ`D8Zhw>u=N$V~?9S(|t5_NZ85G;rmO7S? z*u)v1>Uf(B4Rp%ux}Ht^UT z9%f!yGlVU_dq{;o#2FrbAsYiRder>G8RqbADZlnKc-e%+S1`qIwDapctED!au-JgI z@=4~Cg_rVnz{A!69$X7I*t@nEN_HAe0Ipy30Bm<>;6=`L-GdYzpRDwn=*9|8US3TV zru5Z?ISq@N`4KW$`FZc~^n=i@EWc-ftg=#Mx)m-LvG(233U`9SNd_wih~$mnx;X!& z&@2h`v2vdbWPIl^HXQckAVuMvsc2Lv@19s{-7_X2*8xA^5m| z_2%zWs~=iVApZad9c=Lb?moZS8T9op?zn`!tzB1zKdeRlw>hu5uJ}uX{sGFy51-s; zy*n;=rTdUta#e`?@9twM%`xV{aD3!$pH?M>RVT~?aDI*W?DifBQTfeo!p&PV$cRBL zeE56d-05|8j-N)C2QHseFSb@(?A=e|D>kKI(>p*#D-|CSU7(gC6_aCh#TVAOCj#eh z<{-&Gw_h1=Jt@#-``UHi+VNTn^W>xFt%K`dPvq-?Jq^OA8T+afsG6DeFQVB*QZ?sZ z5Ke6C-_|I*NJ0Xsa3?OMLVXfhUF0xMsSYY|BXNOxfFCb^)pdiiE<#@`Yz;3nu}f{F z!AFc|!6V$62VVrigF{yEzj}OYb7fml>WI#w3QRNZ5pVj-b>!JjQ;|~7Ttnp5Tioqo zjkbjY4*_)fz4}s(^ZcFNm{ti%GSe1M5vL}JMEI-`Kd5=9ZmFmmK~x$d0kWc;7dziG z>9lm4UVKVAME7zSucsn`~Kr?>_^_?=Jp3 zgHgV+(lK+`nlJXqpLF{fqAntmHd8}9)tH9n|IGTwA$0+vp|ONcqn1dJ)uLrjY;4lv z`(B7L>gU7b@Ff1C<>_(7^Rvl64gRI8DAC@bisLmrE93Nh5t~YwoV0E1P|K@d-8Na$ z=5@I+IAG8cixqsmIMLG}oYN|q%%s7X3%B_w;aE52wpoW+j@pZKw{%WTt|~ytJR}11 z@OE2VN0MYFeC#iEHvEp}zS`QB7eq|>A0$7Cf_efU3T1E20(!h)y6!RC$_&Wf*7uiW z8Mb%P?_~$Rj$Gc!V%`unygO+%_e=i3Dq<2}r5Eeuq(^L%6v{7MFYme|{8zNfE9LDN z$H;zdV#7yS2wuWfuPT{q`VzFUl-3QmG+xrSFRun17F!G){}Pax zW?D-bZ*I22wlS!uF~->#d9*X5G?8UTpC+Y%W*$bZy=X=LHa5TAW#wl}8ffaht4sS0 zG5me?+W7;5`)<9PHim}rZIVwfZ+!+;9Pas!goqydF^Dl^P=+vuB>Mg9UZXMbNmjLh z>l(l3U9#%_TqoJFLX{AuWGAhnXmXDL!gvGazKv2vy*0vVypC7)Qgmvc4DfY?fX@QO zSuk5w!3D4I}VUxPzp5Y=j7;3AlQ}CU$(I+hZ`&FMFluu zjre4)9YBs{5g82tgU&X=`mvc5 zG|K&xEFBz!%`8iT^Dgg7lqwD;7ZjO3A$Gu$#r!|;upi7^Loc(^4NB$9-r`i4L!VV`-(lxwaJdd@UJK%rl$ zD@dqfQM@Z3t&dFu14cfmPNTrbmJG4<9UN59I7JR#Y1=xz^(O_!!unF`*;$=+=>gvm z*7-f{Q1r2NZ2BB&P?3#KO()_#ay-^wkGC{cN2^naR*$KnSLm0bsP9c+af=DPI%nG! zQf5%j?h)m{3Tr{V1>|rup24npyuORV7e_ZOO;vM4kBYhar(X8Jwyu|1<(-^X}7jASRm&;U{kV1`b*-FlCxG* z269-o!l&w)So7>r!mRfv9N*FG*w{FOqlhAIL-ueoL>+fH_5ytk8BsrHXKr10!0dA$ z5~2nxNGQS*2M|MY&Zjm4AD(OvxM2tu94OTFS6GyTH*6b%T)%G0rb3WR0HflD{bQw5 z8vr@7dTqC)%&tD*b~sII0Rd(IPBrKDR7~+;yJk3*CZM7CMkrtH)v9P0VMF}*TLS#c(dLaPN>ZMavj;WvD8yGd)MJ4pIj7!5pSEsiF(7e^eY)C0e=(DwJVA5HyJ56BLo`gC z0w=l@GtXOCNncvVf)!gQA>em)vH7Y${Q*;PY5jX#%Gh24OoaQTz3XSWF$XRSrT&UX z>f&R8DD`2^{)$-!oJzfnv6!Q@|S)IcB?A>L&eP02(cu(BWh(X^U1j1 zCFlej4Si&?Tb=Q#=G6l)l|rw#m7$kUc5;X`4L6CO5Kw!FYohTDC^gADGb9>|>Jz=` z1HY4?E(`qN8L8*9er~HUw2Mo4rrwv&?m7lUBY4WP08yWp${+5AbmwtLksTRl4&#rF zW(|iyvj&r^#OFc%&e7(-5e#uG#%!t;@6`|SVr?zTs{terk-kk4qJ2?u_l+GbhU*40 zq0zHQQv1D6`j?LMOzzh&6FRI%PQA=tA6Co-B+nCw|8kDk=MLSZ<;?ds*+tHIo8FO zTw`CsGP74V4ww09h5_y!2?%6Kw>FJl?oOs;#2Fov;_TPBw;pp|4z1@$Sdrj->WK z0Dh|emp$k@Ru?Gk_a_nmXQr^08}rFX@~4P{wh{F^m61=~)m+@1G)3CwZ# z007qMX<~}S+CjBm_o4eek&ERR>)Q?ZIfGmp2Ocm}j~JBaAVoij&5l#qfe8_4xc`<+ zlRW<1$o$W$MhLL>PvDdG(YA-xV7PaByBw1_*S*^qLml%=WT`-|5S(wW*i48ovn8HJ z^j8xFjffs_Mkkl^npev}Y0zj!8achnH+9mJMDVp}o<}z+8sV!e_8>;5!>lrCS{|0* zh8vBPl^Pb6q`k$~|7%H9QPAIDd^Vrpe7;}zw}HoYm&=Na=9ML>p)g5=+edt+*W?Ks zydmj1uk}Z0!JB1peqJjkQSZVc56>9a_*<^RGS*ba^gel`b2B1IENV^ET2c*biD_pP zyh$pcfqk`mm~oD;=!RQLqLT{1m=WH^Qx#SMhlfJ`(#GR!b{dv{O{J`ZYC>5hl8%-) z4M#Wob@BA0!d|bty*L^RbqxFSA!@ei zF@ugV8z=DDz;lcVAFZK%fALl6ygQGI#zqc$vV`zjJOjn*L~Y;%pR#$=^t7$wo%lzr zi??|^i|2Qr(cXWoE=?utOz+oRg>hEW zS-=Jzz6+JazQy9Wx@5_!Xg)?9NsWmdAf|$0ot1A3W0See>^iK|G6EWEuekE;wJCE| zx>vxE3GgZQ64ToR===0Z?_7@a;wwDrxBjwJ>T3ees8kQJ37Mmf3<$7sdL4Pp#rLRQ z480^Ds`f?1_+7G5e^sbcjr5QG-c5Sr{o~{0x?7Rv=c_xh_Z68RizxS+f1RB@dfPMk zxHR*1Bkzr1=jnH&&U6X|ob4@5_VW?vB8a^m@qSRdlIPf8EZt`L9Y&3#5fVxCDi715rQW~bQdGsJ!_ zorKz9O0BHc%TpmnDEJ<$XY)+W%{J3BsO)X$Aq3Cu1=BRIoqH-h_ad4?QB-6YZ26{D zp>}?jSE79Z2?wM}tk$egdN@Cr`)^2HXDABky!ursyxTV5am>;u$c|i!(;8|y?(q1P z%UEFVDD9(XUiXX@y4nsW7kY@b;;vm(dsJ zryaYMx+&|#6Q39TLDa8vtA{tI=&n|Q19O2pQlhF;!U-wn;;VejGTiIJ<_#YD}|C@quqTS2NdOR@S=*6QQ{Vd#MU|!#UghO6}+Z=mydoz#6 zJoTb9hClHYr_Ns_>qod(cRI@T=o5kJF5eZws7a969wy^Snxx;XPY zzQes}zuLe^lXj78svdpLa&8iGrH=l$27IJo36FN;%S56MlWw@tS^-_ASuoGcw^fuI z^BgyPi)B-UkK#;{kG)%?ZQCc`xd>ylKSwk>&ZwV*U)qX=_m> zKqW%HvmyMIbjgdDeO)>jr)oOXuufZlt3#9H&uo40k!bLAbx@FHyLOr21mHIXq0i7`TxP( zTgSxNMti#h3|gSY-QC^YVHhY3%-|Fl+}%oBytum+m%-gz+}*v!ix((XpzlZWz28pu z&eZPnN0K|(vpDJAe|NjG^i^Q;o;1Um+h=&d&U+6v!9wn8Eoa+~WU zqTSxr2+Cei3Gu6wjl1*9>9A)+-zm8%Q!sDK zY0|FYNaSPCX0fggn8ZHo0z2?a8p~>@sNNp_cp_9R$9ec##<192?>5a3$IdWlFV*f- zlAm5i;%EPqim{oAG#H(A$;^*3LF{_Q)0VNt?G397%pF_SRa-2phP`0#tkDhr?6A6y zYC&JTlc01p(@T2Rd`7+)4z&KW@g~kM@MAP8qf&TE%aG*o%2YQTVVI$+QN#zzlmD}p zE4V|q;KS8{h4(ZM;U`o`VU)$DTd)KseP(#{^kyG{ZoBKTzNTCY1FeWQUlrb?Qpm$g2*Rby;8qQedg z^L!7u5N&BYz~~o^(VV?EypMLj&1rlV*>BOk{O0a#Vmo6_h$EyuhxP1AvCh=S&<+Y& zz&^IG{MMQXcrezN}gHlrqj}@@y@GYbKlp>2Gqx(7b zl%4NaX~b7~y#y3C4kC|gQk_f<5!rOf3t%mTNTaPIs&p60^a3uQS$62tRL*OzTdnT^ z!vden2a`puu$~(_n_ya(=oZe-g()SDSHS47ku9T*>@dYlyCG#)3z}Tsq14P{c%yP+ z*@>i#8w5f%FXQh@<17~G?=7P(!Da-dnSn>gj%SHSYFZX{EAk&_^%$Xr-{AEtF8B-X z1WV9yIuaiIExNjzkEb(Ao!4LNQpHp$bOf8(lPQ%s7Flm3Bu@@WKlAJ_6rYj^V}be? zvl*hX-eJm8lys}99O{DMXL4B^si7Ri733R>(#q~s*$?E+VcDewy!cowML%1s^Gc)g zSrO=LxSo++fjVcbq$trbs1}wEEovQ2Phj9Z86<{tA_h{;z$AP2{HuEto@g@q(Ax^R z4Rk|^JM)z)rJZChQx#Ai7)((NRo1sc+sy9d?0hvL@>Ry&OEr6ceT<|lUnf3?Sv;Tj z;e0Gt*g#^HcGoTiw8_0P`veW1x8!8h0#7Gd8`vpQlyyTB%&|6o&{*-_&`m%t7rY?L znCxerluYn15nt)TufEdNe1+N`a#|tI&95TZ%cbp|6+(5LA0VPiI;0qp30g&=)ZdZ| zR{IWpdz*j+R%&(2UDVaC?Ai_1u3l9Tsr?5GwmTnLj6xkiz#Wjv4fyyl%q2Z(63$g1#*$U((^GEG+uzjRY%Z)wJ2agxd$T5W$xx z-Aa8-GTBXj5tN01jj&i0J&|DBZe)f{=gG5)!h-LQMFrlG zt+pKkW{UEy#+>8Qm>0IQ zi>YpEXmL!4IpW{BXq7dnDN~RVUJ{j1ogs$w$s6Pc_BP?4OTwN_@5;q+dteQ8p zG;xQmEGZtZkR-Wa0$5}eT4YUXwQpUJ3F9sTs;#cy=g%iVyCh0ERK6-z zM(Ik5O(2e{B$v6BteV-tP%K*UY??K0kWBO3RZwo+LDzo%C)CGf$+)mjf<k>n?iGY3DY>F7fUAbHpuqg)x57 z^TRGW<*m)*+W7^#GHgmx>ksp@?ckei3d382M8qcmR2rk&iNT{eqiR*CqPFzOnXTM! zv`{W6KeI*2_$r*&m8%a9gYp$z==s6f(yE_d^aB+gY=P+aJ)%!Bh)*IGG8>lE!&hla|dkXsGJuM9St)1C=M$)~cB;9zO` zvNS@-WC@Pp_U6ltdC#F97^-u{SK3{Y9=0vCL2rvx7m}$W>Rh_s?UiAOC zwG0FMm&uj*JIRmAP?_v{nseX(o1f4_+H_n2)_zHH)+!=JnNi8g%2D^?z92J->9Bxw z7yw8@2@Vz{MFIej0HB=DDWM$&yUpbj;0>~Qmu9`ib^f&xNEL`#1;v7VPRM?d7~vfw z@D^D{*Sq6RBp=S^Ik~)p!yi;iRt)|B|tlS zZIQ^R60^MBpwB1#aO-;~8DR`&#%IwCY^Ur`enbNT=|_U`;jt+ORgPJ8Q#7I}Uj%uH z)QI=Q!`PKrDX{>wQu%ai$TX-9k1FZEO{KAxZ{vA>b_EdCo>9M>^}XkKwrQILZpKP!GMi2KI{+-=_CW#Mjel8mS!}I_0;}NQ^LKSu6>O(^z$(Cd`OwK%c ziRIi}6C3&Y1Ru|W%~0%03u?ObN|^``W!yuWa;ghJ9Jw!ykA3|gvVaZuVl?5PeZ1$x z^eZK*Rrr~!>#wQ;#xO=bL3pQBgLFB+E#qDpc&vqCw3VFHb9$tj zIjTS3t{`m+Pjt2BiCfVFN!2R}VtwcgqQ{*JJj3nT{auvz51{FV4e)F#0}{Jyzay*P zj>`|}qEF=k-G9C&?kxWeMPFr{~+_58zT6K zJ}MXPCb)eo#u!ADtXk!{NZZIZFQ!oRWR#~>ae(`!Bf;FZRrhS=VA0t@ZA^$%JZG&E z+qf4$uwJ=l$WXAl82()_{$tQ+y`?G?i^X=RB+D($#{PFa)cuic@W8gk>*kHuC`eep zJ*h;;wQ!gxPk~Qq%t+P;p<}E4^MnP)FD*Fe6B9dk*`PEPZ!e>za|iBp=W5Z&WJDl( zVTZ?;g$=6oy@b@@0a`2q|6)39Zk(4;%$_lq=Cl~3g3M#6TgaGGPj%y)Q&?TYrFgK( zWyyz0WqNt5mgu2@6({YBIBijf&0v1bteVT6bG9?#=6)xq~ppDDCF@{~p|Hb5(*C=!_SzptR{$%Yig zJDM+ERt|)YGQM0T;{q*4O(on`JKu`)OD1m~t6N(A)7INT{k4NT)~*qfV`H@(`YD*? zZ~LmrkD^vYjtD%pw{LmHj{$&`Kw3%otFu@fSqPuNZN6zqi!mlbaX1 z7~~wWYF~$;Yb=O^5cuMj?M8s(ir~^}w6(|AwkV5UmV06P2?HE#&N4U+1mZ})Rb5uc>&i;4$P}ERdfoN2JSob;fhwM58_fGyPLhOOha!NNcy2@n^b(5yPp>|PgGSUUd(O#OHaZa#nlS0Q>!A-nzGcj>fKMuY+}VQtwQe@dxJ7EYwuds8$F)-98>FPn|Ipi#wkTs(V6T} z5iCykhdlv8bM3kIKwVj&v#^#hl0`g=WWpqs*LA&EB(6VY7z)hMdbXk zmYjnzm=jNKZ$chWAcBy8)AwV6-8fFEZ{hShl|3w}J{~O(;TWYD0mypdrF!kGvIq}#2ZmnAiVb!V< z9(}aE}=MHv0X_=^XKuFqUiMe9|PSWL|DO^BxNGvhc zJOMG2h#wm3Sx+%qVVIe$fi&|t6&1-^%3Qy4^^vgubw`jN?Koim>i5kK`D}VvXk`BU z2h`(ce+yxzCH(RzKs6|{%M(x9@93_*>;pb za!jtN`(~b3a4GzDd?j80n!&gY_aD?No;!D37SKU>Vq~YCF0V9%%k3xwmTQbzLew;R zd_6>0>#5~>Zzr+?%{)FbMR)C%C-HVD8uKyrVQrm-dAsdgQ1@0X;a!i!Vp#~Y(zKV& zrtY#GbiK>@HLdxYn>&+X-Wl0E%=Z2!&yX`lV>{M5!%$Pq^}z}1Ab6=n7o}6<6%mxG zr7J$DLURcIl(S<+1s2yd{A@CQ)7M|Gal6vQiNn8d-Bc&#ni!^2Lak!UQabAn$3UlI ze#N=0JG{zM>WFDMNWAgZ3t`oKSd+v@e7D4&z2N~bS!OypPSZd)OX`*2BgRR^!DgYo zz*c`$IB##_yZ+O0FF|L8o2^r@7a36a$oxZ})HbxTEzh2t$lsz)KwYj0+Snc~X@54S z?FuclVYd>ba}p6a=P z%&*QIlcSzi|1%_XaEzVZgY?+o+G%bpPN((jNNCf@W&l#GQ1`aJnqY6}a%CcyK@p`& zgs|fCN-P0k;2LRm&)V)*d*ugN-7WaIi0%pt$7=mLLfOG4jW5?7zxS1ZmyeTeiP7S+ znz9eN6`RAY7z-{yo6smjvjFm3eOK{s=^)x7e*Fdu7=OhtszY#0sa zPPlwBi;BLsnzc_NcXajCeM9@ZD)+sp=i>Zdt)ubR3$8g&G!PTY#p?)lrg+9Yu?kDc zx2g1(FqI5@tL*ZPcZxC)Ax7$ybMk9!#CS!*mB!K<$vSjuQ$#|%)`=8kNk5m7K-(rF%PEYtB_}KkY2V6yn=#{&< ztS`dQiv`#&InZ4QoGLP#KeVG@WE{T%X$<6B#3Vv$;h2vonaVL`^ySS_kC==E;3*P! z&+9Lkx=PPl(mQfxI%gLq(YDrLQ)V0q{utv1 z{m~kzo}me<4&iUKW27ia2)!B?pIMb9`>9h$HJ>3Orn=yXFcL;fcdSiAh^)kvjR>yl zQ`JGj>G`2{h{o$ayI(3T!?d*yAIRQwd^rVDul}%pfoyd8ysaGeqgTpAWIgQ}i}*UN zML3o#41;UW7uIw7?na;;$P4Eau^zb8xBYjU((pXAvz&Rq>95@vID>C8lKv|tNr2IV?tNJL zKNtd4y6?Y8Zk+o_{CI2^w!2qeZlsfKYm@ZBj4i);U$qd!C41Fk2du`c&TEMaE(b;_ z>5o$NBwD2=s)o_|g|DGBaoP78<+cucMlDx+I~1Q;)?dZIL0NXujP_NQRH-&&;yN8I z&T8C-!N_jd&Y!%u5&=~u;fqUCRA~9n$+0*6c9;|aZIRVoAN=j;4eAk|GBC5 zeE45+v^!TRdb;;UxIIRUCsjNvHst{t$yc`w6N}cEqWW9)&?CXlY@vyT<6LCs{Z64< z&VmHr#6Y2wbj%-fIb!&xBG47JLXqQawsV|ITxgN+R{ba&*?>=}m0;68)5-6oI7X@aCaUy~a^=Wt)c;RO zvfK(|o#up6h?Rl@=7>Z;{@KDzhnJ6+D42!zQy|%-X2J*u^s?%x{}$ zgClLvo~z(wNZG^^Ch(i*dA=PvOrrsWU_)0Y!U!0h_eLF~5}n<&I04$|n9#yJCaBW5 z#d~(#EBuBG$Yn?^DxOKw8?QO-+}>4?;d7i?e;}a}@c}`(?l*@I$DqqiM7QR)X+1(;TxYQ| zc&l^8y~e`IzCh)U`0~($;`<7H;nS+8VR3jiB^416LyCjNbc#yI^B+KpxO@K%C5sID zLb{4jzz+T>e3T{5-rzOCzG@dV@qj$j`dEZy_Vq%n8hVLDcvnAr!?C4gvR6yk?V?Ak z#?<7dIrH^_^$bE+DAbGN3G4loj;?FZ` zkF1TKmAju0nSMiRZ}$EUM2XmOc*@1ViU{anVd3@2=xkFqC5fNY5~2@+#_KAu-X^cm z!%1-gKuR)n>ZKzowShEsrh=!_t^fgb-Rw?A^VLcUOk-uGei(RGEc8d_zAh2Axo9M? zQzP?;qd8TwMyXD#q=1q>L_ww51(x>luWS+`*S%aJCoUN%N0^HAMtGYRfU#@!mcaTv zft1_^*MLz!O{nU(!cprqW!^MM%Q#ZA(!J&jtDbgyEF$b0MFE$-qKC_`uBq_Q_Ow-u ziw_o9)eaMSff_b}!A5MW5X9G|AwJEcn)ZO!&|OS&n9mSS7Su0 z{*8C|i~}#4(-Al^E-4f09k6N2+F5}oiU4TQ5&{&WZ05!;rZF!6cX#SS^6>94)!!B~ z->)C|8lJ9NFaD2>>i^;?W-tq$bSjTZtsI}pE(YJD2H{1Qbtj;ek0RTjDGl=^>}5;- zj&ZlAXvQ{Ab^*Ing-t2fZ)`8wL0VuZ7_tK8GIEHxITt=uPMfhR6^dRu*Oh$6HI|vj z$eg5B{gT{WV=@ARyu=T{5aE{h;(B}Q97@5KHYFyVOdEIk9A)-}^>~C6v_U<+t#7{b zRY_fR?{!v3r3hvk{CpqKP;0g!tk%B0UueEP#x8zAffW@K+tgcg4fsih^+?!fm@5;* z%s$B}Waro$)o@jlu~veH5$b8|KPR@quoM@F^g@(F&ob%B2%6KyFvidBidz~2!PWhJ zh&YAPXYmnbYD|CRQNW=Nc)=U=La3v9XqURdUIaCc@N7n?A*hpEql4XGTl z;oJ+`ejI{s#T?h#-lVn>x?_nkS+UFZl?zRH;-ig$^QW6MvbkitN^7- zPgCJ8mxXWjqp3*`7xCnVy)SnutDcMraQAB^++>A*JPWj*SfJc~g0ETASABoC&(vY| zevzw^dDCf5Q#Dtu+BW7(OH7<)uVDHGGd+8ztCm<)!k&g$_FkG7(?>&w(y~@e>5}B3 zipjD!w-TgT&I%$d5g03Bp1Ls#Q(>;vSXclbUPU2fw|Q&%V;zL(k#~DMDa^+10qSVv z5uQ95rd&_>7fx3{D40<;O_%&($MJhLwYObjx<5NI>IyA>t8=z{6SZbgP%@|DojY6# zNeuZJl5<9oTd|&{GA_W7R9cZ)wVz1f3SqUx&3`cq=y!}Sn#eVOr8e*tlOKjQXaqM5 zX(NW5j}Uijzd6d^?6WH1>D=e_kqYt!`c}x_uw`fu!*I(xT;4~D##fji) ziMdxz62R5yB<`#TDtd&%8|G@KKaEu^B*IaS#Xj9%59B#C8mh*2@! z+U#N`)t>x^qFSU7HxkH;h3~C_jZ=}sZPN^i-#OoUeObZgm>i~pC0*#@-gC2hiF($;NuRR4L3sy)H{c;^RPzJ`(U9hoBEr#KBvCgaM|*BJ$+w%D!&(K3)2!G{)%L=+ z-pPz97*On|i?Cn)j$`0Hp;r8gBl-vb2YNWYGC5;lafKzD_H;^;q7k9&6q0i9IMTu& zbbQgtlCAs`Mnze{=5hGJt-e*wrI#JLMQ>P|a(PzYGsev_k`hT&D?5u8@P)+P7?O za}t1#OOC@_lIb=Xw}G1_j;5K7<4mn)lQWRUr>&Kf3vxroK>DnSLbBx_-77ee1|KRl z_Hi6<``hWypUjH4Aa4%INKlpqA2AVV*ZF*avPD@qBOwv%7^HK-CDm}4x0MqcR)rs6 z1R0RW4W9pT-Sw+XhB;1*@hTmX7ii2J+#l@$v?ORE)l}Wt2!V`Xn|~2kG#0jEKQBF7b6V8qB`D1rVvErt z0AP4OI{ugcxkjCWek#V|>g3rvryQR0{P}O~?Cf7%0krg4n2~8(uMROmv|4yGqNBct z)KXuIJo4q%naxgx#YkD2Cj$NDLg&HB)x*lIUf4F6%oQtC1|s=RSg+h;oKQ+vnQO}k z-|-HX-%hCD>QgbZC+!LS;CzXw%Bgk*ZWe`bN<4b4A6zaAaqYg+NGpJJn3Gx(IKjh% znkAf#7_M9R(}>K!H`Au-5FR604B%?50p#9@N=?Fs^b)Hy-%-xhpW%~F1J-&@8Fu?X zrl$RVepsCrg)3$3z&$ynWqqJ9{g=vv6D^@;a!zEO;aJF3Bq(wGzp zXT9)XLcdsbkU#}MpbB!+@Z4PDqT>;c6u;tWlt^Z7X;RX|yhM=?4+D94m6`nZ*JQ#Kwg!ptuE(yQ_@%B(dXZ{2$Kc07-ZvOyvQ=+>4OyRc9IEMY;(P~G zu$oYku05*#_q%U$Q_0s$+$T8J5x>3>{ED-w@;c--+5LLwW9a^VSj2|W=WM;L;~d)| zTJm+rM;B)2xxW%SA9jbN+`KoJeSUpC*Sy$lr|`K86U%O1(-5R=X0A3ZUn@#w^HP;? z!dgr@S;+g7%NOHlEE(%VYlv?-N+vu-ejnoMx-o!^RS~70@v5^-G{#k51QuiN+WdXL zfMP>`FJfh90`U@OwCkMoBc5$|O;wz9;BFf_uhy;@#_DoC%%fA0anK9+YLkjkTV=Fq zprBA^t%W)|7$i8EywvNX4fqiqLodL`>kwo!r1ET?Xvd>t<*f@Hp?8Ze214IEDcIuQ z-^JeHPWNBr)Er1_!v1dA;QOw|7$gT=Gr<}pB;*)DI>X}CN}_Sj1BuMeW?EpcUNe1T z0EzXMLGuC&w@%xXg$%<=7NV-S81)%V*GE_=8;fK0HTXTo{-tKYa2HjF&Ymh1Km`bP zr&zQ2R+8y)Lw>hbeyee!e`|;SRm`_TBY~v@z|Kia9^XcOEPaUY*8DqH!U}&?$ON3r z=RB$Ms(Rdc6#)ulbsA(Z-E!sm;f)mNg{AWMq{HIbT4cBK`*V)j>uPS_6On%a_EL&} z%dJKK0bEMkr1c@Y#`at|#t43pgHL`Tucn=aM;TzE*NJ?C`ihYf~w?I2Iq z=CB+K8Kt>4p7Ump7}1=o8PPmZvIE+n1ff-P)2B0qAj_#qv@vdOv=0ceqw*wYG-m8! zi`nd10tx5U$gmDeEv$q{LA;;BZe3slX3h_yHzFi_%zP6Q&%2;&;*0Gdm0(TV%=Tq{ ze9FF#vo#P zE50Gh?r0r?%MoKf4Mk4e9qd6z2Bdsh8rK1p68>l)tgA&(boU>7zTEBFQS^ zQhv6}*1}O#FUMKt7p>4DH0E~m1f@ykjA+_=>feQ67-UA;GeOzDHAsWN&D|U{f)_?QN&Z*pufmP`p509cQ=6Zg1#f#4UF? zu!=V=&`Xaf5B00m)g~BMiyMB`Urm^mSehF*`R^BbQC7*~i>c`(n~}+hfjwAKPnyF$ z4c78NffXy}^h`Fz4mx;^BV>EVIfk%w_t)zkN{V4Dm{eDhIYkr9y?1rT_=|L}mHjkJ zYH>@Fj2P55i|l8nm@^veu$h^~4cI<&Z;%N=99JuJUkbCDax-0?k5*;a+B@!OeBCQ1 z^hUP=IIYO5yze9Rg}m9KJoF8Y7<>!GJfK zv;Q@;&|ox8q{o~}5VFY6Ks*lhg-=`jr#|Q)!#@D8O}>wf6qk!&W%~irPM$%z-_b$E z=5YQvnTkD(`$*JNO(X8VT&eX%P3u*j&!@-5kPP*Mh@;hEohwqgh8bZ*97;ROTg~#B zsvMZbZsmdP<)U4c9|$L&f)tn7W^=?;wO9^}#mJrEQI4Bu=C=7(qQA%N6%1v{_n9=s z!)sZrt3i=Xd~~socPK3-pzwGcm}B&romg}fAy5CkJyGzA(ra(_rqfyeIaj~=Hz#Nc zB1g6=Dw)-O#%X_GqVQ_#pwM|>Q1+Mba;gL@M8%VeC0c^QA@~ITBJbIr_uFskswVopJZ+<0R@v zoojTfT@cmNANiRfRqW}U1qDU>(>rBC&JD;$XdNs zVbheWtiS_#?#&!==~}@wC^G^RBWiOS_X*`6z`^%k>!?W=&Yn$wuSuTsH)Pbv^hYRm z{_!e8F8~pJI!@I#`%8H#C6X|S&=}fwjJo&Rvb~QQmyCz%_tNiaWEaHW<(4cS@SOr< zq-Bhlc3W#}BW8*=i#-dXo_Fjz>54FdvPkolEjDEY;^O%_ZJ8Q0d0wyKv4veM3_s9w z5Ho!k5_+nz&p_;SYHHM16NH#HLh*4TokRP74byCE7)D zf^!CCF~|Y%s40a)up!AnQZ2Q183&1X%J8Vtw=~SdH^M;10_IuYNKf1$RXoPg zYAWiBrmK{+@h+U1rpbzh5N~Z#q{1+lzG06z`U>JiTj@1c#yW)0t_0{0r?V%$vMTX; zvsZGZZDhbxRd!H?kE^({~11)-NtE#x8OA|H$5q3bnr2t-SlCX;)CA) zrn>7B?y=OJN%!}$muytSr_3P~A#c=dJ22_e@kouOX`Zt5#?+j+cwVkIZ6{vYR-}X0}1?!YJc~Jy8s9{wd(S zsJPHdsa9lMzMf|6PJEzLf2mGN1mVXAa8}S$fQY3Hgka7AGc@?fBeRhZ*gIw1`^#yT zJD+*&MOpzs;tj;o<^tnVA)K#SpVXVCO*8U!Nb{viz=0I_%-un2(rz*IVV@Wv>?HTZ z4YMAT1>DW$4!R0{BPz1D#C8~~3wnxit5twTy%)A@Vh?s^l-Y7*Oj2K>7Ch0BclKuW z@mhRAz@cjYBa^l%JC?;<6jQ){Hauh4dC_Vj%Nh@#5a^p#Ww34G=v7Gxj=>4&Hwta4 zvb)(pdbTabq51$MSzdsfYa7gt2t|5dK7CL29+OECRSnR}AIJDvat&?&{m|u% z5RJvZ-Q{d@PWW~iUG*;x*y+tW7XK?nuoC-^xDlndZ}zjBplZ5fg&fVENugApBDR+{ zpIzRTbQG?Wn4POrsxsO7>AKJnFBsOPMEUz^WjP-4@(ma>aidFbv%i$TRQ0^aQk65` z33N0~zU^5nvhl%+##{pNe>{y+2Z?PhRaa#<`)ryNm|{5RqN0542~a#)*BST$A1mb$vj5 z+>pLBtPkArFa8bAYX5%2I4A4$D#L<sJBAS*5B!bbBg9Oz_{R>M%pT=wK7v zk`B|z3x|1jmTa&5xu&C#=0@U=A}DK^lJWG6!VF~2wowi8p;VaSjmLohj9N5}*U;<} zZq@Q~F<91w^kJiMk%^JqK8V>^6Rt;;D(bi@hWrZS6GaO7kGbk3)@^)BNgGHmgs`_d zXeGP^Z+WzzoY|tbr40&qN{#Mkt<^s~dCFE21~(G5Yd*vL2S+;_lZZ6smI!s{?JIIR z(xX3VT|#dsJ#cQb-wof6f2#60xvy5P`Z;Y@_~D)V?@L>EBC*(M$5Em9nkZJ+8Bv4I zFauHNZ6-Vu)R#7SRa7zIqLO6_-bf*>o(Hb@5#SzJo$u=ojGhaPU-EUW+PoFI# z2KDWwV8U1CmOaxI!^&^c9!>mS(UTpj=xibmmz2^D>3hJwI^MFKx?s+pjFo)tVBe5t9qI^5eoq z3Y9c^wY_4N59_3=;pdbgVcA54D2gdFVEUj}Vrl$`n$4M~LDssID`h_}`~+z3Pc9w} z418bQs`#V*i=jTE0hREVUc5Vkaw*xnfmW2;b!<;`P#beO^>zW9Mb;KB0TD{qSSo(TN_0)^JSW4(y z&^P}o2kC=ND8W{57Mh;Pc%}}3lv7G*aOY2F7lnO7#D~2 zElnqT*~k1YXU`2nLj+L5R4o~-ZqfbwCTxdQc-+KlQP|tu=s>xh{ptm5%>T9k-{nJg zic-g`n$?bIq6WJQ!ekVTAS^&}F@MPi1NW8+Dj`r~L@J?3*6a^JM5NHEnu||e>C7L@ zh-9+CO#v_fDYW)4{Q?HH;`{|NJM+68HThqPr(Vq%&QtJm71S3s*FY5wrlR0q5r$rn zIV#n( z+0JiXmoFaawOicLHrC0c!ntE?$CPvwf#9lW^?RROp?YFGnN&WXPJOigixJC4aCAa&c%3Ihc*i_(Z%A3fyBPD^|*RgP}uXr%O1-OyycV zsP1j-|DEsq0Rh&K)K{Tmhy{*Gu9LAz_fcp0sOSDh7n^FC8(Rv1Gf9WtIk5D*YjMj*zzioy!JxPFLK zUS(i{R8F4jEnRK{vk?orO?xH5IJ>NO#|R(f)41ua^hH#ldQ*s1YhAUa=+LdBhzY`g zUy#b;n@;yjzyK9lW=!a(^4l$bYyQ#1j&MFki2kAOkeVysz_H$!6?cgZMCwwsN!v2F z4pXv=MMBl+b+%HOSzMMuf6F-m5LZhBx`>l4TrQ5Ob_(}&s5Kl0=Pjl_CJ&eUq>W_o z7BzCRGvuGN^NN8aROH@Jp=%NnOjmP9oV3*uU<|$)c3=nvefqOu0MDG!qg*Kh$BNjLPo* z*x~cum!iw7eUHCaZ)fix++UoVek?zq0@`0RoG&;3`2X}PekE5#V`J4&W;=*3*?cUz zGsHkfFlR-iyqs>tGY)yt6Hs(sP=5J-zI25r{FRKQ*_2fq`c2Ybk4&WrlW2Blp76%5 z`4)G*?X9P&+CF~iT)~dgeUyp(C}1&XfYxuJ#(aNYYVkYbPN>yNRd5Vlpi#^i5KQZS zYTTU<5Ko81ULVD#AEtKaNH^ndI#%7qlqA!YrB=M1kdIDHx1Zb#u&gK~QqN!p>uNKm zE<++i3)Un(7nzLPEfKL0)2zNxCmW^V=11r|rVV3IP3+b;|J0-=MU=rez)5PnT2k&T zoEN;fif^KHDUYb8ySS$0^kN83AXneH7!#Fqsu5rX@}9o|n^SZ%JAZdzkVZ#&&UbOEVD z?rHwfZ8bGkW|l1W{2qAtwovj}iB8fZyS5UHwnlUnXHP2kw-w$G}vsI>Q zot}rz86$W<`5Xv4AC?K*n=Gtp2Ak=S#4yq9@N9s{gu`o4RQ|}%#vE>t&2;M437?11 zzWR8VSUbXu5Iq|sJrWmx=VN{oF&`c*2-^l!3Hg=DAOUV6!=s!LoDCBMzgPdu^nq0H zZrbe2fMQ$AS4_D$L&{Os5QtBK>Yl1>DENomi?3#23M4E$M)U#zw9sx*9o0o#zfZmC z@|9ygZYJUqV>1i!9h3Tl$nEK5XuK=Ak(0weqg{16(0hmwoe1cqU+Z#T)a%F z1j)u<#roqV-^FCcG*~(p#HbObi7oOa8DqPNrykx?#@(@(coi-?3yr6YTCT4YbMOZo z%-XFml%~0!b%yq$q!2*86s#u^xWSP3`2T&OR~jP#yfgF;hKG9{LEJj_TG3bn)npnlj@*6F$q1PJP7 zci!JyKdTE{3>S}9y-I{{QQM#BaLYxfBzln=t&5;(x2cP`|1a|1GANEHeDfXL-QC^Y zlL2PXfy^)r7Ti6!gb>^YcTaG4w15eDe zhPhF6?i1CNZzg58v%H^#U=X6F-x}**ucgkTDy+mggzOw%HA%hC&=k+8F6R)92=6j2 zN6&b&TU!DE3*(IPdCk+4tK8-}#6L~k!TWXjtr ze17?jTrmD|2kq74g2%SzX3(#8V_~ofq=nRDx+cSiHS@-8A~b(u3JL^a0!J30JIq!3 zv)RdV^bqM6-_bm|_X|s4=a|a?3QC;s5NzSnPT1r8e_gdV>V0_#X?b(cGHPB9OGhk2 zGF$XH%?8!Nl5N^;mNAWzON!PxE-wap7s_@Q^Z|!r(m8NZ8tAu{?vU4!Z`JBF%{EqH zS$?TpwN!CO{2Z$F#tBVv8+F{!y}7g_{>0cK(uwpO=vUUg-({wiM`{vsd{RLrlCEdj zbdx~=6p}Ft0k%kD7HR8;f|40M9hkurVFjp3f;4+f zm@BQmBQ2$=tTVbt-kx7@IUqD#9Y%ph$e<-G_TwGRWG3w?wob#U@tRj+J>BqZv)EDD zqgEG>aTG^bz~&@IC9kZ0iMes)Ij9$;TkC#28 zoG0$rVLG}4VGgqM)jJlN?G7m`(E1G2dXQeHd^QcskW>G&n9lNb=N$nW^PHYjX)DLJ zMQluu$QIu6_0Qu^FZ!5K-v0nLN&f&ZMHMZc<*dC8eEI*GLO>pfLNCk{go)PZ=u98d zB5(K1<++@j#0V(+-YMH6d zmUG)}=0NrgjLsM-&z9mEZB+(q$Iq9^n(0Tx=YQf+i0E;;tDz5OjpKgtZ|vIdt1HoE0o16 z*tDzuH;RGnrz-8c(=3`_6jfhNSVZ17mIbu`0~Dj(y1j3oqIsawdWiLw<{r>@Ju&b@ zmHrOwBRa$$u!=#ZYQ3o7pSB^4(sVyATk!urFOg(cRE)18%&E}v`!<61gr-Jrts#NW zNNv~hqPvv>taeB#zR-nBN4dLb!O(3`A(qTD=auF{9@JNq7Kb+r)vEf!yWf65aQ2u_ z?X#QRV?HQgw`m;SC`bOGfFIXX(D$BkD5z%I(ERfN*_7Y3)og6Cx#c9F6<~x_Nxi<8 zlBG4D`JniN?KGQG`9sggfNF#hJ^A8hRR`vN9{!t{VeDf!qe^09$#vSJ{tG|)SN@M- zfkcaAwP!UXO3vZx&rIK_V2sxagkn_Rjw|Cii1+!wZxf5<-OOt1*%8EsrOYY9~UR8RH||( zIpv6T0G(R@hv0W{(PwB0{_4Co{E++n0|mU5$b4@RT{tAz<8rXl-_Bg9b39@_N` zkniL2e^%0efB^WjEW@_}>d3LLjdj9Lx~67bD$igCLyu4r-jkwNQb6Gn zR(NQ(*%P@Q6F<-HNfXpkA&o+RA`&?2Wt5)*0B3+Faqb^r_3NkQX%d>x719>(41Rhn z%g#{v@h^*gvc-QCU$L%HicczxaIp^{t+UJfkn6y@B)QRR+|vMQmBL6tDB#O8c7YYn zQ6ogJyceUEOP7cOLtC6r$$uOh`a3BnX=+AP-3g5KyoS7b1EbMH-^BoohH&!f!j+C2 zZjC?fYx$8+`X(GxWt?Rln@q(7`~!&TwWvaD;%eT>j#6>Er8Yh5_NdU!>4L^$s=}(_Ya_!`=Vx4ANQ^)erX{@d;H{eYcgd+9_hTcQfeu9`m?JRl-Mq) zIc+Yf_as3?xJgpacPxlcT&qoNTQufPJDsm%m(hk zY15nAVlyw@5fCb_Bi!k*F7|h-$AnP`_ur|}N66yw9pC0#x*$5E?OPm@r1Gz|a%Rq@ zzuGt%_y@j;HFwmoSFiQR^Vr7bJoI?An3nuTCOEz+90lbqZ0 zNZ1UxPBLr8)hfD1pM$3rGTzg%iL0nj0%&zsgkM9e%NDp8S57b zksvZYIV;jpY{rvx&rnX3svFxd<GV@@I?5yKZhC{z)L$^kfmmKfqv9!qfzf`Afaq?R>6QlLMcpCzgF$)Q?I?NpZ)vTH zsjN{s_OUzg9>?ctq<|gOfn)O`KQioVos+Sn1U#ilwxS!2&$qwu`94i%*BKkSGfL2; zq5h(gV>j8Fj#f`sCx&aU0=;I}HJw)z)qIvv*O+XdF>|$; zgU|dDSMJWH29-m+U}KO8Q*H(YUQ~~Yg7U{_q2o2rOAS4fRQnPB=|-oFlAS^k;*`7G z_Q&F_>?jqDL<3{?9_Q(srv(qfG)rm_?6Gs27U4eb`nCEdW4(c+&$wDPhM?c>{!Gfu zb{UOdvOzy0Dxno3sw>u_^G4iY&>p3cOXkC^Z6?w!T}~xnHpcTE-;cW%lA1>@<@zGo zrQV75;%Q%IsX*Gj$J3Re>YN%y4Pj)m!pb6}dU5_gIPVG+5xDRSFDVeHl9#rGD-Sfn zgmZ}th@pEs@UmUcP4{FWt5&I@9*c*+JnaLv#EE}574k9OPXzABpTf+{chdw^2V?e$ zCD)l96Ks}~rW#1FC@6i%%>3OvjIgqf4FA51OHh}_jlldYY}U_(Mk;%@Cw%+dy<+yX z^+sgJrNIrkhH5*DgwhN@lsea$7N=@rFjiOf&MJ$F9(Sq2cDLsB#t>z2XaSc~ecpQC zvC;I4LgDLxaX;U#d!8wzren>iKM>3w>rKg#O23+9cjd)rAnj&r7_9-3?Ge~nRvD)*Q^`X{A|5c zDe-NAx;md<-9EUf+#AH@+F;23u5p3e?UdQh$zK(7(Rm`{yzqoE#o!)Deoh`V)&gR5 zK!$oSrw-l2Q-TK^=&uU_ibFoK*y>KHF_yv6N-`F6 z1^d+Fl41PSXiasoxK58M{-eC=k%d$P8_Z>K%4u%C_v5~Q>iOWwx^k4u<5KqfE?9Od zrleQcCq?=xq7_?f91g`;GsRy+HJAlW5w+5OS>6fm2ek@=x(n9$ zG|sOWQ|6*%)e9;~6;vJReU3qmqHhN}Bx=ph>G&4%68U2%mlnBgdPQ6(vtsE#Dw2;B zQ{r+EG0;po&i=^?=XQ=h|2VJxJMz=pZmW4BT`dViCk?+5 z%7Kp83uk+sXp?eZTgOmKKba&%)A_zdm3Y?u1;#i|sD&@VQRDQ%HlO@T8sW~d4MGbi z#3Q-hX(<6OaFm9~QfYo;i!&@O@K5-n>2QNb&-hp8hb$Y|CsYP2* z)=8Y#FR`JJl>EE}e6e8T>44BD&a^)893@xfrhn_tv2gGzCEMxO6je`EAH_sKWZq>J5ioAH||D%kjz+{@Cb4hh&(+SpLy_{c34Oe~(x8@AS+S z?Tq~$Y}lx%Ye2F>O(UxaaW%M`QdW81Ze6zVXfDQ0@q%3^){>xlJHaT~iYtj%)09Tm zF1jW)zqr}jnp%TO-OOh{N~SWa;jUH@6(Q>}1A{;%7e;OW1+oSjA%D^r>((pEiv+7j zFE>8eu1&x>7PYD>@Oa%}D2z1m4zbQ#HqSvH1~V2G8DF(yN-wp5CNrVABzxNgQ#RlS zjaC~h!nLNlziwM?z1=fu$}J5B*t;@YkKC~xYo?BFKeKC zLpb&Oz-u@03{rO!k80Aq!6-YBnM>8CjK%_#pabEuy+do;Av{LEg;DLlh5c(RL{9~^ zzRg8V<5}xB8ck}EZ@8=2%kqRtpO*ZwVdh3wi)^7_(CXVxbLa;!t9>v;2UIK){@XJB zM4TQsD=6Yn#Fb8N*e(sth_*w4R3AmErfe5$7bU%3+^%hN)+^x}eu5sh+^DCd$o6WC ziUmc9^~+O=p2$)DY)V^cuwxmYOOuC~iQ1_^`yQavpJ{;f(nzLzHp2Hj9oDy7V5~o7 z_{B)xr_12AUl5UGoulz-&X;Nja+i)Kot3!^W&g7{bN8q0raNzs9pl;&KWP%~FD>4+ zINpI|UY=23ooS!5EpMuFKaTWbAB@)qhbcgU{I#gkjts=*^igad*b68%{s(g-O1Axl zaH*ro?R>8Y{{bhJS82dcai@l3uTCIg@lR6B4P2P$aWPOG_*Kq)bszWTVg;zd7Jo#o z`(K<4Peb41Q)yM*XoAuXa;Es)9JTriFh1dD(3d9^g3K6%}R= zOWG13u<=8|;d%x$Y4EIo?r?F@A;)(t z=IlCjjK`XdhGi~_)igo_nz)~cGsG5U{NVccI|}*>oJaYiND{*oQRKat?2&jU{dI*laH}+Zkp%c(yisS*E7foh$%Tg z#VpdAp6v9Q!=o}#1`^ci{{z5R4h`SH<_{H5zVaBB^ti<4#J-^2c4>mYqP2-?V9Q?baqRI`gh*XS7WeOG2?7Vg%lu1lNx?Z0e7*e5Gr<2$~ zde1*USjY|G$epsuQkfQevCnV=o;HPTN>a$X!d=Cc3tqoE_8Umwv3i0>$X}+`@LR1B zl&tL(vp%Q6l7JSnnY>M;VRuj|HiBh2|-}6KX(t z=V9sz*}EIq8`nP^sV4T^E6Iv_uI$^*0S<(jz?KFrEA1SFbOAo|^#5Gn{`%bD=ydfw zpSkp<&+zg^ouW==Z&%yz7iEbgOho#ZcAI1vO7@Bq4L|c!j9yTRV+2(YzpS(rPNMjRRVIXmWeHo+$2vw_jMczhxY4I&OIp*@JS;&lP(fYC8i&ZvAmIy))H8rE|( zFJ1)+WB-6%#=eb_U6r^9RnXj-?8%%)ag*{>u`KMQ>P}MyyFk~9?lJq+3?Cvrfw36*gH)U`Q8H2X zxL8_9vHK6^>>i(v?fO^3fdo|nzuZe_1^Z5*pSM1lOd)C}%#2%golg43@Rl6Ep?xXD zLhMWPPm-rE3e%osSNs`D;f4PhUl;Owzl8hF;F-P9BI9og4LiXgXrh6bpD?4un>24H zIdK;fRvGMTbFn=p*&i22*k8UZx{9xo{g#{C!j`|$!kHMd)!Hh$Ycwl8ge1g|x@W&~ z!!&d(l7L}I=}2nYj6fw_J)y;)eFyEc^uM@EJu=f8f9ARLqc?$BtWN&kj1kJ2=qHT;?)gKUoBd!(IUZU10s9bJ&qB(>8WB z23zE{c>#=qOicK{HlKzBPW)%2$tC{(+VtJlY{|E2h4fmM&K(zO z83x&Fxuk?`32;f(3g{BJ*4CmCDJ> zlb|PLLy%I2?2HE3T1QO15brwq;&LemXQYk3b+ox|)$U2678K^qpT}RB;d&v^wV!I~^F=@!_WM&#w=D2`L(b(u&vdy{bwcyYH015SDDIxuefjECK{$HGE`jOaU zeGL5>i0LgT{k}g9+Hy9R5|?9nEewlDyLA68uiTxdWWV$7mpHnfGt%=E#@dIqXf zAm|H=MRp>nlPy(=i?&MAJw%w|2=>v;=3^cXnV$=LuiVtK`~!f0{ptQ}fvO96r1^S% zq!c3G{15QMB6+Id_Rq=KKfv7E|A#9hL|~uxZ^yBSIF5Mus6IrD9iU$S^|kp2 z`1Xk{N9Ss`Fd5osmyx*#E4 zkFFq2EB|^#GQx^}vqn(mdb*{m5XhFKl2b0%9}+07m>>DFCf-`yOeWRsuyngkb0ye4 zKZ{s52e+&$=QuyaGO5QI!1g`!d24Kl*4JJB5C_t~nPY?ce^G3Y0?Copj|Hl~4O#Hu z53(^o8lI6?{`4d{HhshO;%tv)zU!CP`?cZc<(~hCx4R$r<}LVc2&YFHx+Rz7cZ2oy zu_zF|;c|;HyrFo+Oyx|NiUn#bU#E-LM~iG@O9o*GJ1Tt?qi{t(VDW_Uh!ij@HTyhp zt$AxtuvJRINAHTlbJW;=)VO94hd)-%)w(LJnpck>S)D@&#)oGBfwBnw3*)6~O6VAe zkC2ZIdl*DMT$66b35;2O4JcG)xQtDH_1}B|+M^Fg;iOR%jEC)C_ns)m&fH?rjYWW< z5=GwB7Qeup03FrtK@+jl-A$%Erd0#2%^nh~P{bz7{&%5j{v#YbN*~HiqZ9F|P~7{P zhF<;++f?3%-hSZo$z9(|>AFUG)iT|~dFC}Oh5gK}%fcUH4Gl?i!uf&Dv8MPbsvXLqqVyDYMb zMeNO=68fluTwCVECTU5w_Otg>2pWob`_&zRqJc`kC}bQQAAc-o2-I>6IchYvc|R{#6OA_b_YEc2_%cFy zr>e3hTB(PjN_-*0(w>c0XI6tlnz@abHqdk-LqG^AcQZh#e@DN5yitlWB{srwNlls9 zBHL-lA~dH$G!WcP$acYECVN3+vNvPOX{qB6vy*q`_Bfjhs651=RGqZKYJV8MljT)L zJxw|y%=f+HjnTi+=NkxzB4crStTVLlB2|AG_UTSFB|v}>pwCXEu_Xzwj5~c*(LVsW z9of$L$(3*g&7y{Sa;JLpR%4#e?Cew(%VAD6$<@^nLEaznzdJVq&6}nF0D1I%9?B%2 zrbRH#Kl5HV1p~+IKl^wSseg|xDdIMJ@dN2I_N(h+){~HZo)rCkj|{tWZDop~g|2nP z9|zIotH*(BhvFQ~417-ZBvO$;jnV^5W}fz^1zwM847Rs^t~X^DiI}t(s|Y<>zb~7f zU)E9@fCJa763xxe<@z0;9+C3TogJx1Og7izkr;uS0YD9sokurE=v`}3bA^P*-Pg^K%>_apF^kq22 zKb)Q#FHcyr^7?jCgcEc7IP7b&+*D(RmNMVl?>L)UF_{rA+lz~8;1mL!hp|82T`q0< zq<3gg*$^6LE>LSt-Z5@2rFl(V(2srvzfu8~V#t$kNe}YuzKbI$gFh_+*Al|0QG`hm zN*t1_OXF!8;0Azau+rreyeTS(4<1I3xz|R2!+o5db+N(Ekmj*u zyUAJ{GO425}KJ+5MWRrSFHz;RLFKYu6`+@3Z*D` z``r)Vm!kzG!xkCfC?d&i55TRh6eINtGr-JPX!Z1Wln?qikmOBS#s?Y|i+rNj7gs0P zkXQn6G6G;6Q<%N;&PWXQy2Ny)=v*_Qe6XcF(;Lx z5MW}UYb;4dU|bHypO1JP!7WS;rM)S&>C@xfuyb+EluGRJ(0h!m;?U<4yHfBt!Pa?4 zrJt@^e;y**2-Pb1UZwzpfFmG6mXOx)lqmF!A}l^Fz>|nf1So$}kpb5@n@;mj0rFD# zoG>YTc*?%0qjf>_;(yjeO?uH+Pc^Yhl`0oBw2tn_j_uCY=y?8LYGUbcuGq_Tj8~NO z-ICf%zz;=;)h@YwK>$-8o$`wAU{C?M^rNx-n21%@#fi!U9?(a8GZUXzkR>Qfe^UN0 z4Z$cqg1RErwN*w8ZfSIosX1?rjHN0J#){)Ur*m^P;GfugbZWY1#m2>Jjzf6!a0 zk2psn@wqr{d@(X+l!=EXx`d0~y)%b87yb03#PN_Z51wo&T`frF90p7@ThSx@sio4` z4l4v=y(a17Vo=aQE54Wr9uet@o?{wEb!nNPxAfRiJYJ62a)39XJm}fKhLVX(m$N)} zZSY7vIl)Zw`a^4%WMq3BjXf}`#6NaBwJ*60ViWcI-=1@J`m<7)0reWk0F;ClJfFht zpQe8lCi+aq%oNIGZ>(JViCMmqD>X$I|8<_^Wh5&LlCCo;qvu}B!;@Bi{(}sJ5B>W+ zcp|r;6x&Pa#V?)h4)8p?yi=o)rKrnO4r>4cZZuo|Nfd8#HYr?_124ktFTOV&>Ya|9 zI-lw$2@htxO29%hMAtLPsF*cff4~e)*&PLnlxKG<-`2}ko>fo>&SGK$fxiFI)+jre8{4j*^KbJhA5npAK~x8QFF0cjsYnmV7Jo0nB)> zkt?sC{TLB^rm)bz-t*THO)J$u17jRY@dSHYxN$MU0%D=zj-ZuUhdz&l`Q#?G6#oq* zet#!>@!gY(ot);BM9VFD;~VnG=J<+MdH5-dMFxR}{t^>y)lV;p;+|ve zQM;ql6Ng*r4EB(uLuW(oD)aIcG6%6(UH&eFQPo^Bk}3e_P9;(| zS>90C7Jq)+=8X>o?To&g`9Lof8-=m0g^(P{n_-VN5*Nukd1c$57wj- zsHijAD!aV%b8j^ry{DNSJ!1?nV>H?wA>0o)#6QCScb!~Puz%fBmAb5Ga*u=9U|RU| zQSP13)g1y@PBuAMYEd2uWvZbhY-Z{oS&{DpFcF(*zt}N01~l1g!JFw#D7unbeZzl% z*&FSP35{ADbE@=0uNRLLYh&05mBea6kEjdNDU4>mBUWF}fPC$*5FanqP` z?L;`bGnklfi7S65lRQOgFugcuW_gO#kbl3f`1~nS!}obxz<)$)oP;=j|BpzG#lLgA zPmvlC)sLk^Pmvlp@CWsnr$mnbAKX6VSHEFUAbjAHUlQROLAg6QSy#lJr?ZjTQ7IP* z#08#g*&D%^Lmq;aFmpfRkm#1R$6cY@jTeaSby7TZ(` zQlq;9EY=@aIL~gi+PJ`V8zDrl2L@yW#ysZQP1Lq;TDUPsT6yf*0J_%B3^;2lILq?& z@OR6~D+!xVS+7_uB-W)D7k$Y>W;Kmd`<>jMmEfd#(LE1z6kNXsOe$3}D@G!pdr*BA z407otin0npJ?)w9gfi%A70j#$<~d6#zBaZDXHX1Jh&Gy5)1b}d*7_j7)laROC(p@+ zeiOI;Jd#n~-j?ly%E-^nH2JY#F~}&RC)3+N#FyE9?-7r`u*-bO zUmT}v=X~$A1wJWqjQnS|lh;JB!1zCaLi@4)O4L;=b&d5I!S?j6Ig;o4p-*43 zLu?6_{khXp!Kc-Y|0Gd5y!VYiS>xNbEiBPin4nx!=%Yg54>4a~bP`}u;aFR%>t@Mi zUJBE@QI`YU-Bd#eS-$eX2u8;dE*EF9D>i3hnH@BquC{{bF7<-v#=Qa@fSO3#2&PDY4?PcObJ9S6$mh`YN9U-3V-yrZ+rwcG<| zMe*V(q_=gjAn@AuxEV*1sH2hI{=NokS4jtp$*zIJ``=FKwcd8qu~j~Q%AHE00y2bk z&`!K!B7`#YEzd>~ob~jPm zrmw)<7}Nf_JXd!RzLd)htJh{=HV_M^cFejaq5=11N~hiKTVatGf|Q56Q%*^@f18b< z(P{Z2E0ax^U22|yzo~@H_2^`s+~Vk<<}kJ$&-#QPGf^!(?xh3z#|4-NqKu=Wd+MFX z@_TjSj~O&k)%keP7Dz!PpZ$D&@6}X!@eoZauCUj)F!oLU8lbmOQ;jq1R9Lv1g77NJ zMpUnOhj#TV!x~49q}BxgyyBD^Bz$J8utfz6!ot~NFN%iBO+c$uHwM%4$}hdUlu5I8 ztvj8ox3oG8hVj>xxK5QkFD>t484 zz%R6MSUmdbcEQTr2Fns?@liex{n7|&2j)Q6A~OR*GieYKQu#v%PyB1)IIFDDcEZh) zQP)E^dZNMz-z_ySJ*;$B1AKPX`XW}hr{!ayJw3tUvet%^^La8octCaWtZDDuc0TnL zi@5{imel04>t-;L-%$@giXygPOLj=y$;hk>#hIzOzCf907mXlqe0ESh%I_B(kv&a_ zMMlmP9|=+YRt%y9h}ulc(NJjB%%3C9o;@)(O{4^~xCz$4`PFeHTLzX+9?x!QPu$;d zlDk8+C&_rI|GwiCyHz7#5;K1=PIx`vNQ&A*XcZFQF6yk!TycLD{&rHeB()-NS1SXp zMZ*jSvIQK6J>Vx&gH7XQ(l)lA`sw(W`3MMjgEkxugyN*6=N!(IrIA%>4oP0C2aCkm zSom-pcut{7rgFUngH7#LMeHGWwRub{aAH2)`KKUt$C$LPmNJ({O>7TmekFPlE(25! z7;spDn`;gAQl8cEf%>G?^62_i!xap<jc+#|p|(Cx*7 zs_C|i(4&lHgsn~!*T={ftc<>uG}F^SXAw^ZExDRP>zpB1HnzRuK_-Iw(#$g8Z@;k;hoQN1)=q!;AkFwLsi4XJ0jzHWHD z9dl-9cO-omqZDSkP@81n&1D{$F9k{a6qdGg@%sBvyr#-xUz(CQ{UMMjm zWYQn-`dj^YvGwjAE60LPskMY_yhbb~gCsCgQ=GI+8Jz}r?J|t+ncmF4S2HwtDnXu+ zCwQCniC!O-24Sm*&n4OBv!@b!vF8a->QA!k_ZP1Xo3Z_=>Z((POssO)Kv0SmuS7&u z(lmG9SER^65$M@^{LQhc4q?e==#b33t3`K&~u0>>eeW{5X`n;bASle3|e^r*mej2#31Q zCfV*HEoOWk+9)h;ppi2o8vyDyG;lZ7Zb%?!YM30r5$ z+jL7$5zJT0Tn~9eLh8}^{wTR{W5lj7T6>rQetKTBH2hEy^ny6dz9;Er^Y#d5LdQZ) zad&OpB9jkAEC2x7aBk588Ce!$taekTx$evqpb@6Tb_RgSpcQNhsueZ%Y)E!EB@iT= zKJHqVH1R6m1mTnmPO(1c^O}i^MwHcQw`JJw);vTK&)6TT0(sFbv3Rk-J{9cjQ>q0F zLa@Zw*&202!=LF?_yeI4jcV=oEfwOnn+~{qRoD?#xS@R?2O)O?HaDoM3&Ww3f}0n1 z%JvI3n`T9&);Ht3*7sG>GwYRYz!EZ1PcILY^$sU>W}{T|0-ubCp)I2v3-JjdYQJ0&4(1wfw(V(Tr=f^TcrJrYs<|$-tKYF4t&+)&8w~P zqNCKT_)r)M#XoNk63F1;$F$9a8I7hk)d{$jE>Y!)heyPKv4vh{49a&ZH|vSwW(w2;ht2(QmUr<*rO3Nx=!MRh?qlen}P}21R$IOH{CJz``^JdU$G$0 z5#F(c?6I!LC66;GOe$5GKfbDUxC~QXv!EoMJ(jk}l4(7e@ZH+}z}4Q@l$bc@wMbWx zzM?ifSM4fgwyCPqey*F)JEy7x_(U0IlC4$Mow)n9ZmN~yo3%Bm)EGTd^X;>~3(7vt zS*WH$tg}n(^G3zFg6t~^*Yqo6?q;zRx6M1=pNd^w_C=FYjoeb4aAp%Q`lT4?@H%Id zd7F7ev4y)bZln@NNU{LSseRCyPI7=0S@1#HUbC`(ItSgE{rGp3901ot3<%&ubb9rz zng;X@<#`K#rGJ5A{u+`lK6Z&$g5P!64M92{g8@Bmtdu2O4E61rkIRfP1XAW*;{p1t z0mDjh>};Z+d#IXNzZB??GmchsdpT7T!pN58XN=Oli4@42vy)RDIge!IV{>~()~je^ z*y9S0pS&s7jL~9*Fy2_gn_qVxq_t}`5U z2)Pd^(yIdi7^REJjgFV-)?fIz(dHZQRV5Z`%!BBmX|@_np?6-Cq1n%~&>2EQLlj~l zXRj>Fm*0d7y+`$x!9IJuMWVwXEauwu6apkUP_f0gHnaeIE7G(7X?ezB{}qtf?>*q8 zEbxWJO~_H~J1QYS6icC_q0I)UtZ}J!k0A<5=7wAZPWm>q9-=S%v5?;&UBLPzaOenS z0s@ny%8hI#Mqr_u`oUUokzaSYZn?rC&AA$h!|$#i4~DWuJ{7bK&C!n{P!@TMPl>H z7IC1P&_&sLuy#}Hv4_l-KSR^GV_WQ%g5=Enhd!yG04-@paFnlNdbr?_sly3YxWNq!2_RV zJux5=Z0F7MbsQr@;DfzGatihl3OCq&LJnh`vvn-VD@rZN{LFQ=)ic4I@rFe$L$D>f zFmq}(3Y$+~9wbH~hqUC2B;+C`!gd#*2oqO(7Ln9w!Lqbau54zCn#m)D#ZvdSM_w~FNyniD+*_vN&$Q!KsbrR%&^;wh5L!PB z+ET>ER&kS}VM|DBAv!*gadQf~)*X0Rb3YlrxjsYcES`fUGbt!O^Kx4)ekfiWa2J4G z;4bRsX_GJ3+dIjxrJ6yNskCK%(5f;{a7in$d?;`Me#w}zb-?M>gAB+?B@G7kZ)-3p zeIciqPCfNWlU{@RK0~(kSqp7WfXg*osyUdq)<83+&#cu3Ye4z{utXIU z1K@}Iy^YAZ(YgsGtuxrbRI%x*+ zGOUs7C_D-CH{uD{%snS>s`=2*&Z#LHh{D*>l5}LkdVSW#W+mE!A_dR7(KK?5ou?Ol z+VZT6%5ajB0>Y?`WGF|L#A&6_NO(!8Pf*%pexu@e)&!3g^>{KA_6<*?EY2D;B8Yh! zt>vPlo2g6#a9kB4IwG@kML_eq(oDcU!)L|TC+f8tvllqEkP3$xf8L7neln>9)W(|~ zkbyHb@~$<}F;@%RrhS0B{z=Zr=i-5OnxGob0T~7y0lyu>3#|_GdD`H@iD?7s7#yVQ zNM*#oj}Inc&lA9|=J(U%tEi&v$7mZg!`a;FpgRi;j0_cn$~kbIz^|GPIZ7^_y(aqH zK_E)BC9y9@IO*mhf>s5+f|<{mQQLHC>O-;xsm(oceoN`jr`T@#IzYt47Jy2HN*Rp^ zjU)CamXemzfP!O1-hhFUypEO#v?_3Om&DU-6o7{X`F<{-C%~u`zlIZ~5nV$HgE@e#X0Az(L zm5tIw`1OB0pk@tyg)f~3nUoeb$pD#f#6=M0=km-i@5uI=f1REZeCoFSn7JQPxc)$N ziuyv=%6n0DI)A6`rbW<*D4)?=sDHP@o`V)fU2eJ;N24!i-4M9~12ETGuI}0K2iywU zi59xBD+UE;XtNe(Oi9&V<1}fH3jnSRU!rci)SGqmZz=nSN;ZB|`ixATGp5BLH4qzB zwi%e47K}0;DLLWvsUVckBJWSy3i2Gx61Fk@uBWyWwYm>~wluU9^Xga9LaSL zXE^q(*8yFATLn4c4Gf)p9h4(tlb8$U3F{jxZUFmVej_ha^pq#@N*Va1*S+xa9cnX1 z+3hcN$-zLm2&+io9*nOIm2yvv?v)bgvdrx|5%?`T5uT#<%x;&9c_3FWBaKgnZ?ZVU z))&`04pg!36?+)_dRa)}jq!bWUq|8$@t19`4Rdl&L(L&B{dY9G#-hU2A9i~k_o{N! zcu99Gr9Vir(2w@!Rp~R-Z2wrM)M|bG;YypgCpV{?Ju7saQ5the`DTaRI@t=bj?rkG zDgC{5nV|1BufnHxNkIbt!{CgLrFE?og|XjX>6h;~jbMng*M!rxWszmV=b^BX9}{of zyvIKC`sQlci@nNe)YRp@;G!e>Lr*$hG@;TB&Lv#gNq~{asIpY%FD6*{*KAxz z!uiiC-zFIjoA$4gxd>)^D%;4ZXB36`3&#Pr_3$D(6OR4?ddvUXr+p>W>JrON%l>9J z)NMGKGbx|ymqA#|uJF41RvdYqrXvR3<0j>G=BT92KUN8O9PFgq_+5aqcpP?@XM5M` z?;v?%_T;}DHM3{{nsc`cNqJ~lw`HABH(#b0rq9=^kjI9D#(#k9t5}-LBxIko z*~en)Zc{;o%{-?KALis7P`diu=n&c~IXlQsj~jcnINW8R^!5W##fDESNyzoWEKF$1 zNT4}><0#t-VO*BJYsqeil(yZKU_6OKajdeQ(=J_9ZD&u$xG264cygPunT(HHuL()93n|t19zr)Gd0u<)dxpiyQ?q)+fRUj)S2D z9XG#KS;D!2kjm7wJNg<8K@Wj!MzmMcKY);GEd#@PqIua=g&30-v|Hc~j!4iK#R0d0n8r{ODxkeZQKb7IhIP-P}oR-k22Cq}CHR zHqLVQWuL3Nu>Pepv33_HwzePql4H4 zj@8WO7{e1SI8gM~D?&I5oar5|S!}y(gz;+pW!-ccFXQ}pxwu2kbVekO?fj1-1M1$& z{~o-&Fcv8fWI6KtxO7dPAs@WNgOoNFZLNOg+KR{m#7e&b;^cTjtjDy6*Ehe(LKRCdV={biD!8{PzVF^-q1?I$Bv=EN3lbjM%BW0C2#{HMRdeFZhG?Xmnaa37^8j0aWzeaJfCsaf zjBlF(s|2qpXcVz2&3nCfLun;DIs5<(J^+EVFwi7nK9Qj^G6zsnx~oIW)SWWiMERLf zVY})#N~jYif2s9|mGS!Rvz~UTjP3KtnSpfkMG$qJ3|@?MvUuzktulMYhV5wGBxb(0 zAGWfzGq%<=0}f=wAt1Oosd#?P3c&p#rzwE}#on}a`RCEJUS~n~yHkx;@9E#h`R6(H zfI+3#iiLybB|})Bh%dY#e?z+u)6P?t0uKN z8i3Pu(@qS z+gt{5hg#LFLErJQ|AZRbdNGB(lr-x->3e?`5hw1MwJnH-S@9IbqrZ%~=SZS31}ugI zzLnH*k;2$iV#j*2H?QwpUf&%TIq%)v#$y3i?A%r>w$;Fy6%>&v$VzT#!#_e=5edUT-FLrZ22e2wRVM$Cz;Gqm*99 zvsc*>T(kieovbh;EKct1sKA(}7IhV)#9|m#y|TxAO(QB*9Gt|cl7o)G+FLiyaT|3E z$R>+HD)OXU&bVywQnsV){YM=QkkCf%#ulnt!ap;$QFSVaPRGn=%U?2wo`hHNyM%t% z6W@5r-p)yq-8;~Y@=5W`sz|JrtWuQM@)}>$n0g(QyPoFY z?*5N#`WsRvraMn+6NFs3>(wsT@NE0{rmTEwCu&^Br<)b>f(&bA!P8Sl6bpbzI_geJ zv%u?HHe~N%Qba4#@kBKSSKe+h)#8dOsI>Ka<0H$G8t%-B-klQO6Tt1`nY0kgcaVNgr(;BT~3W`*cE%2>pPM5M6^5wBnal18XH|1>iv zx5MxacxElHK|YqOpv>MFq6l}OhXVDPr6s36m7eJ9>v*cmy=i=iOUCl2JJ>u7PfsU#HuSRFMcjej-c-QGfb!DL3xd6 zxZj?cosE`<|cspblh2VW!MwGX_$507q#0K`0`b@Ns!7=4)%!HeMB$E z=LSLvtTF9ywyTEZX(SQ@e!h0?SUf#bVq!EZzu*zt>@>{ioYyG%N2{Y*=wv8u9Zadj z{6&n|OU&nY3E+jlxViQsYcq;AB*Fd>A9(SQVa7?piAF?`1p_dCskTHu>8?{~)EA?9 zpv3~f4ojUVImG)t)#H8P=u!)5(9eNQ5a*LV>Y#kxfZOl|iMH*Hgj21C$}QxT8vc? zL;XF8`mSE8D?kuEPRRxx}dkcr@3qdM){ViIRcgBUWac%aq>C7%l)_$h#x_kRw z;@|VZ(+W9x-URw(#baBMpKT*TDsTs0NfzuQ%d(+O**_1{J9Gt+re)4KNo!?2dFj!e zsV4;?)e4~u=BlZ#MbU{TrBlSrUu=Vq9<=^gIQjIH{htr4*LHKl6Se;W?!D_d^*#1p zE4NefT@PBuo@#!4@$R-sgT0*L?eNibRA5^pN$b-ORNw5c=1+f7?=6Ph7W*=7)i$ra zlJ*!MozK@8W=>i;rjaV9x6r1)X=-cwFj&5y&r#hDp5ME6#;b#MjgzUcucJ!$! zp!legP;gTtqdQUJIY8B8D#QZsop5a^H&K=X4D24*d+dXu`8InrA0p9A<{vvI zgH0}D@=O5YhaR1#CZYnjeLXc-$zzbXejgxCyJUxNIs{=hRO zAnTZ2I;7o3w6XQPyGN>up$xV3Vci2t?V`F9!h3w@!|2?J2kF&+L{3El-LDw)U zP_@9=nMdBdfwd%#oq$GCyp-l%9!J|-?cpg1WpzP}`w*(*)@9Fh8#ebRPHMv8HJr*Oc)xLd?m+mt7bu5*?%n=ftU14FJ^#AEwder}H6%q5IIG(C;! zl4jkTT5QpBbnYA7hyO{i0)P7P$wu-JG_Im2DNRwR^(u&hp8gJj0f9DBM#j6s8LyTjN%2b56_Va7gyyF>i6^Jc)R~#65&q zVWUb?aTakYY6KAeD zLTV&%ufWv>T-c!3(f|TwJ#n1}0y*PZi=UtSQmZ=iQPh}Td@j}PB;;1XUVLb8a(;-+ zi71ZNXN=^SU44-Kf^R|l`{EA9mF3E;pG%mT)k^Qusy#I*?Gp~K;-vvVxx_p#)KW2* zO>gT@hCK` z8~Na?Wc`Ec^at-HPeC zg$}_Y#t2Fa3S6PR#Om(jvHO8L`^Tu0X5tY&`v8|hhg9Rjx);i~rp z42vvsENW-xk)~2+7u%N!JQ*YvL(qYU=N~< z;s_sUMia=!Hw8V)?M>(NuKs?fV6O!cgma0tS;FQO7 z#!s1F>COjO_-=W&NHa*rKCt2pEpj$FNtn1xR>1Lutnt>=d0!gbpqG z4a7VL#n?T^QfCaT@Ne^dKZ+!sYnfO#q4Z2ZP=$3>kJ-;}>+!eWOcj10cY-LwB_mQ> z&P1kMQuD8{b3*xAtIo=`2Sg~KG8JuMOfN7;`NVS(n>F#8OHieK+v~%XYf))>4EBe; z-f+a0)bA8yHbEGm&V7S)O*KI|7pKYZC&$Z_CVSG-FK%y^e&2M7W%uVGUcPG-BXs0i zW!|<(xW^$>%~(Sg#d$RB10@(99yXD7 zzlhMdh1A2cgC>9oo#-qZAgS^>?4qymc5|`qkkHHk#uH>$NofRSSg$wYu#2ztAH1(P zlly%{!DIOr{D+MpzR;R?e)v( z1jZ|2-*^|Xj~7;x?Tyn~stVH~3Z;DpO0!BU#DhV76@o*jvT)VE-7*={+OMiw1&L3y zd5jk~e#QN`pc0i}z-H$HXSUr~J~ZX1`q7>haS8dKQt;LACAp^Bl@Dz$_o!DXwP{Tl z{8i=%97;{bRZpzy*o2Jk#DVAq%xbUxQq$tm=}e*f#I?@Qy6uLo$ABWl4T{`?XE~g- zgq6jC{-Hxb*j8*Xo+0>RgEMLvt^C zoD1iEqX`j)f}WxR%e6Yk8XK61 z1;}JGOHYJWTldzdEjPEnmQV!^!H(uGV?XrHgzcAmER=#Wf(m0)jCS+|Tr5~fNhgdn zW!F7`&BN(EPIoCzWARoq`nG}|->8pCzAS5%mA8vrJ-KYi_Wn3PGb2$EK4A)@R-;L7 z?XWte{wNpTX}|rDcU&zZ^Y~6Q$Hlk8Znhy@y$aK*?H@VsgN^tS7v7DwYhR_z)Cp?n zjd!!#JchY=2yOM0%O5YdW;kq5CGt#uX?cf-_8oYSp8zzBr(#y^?o@c zTkV*;FBDi86u=#Beb^vTWId$jX4tEGsB^9Z@MzE%wuq6lBD^8+sw%nyH%B`0z_k>4 za{A}cnRVyGvRWFvSsv2(;EXci+KSuAaptR%Y+lg5^A1G$#*si<1D}%`dOfJyJVZ;- zP{rFOcR(u|Yb>|SsZtz)K>e106V9EFO${zbC*Cjm>-c#O;`Euc{z9EPG1w88G1epP z1==;oqSV(4t3i+3`whM%xFUuBmY`%94D91ioi$K=??a5&1}0}!sK&sF>NEZ5@8AlR zQnJ~FH7;WDtra`+fYpFmpQmAXC? zm#U1B(UKK_$(pY#FlJPb(`FN)>sO_H+{)1QXwO-6_$RYhy)-Az)e>e{TFTvT;+0Tp>75yclyd*^!b`xtR)@2E~vD z3t_be>zXN!^5M>n_h3Whq(J=yXx#>i6>4~bFcTvKR?{KUpTx6doNjb%dTqF_CMFw? z9Z!DfWK4N&uRr{_V>YY#)tmi#6Fp=uh|&r0<~$pzN(XB(jG_<>dTI+l4ZXP*znL!0 zBwcMs=*zilVk_5WIpm?F6z=Yt#PNax$27W%y^E`j3nt#zkZRmhb!lx?!9m?ko>qZW z>&lGe3C^^EIf-{!CbBGV9Ec53t{1^J&DzFO=bQ1qn{n?#D z6mkULm_?f~)rzdc)}OhD5q<_w0<}4TLd24>`g|70u!fpawICnOl8ov^aD5m$`@Fs+B0)ESlPg3Be3_xbOgbC`)8N*stTkC`$S7!m?O z&^H1d;v={L%{?3Sa4sboJ-CLp-*e#G+|5iTQxr6VeNgiUJ6u2*0C0<_TWbj3qIDEL z$ck~#t2qW%Dsi96{+xUz2R_%bB-VqoCz@$ais9mkZ)Qjji!$uGQ;iwZ1zmEJgZ3$$ z^ZXB22aJWN1O`&en6eU}6-h#OEhvJ054ZWfhOFEIej9C3m%y(w1g0PL%^eM@BfTTp zX3e_wE^iyem+%8EwCGjmy|a(`+XK(^7%#J&S9xi- zjyQeZrjVlaq>eRf_k;y(a)@IzivNpPX0PKB{N}HvtEZvU8#Fcyxvhx#mN%v`c0(Ac zEV$%&N6nj~bps5b3~~;tH}`m5A0SADXnKXV@3lLd<*-Z2DScd`c#(ps@6JS^LYU== zloOsm4x>)8sGHi98jZFf=7o9-d^halAQcmR6Fv}fb8FM}O<5~%tkH>}j?HR$U6Vs^ zOf?@z?Nil32^Y#<(&QbL)zq<%*<-Heek&slcmBrT)oJ< zd~EDU5sNH6*{3;-C-LnUvjXqVjx-*ja?8eCCWO-j(>wRu2~Tjgv<&H=@BFWKj}Njo z>N!f72Wm{tCbeKM@^eg*LkL(|2N(-b`uiB!<+rf0j_Zq66SheCyU0*1+_ocKhzvd% zgL|x|2fPs=^K@oJA>dGbC#ne~le^u^!L|R@IQ{1&=Z9tXpHQ!#FTjx^A3Moi+Kc-4 z)sRViu;;pcm=!rfMT{mA4PBF}{;mr+;y+R?6>8`xp*>*i-7y!TPY*1vRf;oh;?GWk z4xb(AG7=L~dkqv+^h`470Xod13HALPPuXX2mplPnbUs|f0e40QLnTAC>F+(R!F?(9 z!`F!>sRA^CDO_eiu@W5z3Jx7k(KJE6AGvA`)Ty;>ctF8;V;ty zMIP4+0r`n^xDo3vhmUiw-{&_47wvVus0h8TS5%&*oP1@1XwH+BBTH_Z!7sKoiRh0| zF;`&DrXND&smYCJL@FT>L)8)n0ZyFPomt7sZXMD-3OI4|Of5^809f%!V69FSU$%O2 z389Di{LHh+?4w7kAsy!f1Y4k4cRpmEZmIhbHr6NpX8&^J?8xGbXb%^Xrx0?*i<3=R z&UMVrvy^W4Fz+aJc*ogkHZrS^wDfaP3-H`q%u)(|N5#a*1fAAgOU!;{c0A;8HZJP^ z0by*OPe`GuSit?b!(?8gsoer5Ae z=Qj%Rteb<_4kv)V+|2`w0It5rY=jPNDQ9@lYrpj4RB_JUNQE{vJzxwp^>0oE99*BjJok?W|3{0U4;$JFcuW}$-hE_Oi&DMv9g`#Fm4aNq&+e8eK zR{V#o&l=t-1xeqlsliEg>naPmG~qV$6~9mrZNH}Z)Whu3gy)P5q|gAj3V(kIp!W|h#C>A|0^<%v&U#&8QXza){kk}Ks&{Hh-m&i zm5HWc$kHbwLo$-#*~Fes8b|>`Q!)799l}bz^)*xaj(}xpz2bdzN5G0d+EIUbN5ERV>?T}9lMF)4rpO0LhQ;f^MVX!5ky`=6G=J}?KxnUX0mvkimw{85t zJOsZ(V;5qLHqFLizbH0V@`N$rvepMN(t44=mq4T%KHg8m_f3$qg6S z_m0x!GJ;DOzm_jI;0(q)GG?<;)r)8{p|u!A+s1sVhXAB>9)9G9vi$`4RLLJEtEv5( zDLSYUmi1WLp9FELy;6F!DxDa8!S8UOTG+xShaNV4|A?UDB?LCTkT>Y8yI82<1;JUy zz=iK)=pBjiL5qW0e^*f6YY(z!30r5XS~+d~Bq%f(r_#1;$oH)F4hkslgebZ{eXL&AnzVxSt@3-Y>?>t_J0SCf(UP?%i|Rg1DkndnGm@+D<|)HWFfD z&I|rx$xyf|C63~u7)4k5548J_w1)%Y|K-fK6Ym5#`cNObN>YUaqGIE$TXT)I9F&th zy7^VQ*X7sJlC?Wu&aNVvP$w7vSo!2Dwen{=Va7- zan&t5sg3jC&fQC)ni%?A-Mx>_ZywHfW}+;!mUd%x1wN(;5s?YNR%=9`0KIi;?JDG$ zWWNrUg}nEzcQXjiN+~RiDW`zQLy`Vz=k4!cX0aJ74~{pMhgLmm52MLNI!E6?G{`Mx z-G&BdEK=wmC@%lNtg*;L1sV%DRJdqCD=-loHeFcqFv(T zro(mX(orgCW~WAAL;1Z3vI6Xn&79tvBgn}ap+*!oPWgQxi`c^*!kXEq4}_N-gb4&6_iCVmV@6^ zP=pUtIPf1Q);Z>_U_g&Xch|&6QAhVk$HG8IZ#qe_?DnF?miE$IoLY1&Ovlfiylf~a z(`DY6O8t+G=-wUvPkUG~l%CJ2v1_UDzEQn1`<*&JH+QqX8+B4FoV_^d9!E!dSm8Vy zl@d9!JEggVTho&7qed(wSYTQ;#y`Fs`mre`IVKvvm;$v^pd=?D>M7Cad-nK;YSe== z2u+fbtg)?p9$YK+`__cD?6?-V#tu^JqVJqWL09E)6HwLxOE`J@NK{X$rqlQn4=>y9 zZ`Z8G4YT~hSozOgp0im-DLy2O(2wkVq?&P!2@iZweXSZI%>%@WYmi&~ zr97exM)oPh7(Ppcs*t1|p=dkFSXWHp1XD&gy2 zr9y@ttjse$v`V`H5}U<0R-dSl9~wBH@mb9`U08f}pQ%A_3PbC}v865a^t`d2vCiu% zdi$rJ(OGGRl!mj%wDC5f3Zb2HeKz===>gw39fL*;!-{Jd6}Ww7fzZ2Ggk&C>zT}lO zaN*c>8L-Z^nR^wmfJhIuR5H457v6iF#uGC4g_#W-3q{RIkc|ne&ItFNCBw0eHu=wI zZ#i!nLVSOSe9UUd`sd++05`-xZBb)l%z~pgrHU|ODJF03!KCWONTf-sQTTUFerEl| z&#M04%Z9G zD{r|>)@FIvvA)Izw`-Qx_DrOu!yE$)$Kakr!JrDN5C+lhm=GOWhlujqV@}^?z(idI zn{zK+TyaLh{3m!WW$+TTN`OzCdyM-*Aac;Ak=}Xng~4RRtQ_@F%*3z74|(ZmL9kjJ zf)J}QJoFH^iT=d838KT-7G^WPCZo{!!tk8P{ML1H`1A15lf+NYmaYz^=q@L!`>f<% zn6dJ&KkH@iKZk=+$FJCU8zw~#4~{`w%t@vuBgA)oo-r+p&Nh3)kIiBHvAA9#Xg8^(d|{dXQtCl%kKUx$2ch4H-0V)tkrxEJ8cv1!<| zV{h;c{YG+T$WOnhpeYrd6p&cY>L=qO!1S^b<$G>Xo3fX7u8j>e0dR8b4K+dP!mcY% z(BzQqdkXPCub{vF4m9Rm*gC-7? zsWhZX=2^)d#pnQRwkER)fU+Jyl>TiRZ51ctVwzHhE-C7paJH+vFLS7()69E_%BH94 zQ>8G~sR~YUs#?C=_*37JbP%)sXlCON3RwcPuYl) z0gykvPklwEBtfz{lnYVTTDyTft1qT2L6@XNyE$aX9_^1?v7D%H~ zVD!&B)PAg4UKVSp8LE29dNBy{{H+O3#V@qSu#w$G1Ir|_zpxh+sXZ#?20DU&;ZSa8CiX{BDt>%pP{CCKV^m<==Snmp=Q*;-`W*8eKC-1OIE zO6oIeS0G6YR8#q(Fl=sGu_FT&2}jlBpXt|Z5!2NmsM_oX8=occb*?Gf_)ff`yorV~ z@YE_hDxs1F)VvHYo;-Av78P`>SU-L@In=4^f60*FuHouoZ1q7r$cE6ftXLyPG=dP- z^|OAQUParQSDK!!W`)&KNC&WeI6Zd3X*DV~5G9EQonQqklhi(|1gA+B%PKaXz79(h z!av5tV#$57AI_UjD5MMx*3ys4-KKmC6=hyLEv5Ed67*{k3=dWbuiMx@v%lqi@==y^ zJL65~wGh%a7vl-s8?Q2>A7CEi;~(3|6NhS}YS3k`zYml(ccr8f9%v~^*125L+cRnu z6T{4zIM(nJRSux&+RL|`Mo1^nE=|HSz8us%o$oBG1m(6})2~fswhTddiUDrQ&RmUH zxFR;zl!#uOc5h7R+m_yBTEmOhMNR8U35af(E(s5dW0Pvws2eF7xrSowe^XdEIA^Dm z6fZXz#zLTFYgcODs`!BVN&B{@>R`WqY*6%mCcboLs--E`y+^i;#NTLlR0l^H1?-xJ zjkiVTWCwErzmEFVubUJ;S=Skw-ZJpdc5jMVWnz(IsgQ7xiJ?`S*81x7B;Wc$HPdy< zyU%8mpS1VTcjCm~_8ym~RDqrCy(+c17RVU_uRg(eeY?JB+N`x3pcsAm&qI%?d_z(-S>&{U!YH6tSY zTH0xgw1s_l+KNvGL{gA%%l_}MdeB_WF^oqAEb=+EyuM{GPK! z6iEzTsG+M^{t@JNcAW<+ocT%!P&VOp?bDY2NLFA{F2B~1`>0rlJry{`m}fxU7@p!| z@n;_L8e$YjJ8@|TAzzr<8_x*^c7|AjWWg(QG1-Ea58=Moe4sL&+uHGuvTMLjsdHs; zBC-ucB**5E;pCVW%-8vS)kqusw(3;BQA9*7cwMxtg3AO*%l)R)x5l!}L|p1DWJWxA zfV$M(4OVJlhzS~T}(Z{M-I<~^(j2tzX4fs^O zjwK5=I^zVK;)e$i0oQfn+lQRLSUfnQDt;BBjw0;Z)QbG+7c~$9s;A?6Rh<`6jM%I^ zi<5u_;zD{d;1PwzE@J#aSxnDK_57qv9_GvE2x%9NZxqHmy(&0_C_sl}piYcMJ35*4 zuIPpnQQ1Z*dRH1w(up&LP3uI1e@+P(OS=3_`zmP7n?A`0?!+EVY|6eD&f(Aq zvpp+%V6haI>QejCNEI_oY7EB)Ox8|3BX{$woRn)y@{Gv?iUA65jo}JMX!bMi%&@5Ye3N6wuOB#H zFPx2ArtK>+i4fqmm@)-QM^FkMp8zq*TlrNt$jQJgMw_ zmplV-S-pJ0Z*^X89TT-;`zOWfg}Y7aUx$wx7yrV#IoflgD5)rX*=0(tHFo?zJeL>a z*%iU+@d*$bh@z23iA>CQHb8~1ToC8ip_#l=sTS#+Rn>`7rF|xhTAj{}L@Mhl6V%$w zq)_Oc9U&~7NtXAAh=s~nvyh-rvDBDWDjw19`if%!#B88V>5k$4Pna$5V*17tnN_-T zg?Ay1j1?!jm}$*+JCUVFTrb3)%Xw@XRph9xD-Pgd0gm@vdAk7%t8#%iMpXh<*+`&V zKNSU;=gLcsm85JX?h)c(dNZ~;CjcOmQRc=y)I+S``bdZ?kilkf*x_K&u5!uOsWvJF zIJu`orH9aj%HQ|m`rNVdh5dPuWJm$X4Ed^9OiL&ylA$Eh!MXxBU!GeVvaNA$YqwQ7qipQ?Ojeyr}5v^s!bp-zp? z3Zmjd9Gj<*ZH8nP`87K0G5VT$rBrKK;C9v{4>EME17;=+pY{5tQA@p1kKIKYHk1O# z>v*6F125WMb&f7x_!cQP>+5d3LEG#IGrEsjO4qQ@XICaYi?cA5@op_8e;AteR0*JCcUV4|kQ3Uk!eo>)Qd05h< z5x$S?hJu*xamT_)CzW6zXS-Tb*%U$pH70<7EJEJwE89BjizUr3Eaq@(D=tzWn$!zA z)xAiJ$K+aaQX7|0`#mC3qU44L4gLBQG5pG|36(-`6rhu8BvP1u_|fh0$6$T@WQS=9 z-ta1}F{+@wAs73zs|mL-$7aujIsdH8)BXkP!h~ z)nHT<4UZb(<1u`C^=J0e@l*EAafe!0!+~3wx*Rt47fL}2)IFimlW}oJ@fcyEpEb`c zqZU#+iK_s_ZG|KJg{*$kg5n|L91sZcSh4nUmY+K-GwlxfMBGye+p72WxQ0GZX?-@e zzgS4ZC*!GJ<8Kd?r&(9M!xab723^erbD_NzHpvF$XHFTUjgo*XC?9*$SY1U0cB*yw zMPKMgTj{4DVyRwmpZ#k=4ri=I@#W+bpE{Y}znZFvE|ij+P&N__GgKjk2_*ChM*>l* zy^sGK?M(fa=!()6-Di3Az9#iFzOVC-@QJ*Z*;l%E|ou=(sU-@3KD5pTr0|8uVW2^|FqDR{hJ1b(oYSW zOOHMj6?eEN1IDFgBJw)~Vd?~w!TIEHw{{fXXuL8jm_(!r4_$LZBppnn?j6q(3Nuz4 zIs*_z;DEe%Vl}XQe5Qj-9Sr5U@Kz#5{j~zEq{0&cP4YuWW{S>2)j#*{7ySz$`xo%D z`gZP1>crDu=3gF-J{HXW7x3ZdtB8LAa(RFLVwM;_5BV2h2F}XMv>bNaJ$!P{)S~h4 zA)CHT(V~TSH-jA|L9d5)K2Wnl@(A@m6w5-2dtQd%J{C2ouX@Pm*s~`yRHiM%krPBS z;QHI0SjRdqb#od-`;R0g_n)PMT=tr}v*7mEd?9laThFJ)CY4fQ{wD9x(AVIG3;}@v zv1H}e<#QI5uV38LvWarI`Td7_dS+7Jlc~g|#`uqMg1S6uk_zWb)AEqh3=GOR=(GIY z*A3@zQ|x}zmS}f=h)jBM^DBW{OVd>u)_8VheU>{i-nXrly~+!ygPh~z#&C$iP2{WJ zK3kNuscpbOZm2*J&|lm?b;k6A_nehqkp8n-M+p9nS~D@ zX9B*sE-7k6J`epX;@!pUcVx(u`_I3t+wN+_n?0evH7KZlDB~ldk0zGEq1m8M*}&D7 zc!M!8pO&-&0WU+9f}yVvu1DUWz}6GZbk%*ulPPrpUdBa|QEQzqCAe2y98Y&u4ajgN zi#WspHL$vCO4+NaIhneOm9z8+B-Rii6xT4b_}M&BI4jw^>kj$es}`kFLZ%kA74FiS z5C@X#2tVkX;K#CIavT>QS(Ic%8s9-PQkh!4GKW;AiaKBY>drcUbd4K+oeMOqD%9=lYSbh>JK)ex>kTInDp_ zanNn_h>?04T2==;$vFFm%7}c&VRuT?9d_*U{D{!3y9*u@W~CX-^9Va73sHSxNpA+e z&SUHar8MLiRh_jE-q$BvX>PZlLbbXs8Yl;vv#TSVaV&(9xq;zq&ONl?DK1OvsH?aS zR^(i$fPk6H1Zoy@yC-k16oeUmePAQhj+L}#=#n7zMMDg_<4tVCAF|pVROAK``Dt`E zPl3!xxEjLQQx?($FYP45lL*IF$DnI*pQ(Y3oRzC%Or5Zueyf1M!C~burvBuRgae>V zfUEI4^w7G*7m=Xut@`=)=9z8p>ZmaHlp+GGZq7h9%JZH0!Zt%W$^CU??JApk89*yau>O(lyB#?>M9=I*)Y< zkMwhdp-J0QB(EA*xLe+=?4hFEpq!!D9y?6F&6*JTjpuyF<_++aZQN^_UwXsN2HkKQL2oaV9~wKasml=>EEE9b0LBUCoI_s-{(F)6ER({a$rm_&PA90oC<4z7Y7pByg2I( z@=qA&T!r1~1G`4eh^1HF(cBHpM|>*$0ZbO}2yS5zDQv!MOvs!{soHC*LXX`*_p>As zs)z2|jp~~3d~*^}{QPO;WI1bLHm1qbDpZkqoSqL@U!`wx($EC?&&x@qIal)PKNKb( zRM;&k&AB>7?g1Q#ljnq~1yG(3bh?ZmnGT7qHjNHTfw4rkff6{D(K6iTY~QAP)5^}I zVgCN%-XiH)@@!>%nZ*dMgy}`~o^kBka&PM#dL(qj}1r zspCF{SQn9$5l4H-@1;%6a#%LK&X0~QdpT~wn3Nx1oTc^hNm%Gbr>aBcC~?)5$zLj@ z=GLkbo03-2n=YBm;KaC5@*gC$4$aAU3VF^CbeYsNp%qHu_eWUb%KaENl74Kw_=2*e zF}5k+@bLB^%=PAH^!B)1-2GkrTNhl(uYlaT>jnF`|G)&t%@nE3BsBB}NoAD6bgo!46ikxm*GrjpEd1!lcc^u07NN_OY_s{;g-L4hN@i!It z`xB1vYcA=g@Bgd?-?A=mv0T175pFy#(zJkGgi^Q50Ygkhh7SB4=^wFzC5Af1g`%*;&!hQlgUjcK4*@P(RlJAh>h1{{W|ep1O>&;~5V(zr;oGVqg z-Nc}0xttzo!K$e1pPZtlG%gkA6a#9XQ5YOKsr3Ra?1XpN+iU93YeJqJ3)DO^3Ai!O ztg9r5gi?0ax@>A2TWHS8hYUE2$7Qo1Azaf6=2p&0GdspES#3*$4%Z2XW|KsJVN$(# z&vf%iPj{8j$;R7k;ySw7cH_OnM8W&c#rf^o_t|TX29BMCFN|C{b&ZZnoaUW_)>Bnr zI4_}OFxevOr>j6`B799R3Rc{(6NtG04nPt802x`ik+-!+!ystwGoJ{NJDaUOM?h zZ8Nm<43BT$FOTS@b8C5E33A+2p>G$bQH#iap+^HhU%f1q37ecK!NJd{ z^w6|~R%iFpu(9hYi?r(}29|xlQ^RmV=N;*8f@_&<>70rNL1prf&5C4HOWO=2xWtR_fB?`jx@1IgPcf;p9M;U;&wlh3qk9?Fnt|@0|-_Os6xu#|3`> zyx*@J{)m_67fOM{EH;4XQQhp_7bwP(wuE7>Mc?Ig-F%20B~#K?nd$P|Cq3$103BD( zMu+&~%Cq&(b!v5V|F9^mWa(f>Zs1!G*Y%@t(iaht@(QrdhF+EvFGZI7DnT2u((A

    T_?NG3%gcqJrDS`jbsy7jounJyqCrM&(*Wo>Z&-@RI-z zGbhexxU^2QS(SWKVcG$QLN($%$$I9xKnz5*f{ zUK&c?H%amV*pJccea$ExBfv zO)W%%$I#g#$IJl4fV;HXY*tNhdNEZ_m+ZG9ulq5eupb{@!FlC5Fqa=#-nqV|Oh8Tq z?HC1$(wNgAVcL59uet_>0V>ko@+s)i*RwKj+B-MC_DLss=tlkVe>8ViL2)&4pXMdFySwY)Fi3D` zkbzFVn4^ZP#!t!~NeyAGruU><7-gYS?bwF&I80lqr)(&NnD+U8%eWI1fA;e5+B=ux{8 zx_sS7U>$vghP~%!K^oKRC-Vh@R7PevtzwZ*s|5;AU1Fgei?nj{8=mY=(1n1gG0>+* z)22@3WkG2bSqahv;Y9SVWi6xTxSZawr=_k_gS={m)to^c{l_Rne^X-_Sz5YufJum1 zQZkedhP>!i>_fSjXLqEfx7w0dYwvnKu~`3$5!N;|yky8FYJ~KR{Llx?^8ceV?uz}K z$?f)Zc8|~AH&0#Not*AGhv`;&I%P{dWdPB+dS7>o!(uSiW525h%pI|C=y^5kQhlMX zrJn(W6PSLg*rfU?SzHSIg}|A9E>`I@1M%?m{sh0@c*jr9*UlypIik|1>|aV;26)bu*n^gS|0L4DZ#_;`XZCVlJxkn<9UN z0$z5Jyrx8L^T_9>^sKOv8Xkp2ziTX!-Rz z=yJjxZm}EUce#9sckZHiV1u_jSjtlL?$NC)00bRypb#bmnxasD;<^&4{4SpY@kOw+ zDs1FpU(X&dOHFr}Vt!^8lrNsCLiru$H1@L!^Y|YcW)c(2AuEzarJt;feR~h2aeGy` z>&I9#HCWFum`xc&lDOo{rUGbf7DOTd!&>`c9sHK3k{h+Bi|U^sxp>u3z3fL=yQe}M4nh~q5lf?_R)!g z4ps$AE*f1Z?y&sN_SZyzNh6c3)us^f)nBSE;Rf-yZmo&c1DmoAdvr)wp`gw=qD-H_ z-L4&#HJ0^3b|b;qOn+xQ3czp3m#yFGX5V;4hJ&xVgTtjs7khqB1b^>VD_9R?UhnDo z+V!4R(DKyO%^WCXy*VXPg89vr-khax*`&UYTj>qUK#PHF%cr-6qet9@|oY) zzHqqT2_8Lf-R^f}nKUIHXtLems7}aOwQk+ZU}u#>%h0lV>p%eJZ?aF;efgjBH!mwJ zvI0Z%{1-t%=5pYa7~aOljPH%c8TAxrI{jMO9D7d=*>KrIs0QcD1VtQscCEa2CzGj` zHz)Pmky7E#4ZF=r`6*%KwY^$x=liB(pT2?C%^+pVjYJqeB9f1U*7C#=dhAW@Jl}$m zh751u?c(CsYVE<431d!W|5?egd=#pZ4+Mr7u=#4<;QM#%tUZsSspk~ae+srQj8Zwy z1aa=|_+&^BO>dZ41Tg}#oECYdRIjk&SLqqtFLx^@;U_m^lbv!l!RVn*SnYs(td1mw zN3;NZDm}bio)YaVddMGbhxx>D@G4A%*PK7#CSaaHbG!>lKk31wUJha}U+!f)3(5k; zYDkqYh1;W^OeFK1<^&vZspiB)wYAj~u~IPh5{laI3oX|2 ztN?I9J&)5kmH8X?Yev`1R(D#q8*?2hFTd~Jx5##av%(UXLAq>;lNry}B1bS9p5kZM zh%^vLNx0CirHJ!qaCTojPa{AAAmKqvMrOWcS(s6BNis=k(u`8CY3E#99N$cO4Tw+m z(m7Y-AOZj#nS#bVN4&axhkLa6o&WIb=2l=Cbq)4w>6bI~)h3tuafad@?7A~DTE^xI zol-6jj-_|&Jn-TpUC!la;L=o}ycEXv_DcVTjr!&sbJ#BB!^?bK`krh6;4SA)Q1HT@ zK;vb~$`Ag3E-6q2PmkMw4C7cSlL(ufN#H=GK5SaTC~~mJlMMmp$0imu8RTxm*>&b+ zr4FMV;`@FK=n5c@FQkHvlo06gZTciVh*|&+-<0LJ(kcGz9uhKYB7yBTTcA#zl@3m# zRDH_9k*|;661&lW7}{^%6f%Xq^tdyuo)Z$Br>awfHUY~|)WOyRY7&S*4FZ@t=wf%t zC{AQ6F}DxE=^}Ec+Dm8c>OGJyRKZnsd|$2Kj_5QdF6FXR<+$uStXROxuNT@oN;HmQ z3_Vt`j@T{AQ?j|l3Z~9JpXNx~IG!zfNdKdhKk~qZ`?0piR5md!b{1o14UtQ)XC!C2 z2YZeKVpac+X+_%4jce&+oXotj5tzaMmNNLNP~8|zacI=dfb$n4vg$2|m6P{kjOu;j zolNo=bk%f2Eu*%MKnJsVS6qAVA8j*%Xg};*Mmyui2;N(B^NGOyW=_!CS}J7IEqg`z+-NH zQLCv0vyBc5^svU6q&ha+m#slq4$*c=OLoDv^eB*Gc{*scpu>3P+%E&#heCDPCpx(; zG>Oypnsp#xS(rW67%wni*W zFl~C^?qL$fo{Xsa_HmK#Xc*4{Q%euPzIt@QEm2pqTJx>yFvCW3{xuFTm`Fr2m;mO4s6%9L&aH&d4Y8_0SAqDvZvg1h(9#e6GL3cos!9NvI zIEsh=$Mn#v`~R5TcpK|R1SHel_L5664tagfC}pgp6!*(T6G&`3BXG`KarlyxbS15` zt}-NhsdV?grx6I?Ya6HIx&>oAUheRt*0k^pk$R z@AK2dy`re|_`k`m`9Ia1z7&m9mVAK`qpK|`(e4<7ydsQGWJsx1(6B3Ns+Xt4sIZ=x zy4RH(FaKivW>lI!`*ZR9KXTZ?zS?^nrD~Y2ve>HRDu7to&rhg87?0sjB8EFDQW28l z4g!9lnRhnUs2Br)HrYl>VgEd?sl+)kGnP!0slr5snaKFiTV#=+UixT&FE#P32^{#9N^|CYM^I{ZR>W;Tr=T&2uGz>U83h zNy$|U`Ra3xu)cV#!rvCh$6!N8E4M`Nk^ZdW{zP)=$I2IfA(?;sn!xzsZHSMB9H?44 zc*CWRLdM-xrOzRAG*|Hw#_?nzh89UpRt~ruDcrj%GMLdM4I&4xRL2;6v1t{x*HV4s=j+P+F$=r71(H*u@BV zhDp-EC#;}>y}N|474#S5#k=8M>F_@uJAW~bv{=(uPVTDT{KY6|dZp%Czh9^H2kv)A zT>LTr5%qZw{;ztP{FWpsV$>!GXcMtHoAbcmIt ze8-`->VVL0{i66JU8nhY$^2mjHYWNVNvX3EJhD##bb~S1;_OEq$)>)&5)qQ3!UN6e z7?G;+OJ~QaE*<3)5cfg%?eVzy=wnnuD#dga!GAIEF85f!yzvwx#S(5ij1| zrG?AATnu9Tt+scuaQ%kn<29RNZS!qj&S9isFam>~;J4B+DA@k$YzBM@D zDow#98YTmuR=D?#Lj3QnT|Z_x!_(w$$k*eePMtBe4$W$_g1pA@7AE;8=e%dYtkD~J z=ROqTZK)&|`(cQike^q;)F>3N4W$(%_McyAa__*(wvp(oon+S#&*P+{=84E`-l=I7 zhGqXQ3H^()Fa{xUtu$*Qa!2%KKB1xvQ&f%PWw<5-QR8C9Y1Aw9f!Sm*6B%jd#EPmp z6nn$u%SP%t#)3R2yk$EHsen#fw98wu)b1Qo1uZQ0SntfylcoHC5Pl)e%9RmFk-?H5 zDP%+L{$tLvgJ&?uai=UV4SqIM+bp2fD?_FI9i*ImTxr+!O=gNDLxN8S%)i@IZ02d9 z*>yAERoS!O|NDo{_S(vjbD93OG!EgGoEPdW$cV}%Z!~WoYb7<6B>G?AfOt-7rz_Jt$fc8^r(E6#0wgm9HCmvnm^U# zPpoy{YgO>fRtl(?)Pxk>nB*d7c4zv0N*a7LhQ-4qNP?K@-%xf8Kt&QA^#+6!s4W&+ z!KVnploW16CXS9PNk-_#I%OtMN58Xz`w5BGktQN}|0_BKP*!cRjXCNxa(WhUbGW)d zJ;_ZFIOeyo9RJ-1dcl0=?nLQO{FQ=2A&!jV`iE1(pb_uufg+mWK($P_wq(Z9`#;Zz zbh9l8{hM@$B~k;(xA}F_&t_E2a6Gn}bYYK$wdzKO1Y7IxQr`-SHs8ru(8?=2@9(Bk z!39I*PJjebK+6gflnGzg-rE}AN1Eo*!x7@v&vtI2<32UwhsFH!8`7MQW^)Rbe=%mF z?%Sr*nM&G+t9* zE%ozy?c#Q$-eV@$8PR^=uiIFSKP$h@tv_bP;)GEpD_NV`iMn1@=*DumFt=3 zhOu*UonlOhvvr4a=oInxKl(DWG9_e7Y7XAmLvZ4qXs5SS`t z#zJJZ72$U-U9r3o*nL%A5voVOQBttcct&qfk*76oSx<3orLrM`&}1{SND;&r@3w=b z;Q=hskQt2MNLls?99CEF*u$58-n7`Szrl$KKpC>CTwiZJiPe-j!QosSyE-HFm<|HQ zT+U;qB?64M`Fkg=q*StFrWR94*)`^#bP=?UTV;cwU0FFqlv^X+JqtjQSe6Uy65Hs& z@cyD=R?Ds_L3Z+iYs(Kp!}HDt0Bo)jD#&W0e#2_Uv%|gJNCJMTxE;Z*oXkD#b>3K` zk?gi~*nvIbAO$3Egp09Xo#9WIRqs@4o*yzSl~&y(eRZ zt~{8T_qECxI;z_KeI%Yc~fS6#G zG7^@qC^k!Jp_VtnyM9QdjSRt-K(K6a2?!|PfsQL6T@t$Wec2Z` zokqAjY^$1Ej$6{yY8eW`Ym~Qs$XYb^C4~#%n|x4Ye!bY$YZo_nQyCTeCQr>tAT+)RxyrAD3#dJhIY!re^-Z zx>)h)+guC!1`K~#Q(p2U3kawwu}TIGXTQH`1I_1Va4<4fi3k8#1v1@`)iD*(+`KJ= zk$U0>$5Iy?uHcXJiqC%AYF~Q(#ZY~6yr$%eW0yRDi03HJ0-(%Xk?1r>i{({OdF)L- zq*_OCeF0AcjLo>n1qPR5)>crrUkxCL*KOJGx^>f~j-=YR7AfE@mZ|TO5nYVE#5!$c zN9dzMa-N7ol_8&fQSd5hYvW2iOa58opp)MjgW_dA!?L&x`vU4cvt>~p`*7M6EiqZL z*fAGT{B7$V{bjPS=rT57w%_L`$8SEL`K;%*qWi$nmQpc;bj@~|SW zYXH&SI0**&Bg|omWPWkF2E~0YT2e~Ssgt-Ge}7@!(+$?l@v}2Pi{22$q?9{&`y7?ceZ(h_l%4MoCM>-4nXK7g_~X!oq#ygP8Tg9{m!{6Lh2W zCG@M{i^9^*MEF>R8d<5`$UIY!eZAG?!mDYc>d$$jF25+fr{*X+ zd%mAjDxWN@rIXWa^8kf1t1WAnK!KArE=mfr;*b|K%0p&)uLKz}V>QYA7cdbL?DD39 zt>>@NKImG4{S>r-$VeE7V!>mjp&IxXllv4X`;8iW3j=vaAdap{(=EIou5|nQ6Q?3RT zpUwBSELa{mwd+~?33j#eJe_r=uKEy4K0X3!@j!-q|9BtX$!n7N;x4Uep|W&wg<)`k zg|FFBKt|WUhn=~mT(x~jy;(vl<;ZCacs|*y%CT{V>iJ0l}^fZ?Vc1LvO!M~|H=xSC*kUr;5 zz0=LGKiSUH^PXQir^+HxFM94jWNa_}iN#%Ldo`9WDHm6I2263PS)Ey+!}sKBGMWJy z^2z{^f#QNf(3&-#vIGOH0t)R4uo_i4IjKughP&}ALjRIg&m~LvaKM|4Zv|3N3;Jbx zCDLr2;Og(pY?<9Te0&+VXJCnR^)d;?8+^}O=mhNwf92#?JCkSrdyyZON!iYT;gilC zc&^42B&j2gEHmYs{>W%$Mr~RPgqxZAwpdLw9#OJDxutJL3;l}O$)HBxhAlk_#N<7o zK-O!cd55bMhAegBE0Vy7@cQ@Vtk0zN2UW4=;%vEWm4PheM$O_=?8fTYg%^7?_%$6_ z+NAig(_c zW?0F$W7U{T@g@PFzjkutgVm#spBY=O(5Lxrat$pibmfRc=B*1q6L{0K1X|Wr1GS?L zMs*Yd_nLvr0|sjCkZt*qd=Dl#0}Ic`AoBDQZ}kjSyNOQQ`nQ1AJdfG_HZjQ;8m1#z z`UevS@C;qY6*~H-W4TAKDW32@$cP^&j5(Fp@_9s*z3K~mbFT6j06`zA55L-Fdl?!uVL%{?}L1z=z(Y0 z>XFa$__M|DMLt}6#9~}hH;<;UCk+0XP7f z0J1#~)P^_V!;cyNt{zx0zERpeQ#DcCmdGzNe z3tn99=(H(^4bq)oa$kg*(I%(|sTl5=s^wHG33`6IC0vw>vT5y-C`U=M6pXY` zo2n#$ETRL3L!#ss&+U*6ky1ndO4XU9L(d=QfK^AI_*Pmv1NwDFq+-3sT6M+dzK>~! z&U=-`&2eDA+(PI1y-~Z0JN{tu&GvCGy!0n2qCOhZZE{t8*LEYnNMe}g-}CH3@ow|( z_Z8wGg!zvvbs;|l*7z0(x&Jw|VFhuaNlUhjC7%}x4xjh3S}IRBPW+|#<;Cy<+JNghJb?P;xU19)u^bjX)CIe+tmLjH zeqm79Yh$lUSuH^%q~pWXzpj8UK_f!nHuWZ_oAS#2iThFA-b$LT*q;s5P{IzS3%;r6 zR10|>r5Yau;{yVaFQteIW+nY=NJ?7C%<$}&R!j&Bq+E4Q#fXWM=0Xto_Gs~`S*-kW zOK%#PAjxWgBc;B}k#?%Rkm& z-@nu|YIJNA~Y+S`v#sh7&`2m>+%ItHMYSh?ItQ9w|JDtVgZhk*qFphpvS6fNn z=>3@~$H@GT{|^aawP(Zw?uqc{$*r|d5s{-{h!v7B{`#BML;%8f2vTvdUgiI8=TO!Hb8;bw*f)F_|faQ zUC;A0h4~;Ie9poWw5mgtK=FCbbBoeT*pYdNSdbWa(1^-veagT-aN5gW_}gTYvnOk1 z$~z~}M0XOGgDMmXWykFC&(wL!5#?C~}2v?y5NXz5fcjA@~e! zVs~jRG*`w+tYNG()5XVNy}98Du9+sa1vL1G>~~)qbTepr06d?nV6I1e+t%d*ZVAF_=@3Qy zzZfUr?YDUb?cU5TuWUkCEnYg`MEu35{Wvln0x*pF)p+r6_ZQN zB-`JHpemi7Mf}dZeDh4o<7QP>Q*el%)h8|{FvgvWXk|QmU*}kt%GgwWK)UdgL}+*h zy=rfJ^xPtT?J%>wN29<*eVL{8ls(PJ4|->$x3r4ayEx4wL&I(j$~+Bn9Vr^?vFk13 zY|+3!#u-PvGPMN_&S`nM4BL4)fVV59bxqfLpWR`#jV&#lNpA7ey3i`o&_q;+ajcPL{-mhj19eVas3vfx4sp@ZcRMKeKb3^R^U=J0Xv)5J{b&-PTY;jN>_ zKn=GalN5nXhT~`^JI`0zts9tT8guud;U-_9(tu zXY3mzm(e#0a>!5j8Rf;s#x4s!<}>CCfQ$XF)3|ItF#(R0+8u^xN0+d6>BS>$3-r`G z3%-t?K5C6I9@d_E8vKOZ1gYT;8%_O1PwKccX#4dvGgFFNUU@XRnq;8b_mJpBx`DG9 zB5x_y+2DvjQ%ip_ZrXp-x_&%8dxQ*Gz4`y;X6@Pqm0pj_I}r3n@sH09DC-^S@+=!x k%O5Lb4cU6=kGb&M1T|?;jj1vbaZ68r`BU;2 - - - - -Ryzom Account Management System: info.php File Reference - - - - - - - - - - - -

    -
    -
    -
    info.php File Reference
    -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/install_8php.html b/code/web/docs/ams/html/install_8php.html deleted file mode 100644 index e05c51d76..000000000 --- a/code/web/docs/ams/html/install_8php.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/sql/install.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/sql/install.php File Reference
    -
    -
    - - - -

    -Variables

    global $cfg
    -

    Variable Documentation

    - -
    -
    - - - - -
    global $cfg
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/installdox b/code/web/docs/ams/html/installdox deleted file mode 100644 index edf5bbfe3..000000000 --- a/code/web/docs/ams/html/installdox +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/perl - -%subst = ( ); -$quiet = 0; - -while ( @ARGV ) { - $_ = shift @ARGV; - if ( s/^-// ) { - if ( /^l(.*)/ ) { - $v = ($1 eq "") ? shift @ARGV : $1; - ($v =~ /\/$/) || ($v .= "/"); - $_ = $v; - if ( /(.+)\@(.+)/ ) { - if ( exists $subst{$1} ) { - $subst{$1} = $2; - } else { - print STDERR "Unknown tag file $1 given with option -l\n"; - &usage(); - } - } else { - print STDERR "Argument $_ is invalid for option -l\n"; - &usage(); - } - } - elsif ( /^q/ ) { - $quiet = 1; - } - elsif ( /^\?|^h/ ) { - &usage(); - } - else { - print STDERR "Illegal option -$_\n"; - &usage(); - } - } - else { - push (@files, $_ ); - } -} - -foreach $sub (keys %subst) -{ - if ( $subst{$sub} eq "" ) - { - print STDERR "No substitute given for tag file `$sub'\n"; - &usage(); - } - elsif ( ! $quiet && $sub ne "_doc" && $sub ne "_cgi" ) - { - print "Substituting $subst{$sub} for each occurrence of tag file $sub\n"; - } -} - -if ( ! @files ) { - if (opendir(D,".")) { - foreach $file ( readdir(D) ) { - $match = ".html"; - next if ( $file =~ /^\.\.?$/ ); - ($file =~ /$match/) && (push @files, $file); - ($file =~ /\.svg/) && (push @files, $file); - ($file =~ "navtree.js") && (push @files, $file); - } - closedir(D); - } -} - -if ( ! @files ) { - print STDERR "Warning: No input files given and none found!\n"; -} - -foreach $f (@files) -{ - if ( ! $quiet ) { - print "Editing: $f...\n"; - } - $oldf = $f; - $f .= ".bak"; - unless (rename $oldf,$f) { - print STDERR "Error: cannot rename file $oldf\n"; - exit 1; - } - if (open(F,"<$f")) { - unless (open(G,">$oldf")) { - print STDERR "Error: opening file $oldf for writing\n"; - exit 1; - } - if ($oldf ne "tree.js") { - while () { - s/doxygen\=\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\" (xlink:href|href|src)=\"\2/doxygen\=\"$1:$subst{$1}\" \3=\"$subst{$1}/g; - print G "$_"; - } - } - else { - while () { - s/\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\", \"\2/\"$1:$subst{$1}\" ,\"$subst{$1}/g; - print G "$_"; - } - } - } - else { - print STDERR "Warning file $f does not exist\n"; - } - unlink $f; -} - -sub usage { - print STDERR "Usage: installdox [options] [html-file [html-file ...]]\n"; - print STDERR "Options:\n"; - print STDERR " -l tagfile\@linkName tag file + URL or directory \n"; - print STDERR " -q Quiet mode\n\n"; - exit 1; -} diff --git a/code/web/docs/ams/html/jquery.js b/code/web/docs/ams/html/jquery.js deleted file mode 100644 index 90b3a2bc3..000000000 --- a/code/web/docs/ams/html/jquery.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
    ","
    "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

    ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
    ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0) -{I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
    ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function() -{G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
    ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); - -/* - * jQuery hashchange event - v1.3 - 7/21/2010 - * http://benalman.com/projects/jquery-hashchange-plugin/ - * - * Copyright (c) 2010 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ -(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$(' -
    - - - - - - - diff --git a/code/web/docs/ams/html/logo.png b/code/web/docs/ams/html/logo.png deleted file mode 100644 index a072d6eafc703b0180e60f9c527fb2eab12b809d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19642 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 Bwf_JB diff --git a/code/web/docs/ams/html/mail__cron_8php.html b/code/web/docs/ams/html/mail__cron_8php.html deleted file mode 100644 index d08742e2a..000000000 --- a/code/web/docs/ams/html/mail__cron_8php.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/cron/mail_cron.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/cron/mail_cron.php File Reference
    -
    -
    - - - - -

    -Variables

     $mail_handler = new Mail_Handler()
     This small piece of php code calls the cron() function of the Mail_Handler.
    -

    Variable Documentation

    - -
    -
    - - - - -
    $mail_handler = new Mail_Handler()
    -
    -
    - -

    This small piece of php code calls the cron() function of the Mail_Handler.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/mail__handler_8php.html b/code/web/docs/ams/html/mail__handler_8php.html deleted file mode 100644 index 51c5ead9e..000000000 --- a/code/web/docs/ams/html/mail__handler_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mail_handler.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Mail_Handler
     Handles the mailing functionality. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/modify__email__of__sgroup_8php.html b/code/web/docs/ams/html/modify__email__of__sgroup_8php.html deleted file mode 100644 index 12cc4f71b..000000000 --- a/code/web/docs/ams/html/modify__email__of__sgroup_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/modify_email_of_sgroup.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/modify_email_of_sgroup.php File Reference
    -
    -
    - - - - -

    -Functions

     modify_email_of_sgroup ()
     This function is beign used to modify the email related to a support group.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    modify_email_of_sgroup ()
    -
    -
    - -

    This function is beign used to modify the email related to a support group.

    -

    It will first check if the user who executed this function is an admin. If this is not the case the page will be redirected to an error page. the new email will be validated and in case it's valid we'll add it to the db. Before adding it, we will encrypt the password by using the MyCrypt class. Afterwards the password gets updated and the page redirected again.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/mycrypt_8php.html b/code/web/docs/ams/html/mycrypt_8php.html deleted file mode 100644 index 6c440fabe..000000000 --- a/code/web/docs/ams/html/mycrypt_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mycrypt.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/mycrypt.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  MyCrypt
     Basic encryption/decryption class. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/nav_f.png b/code/web/docs/ams/html/nav_f.png deleted file mode 100644 index 1b07a16207e67c95fe2ee17e7016e6d08ac7ac99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^j6iI`!2~2XGqLUlQfZzpjv*C{Z|{2YIT`Y>1X`Eg z-tTbne1`SITM8Q!Pb(<)UFZ(m>wMzvKZQqKM~~GcZ=A7j<~E6K62>ozFS=cD3)mf8 z9WX0+R&m(l9KUsLdTx4?9~({T__KA%`}olPJ^N;y|F^pHgs_K%!rj~{8>RwnWbkzL Kb6Mw<&;$VTdq1fF diff --git a/code/web/docs/ams/html/nav_h.png b/code/web/docs/ams/html/nav_h.png deleted file mode 100644 index 01f5fa6a596e36bd12c2d6ceff1b0169fda7e699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^j6lr8!2~3AUOE6t1`SUa$B+ufw|6&kG8phMJMJ~w va4>Y+bZ&9QY?(VEUPY_cGd9nQ`um^ZSUyYpAAuKhL7F^W{an^LB{Ts5DmojT diff --git a/code/web/docs/ams/html/open.png b/code/web/docs/ams/html/open.png deleted file mode 100644 index 7b35d2c2c389743089632fe24c3104f2173d97af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{Vww^AIAr*{o=Nbw!DDW^(zOibV zl!F8B0?t?i!vld4k#$~0_AX3zElaokn - - - - -Ryzom Account Management System: Related Pages - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - -
    -
    -
    -
    Related Pages
    -
    -
    -
    Here is a list of all related documentation pages:
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/pagination_8php.html b/code/web/docs/ams/html/pagination_8php.html deleted file mode 100644 index 880e06a36..000000000 --- a/code/web/docs/ams/html/pagination_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/pagination.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/pagination.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Pagination
     Handles returning arrays based on a given pagenumber. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/querycache_8php.html b/code/web/docs/ams/html/querycache_8php.html deleted file mode 100644 index 0a9593825..000000000 --- a/code/web/docs/ams/html/querycache_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/querycache.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Querycache
     class for storing changes when shard is offline. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/register_8php.html b/code/web/docs/ams/html/register_8php.html deleted file mode 100644 index d326886af..000000000 --- a/code/web/docs/ams/html/register_8php.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/register.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/register.php File Reference
    -
    -
    - - - - -

    -Functions

     register ()
     This function is beign used to load info that's needed for the register page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    register ()
    -
    -
    - -

    This function is beign used to load info that's needed for the register page.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/reply__on__ticket_8php.html b/code/web/docs/ams/html/reply__on__ticket_8php.html deleted file mode 100644 index aed5249ba..000000000 --- a/code/web/docs/ams/html/reply__on__ticket_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/reply_on_ticket.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/func/reply_on_ticket.php File Reference
    -
    -
    - - - - -

    -Functions

     reply_on_ticket ()
     This function is beign used to reply on a ticket.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    reply_on_ticket ()
    -
    -
    - -

    This function is beign used to reply on a ticket.

    -

    It will first check if the user who executed this function is a mod/admin or the topic creator himself. If this is not the case the page will be redirected to an error page. in case the isset($_POST['hidden'] is set and the user is a mod, the message will be hidden for the topic starter. The reply will be created. If $_POST['ChangeStatus']) & $_POST['ChangePriority'] is set it will try to update the status and priority. Afterwards the page is being redirecte to the ticket again.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/search/all_24.html b/code/web/docs/ams/html/search/all_24.html deleted file mode 100644 index 476d13496..000000000 --- a/code/web/docs/ams/html/search/all_24.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_24.js b/code/web/docs/ams/html/search/all_24.js deleted file mode 100644 index 8e8a493e9..000000000 --- a/code/web/docs/ams/html/search/all_24.js +++ /dev/null @@ -1,91 +0,0 @@ -var searchData= -[ - ['_24allow_5funknown',['$ALLOW_UNKNOWN',['../drupal__module_2ryzommanage_2config_8php.html#a384355265e4331097d55252f901eddff',1,'$ALLOW_UNKNOWN(): config.php'],['../www_2config_8php.html#a384355265e4331097d55252f901eddff',1,'$ALLOW_UNKNOWN(): config.php']]], - ['_24amountofrows',['$amountOfRows',['../classPagination.html#a6b5c716eec440d8dc5b9754c53c545ec',1,'Pagination']]], - ['_24ams_5fcachedir',['$AMS_CACHEDIR',['../drupal__module_2ryzommanage_2config_8php.html#a92879a931e7a7d0ae6919e70a1529747',1,'$AMS_CACHEDIR(): config.php'],['../www_2config_8php.html#a92879a931e7a7d0ae6919e70a1529747',1,'$AMS_CACHEDIR(): config.php']]], - ['_24ams_5flib',['$AMS_LIB',['../drupal__module_2ryzommanage_2config_8php.html#a75086b9c8602bf3417773bae7ef0cdc8',1,'$AMS_LIB(): config.php'],['../www_2config_8php.html#a75086b9c8602bf3417773bae7ef0cdc8',1,'$AMS_LIB(): config.php']]], - ['_24ams_5ftrans',['$AMS_TRANS',['../drupal__module_2ryzommanage_2config_8php.html#acc96a0076127356b4f9f00f4bdfa9b65',1,'$AMS_TRANS(): config.php'],['../www_2config_8php.html#acc96a0076127356b4f9f00f4bdfa9b65',1,'$AMS_TRANS(): config.php']]], - ['_24author',['$author',['../classTicket.html#ac35b828f7d4064a7c9f849c255468ee3',1,'Ticket\$author()'],['../classTicket__Log.html#ac35b828f7d4064a7c9f849c255468ee3',1,'Ticket_Log\$author()'],['../classTicket__Reply.html#ac35b828f7d4064a7c9f849c255468ee3',1,'Ticket_Reply\$author()']]], - ['_24base_5fwebpath',['$BASE_WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#a2e954ee09fb5f52b9d05caf9dfc3d5ad',1,'$BASE_WEBPATH(): config.php'],['../www_2config_8php.html#a2e954ee09fb5f52b9d05caf9dfc3d5ad',1,'$BASE_WEBPATH(): config.php']]], - ['_24cfg',['$cfg',['../drupal__module_2ryzommanage_2config_8php.html#a32f90fc68bcb40de0bae38354fd0a5fe',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a6b776651fa7defe140c03ed3bd86aa96',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a68f172c430a17022c9f74ae1acd24a00',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1805c74760836f682459a12a17d50589',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a94213b6df61b8a6b62abbe7c956493a4',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a4b555022064138fee1d7edea873c5e9e',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1b49c1f0de42e603443bea2c93276c13',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7c5f3fd8aea7ae8363c6cdc9addd9b62',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7b5bbf5b3c541b46d06deaffeeb76424',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1dca44c652dd54f6879957cf8d4a039c',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a56e7e53dac48b99f62d41d387c8624e6',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#adc2648938b5135f1f2aab1d92d33418e',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1324eeda6b288c0a26d7071db555090c',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a63d97fffb2ff86525bb6cacb74113a73',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7147f422b8150cd3f3c8a68325208607',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a53f42728714b4e86b885c12f7846cd06',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#aa68c438d0b6b38d756d8724bac554f1b',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#ae4ae1095a3543d5607464a88e6330a07',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7cf20f61de759c233272150b12e866d8',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#aed7bed5da2b934c742cb60d23c06f752',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1606e0620d5a628b865e0df5c217ce7e',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a41e3a386ec52e0f05bdcad04acecf619',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#ac2c263a1e16ebd69dbf247e8d82c9f63',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a9996bf49f150442cf9d564725d0dea24',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#aa7eb09eb019c344553a61b54606cb650',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a79b711e7ee81b7435a8dba7cb132b34a',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a8578ffa00c2dbcf5d34a97bcff79058b',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a50d80d35dbd37739f844a93a36fce557',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a55031a1c3c2b9d87e37558811b311ff8',1,'$cfg(): config.php'],['../www_2config_8php.html#a32f90fc68bcb40de0bae38354fd0a5fe',1,'$cfg(): config.php'],['../www_2config_8php.html#a6b776651fa7defe140c03ed3bd86aa96',1,'$cfg(): config.php'],['../www_2config_8php.html#a68f172c430a17022c9f74ae1acd24a00',1,'$cfg(): config.php'],['../www_2config_8php.html#a1805c74760836f682459a12a17d50589',1,'$cfg(): config.php'],['../www_2config_8php.html#a94213b6df61b8a6b62abbe7c956493a4',1,'$cfg(): config.php'],['../www_2config_8php.html#a4b555022064138fee1d7edea873c5e9e',1,'$cfg(): config.php'],['../www_2config_8php.html#a1b49c1f0de42e603443bea2c93276c13',1,'$cfg(): config.php'],['../www_2config_8php.html#a7c5f3fd8aea7ae8363c6cdc9addd9b62',1,'$cfg(): config.php'],['../www_2config_8php.html#a7b5bbf5b3c541b46d06deaffeeb76424',1,'$cfg(): config.php'],['../www_2config_8php.html#a1dca44c652dd54f6879957cf8d4a039c',1,'$cfg(): config.php'],['../www_2config_8php.html#a56e7e53dac48b99f62d41d387c8624e6',1,'$cfg(): config.php'],['../www_2config_8php.html#adc2648938b5135f1f2aab1d92d33418e',1,'$cfg(): config.php'],['../www_2config_8php.html#a1324eeda6b288c0a26d7071db555090c',1,'$cfg(): config.php'],['../www_2config_8php.html#a63d97fffb2ff86525bb6cacb74113a73',1,'$cfg(): config.php'],['../www_2config_8php.html#a7147f422b8150cd3f3c8a68325208607',1,'$cfg(): config.php'],['../www_2config_8php.html#a53f42728714b4e86b885c12f7846cd06',1,'$cfg(): config.php'],['../www_2config_8php.html#aa68c438d0b6b38d756d8724bac554f1b',1,'$cfg(): config.php'],['../www_2config_8php.html#ae4ae1095a3543d5607464a88e6330a07',1,'$cfg(): config.php'],['../www_2config_8php.html#a7cf20f61de759c233272150b12e866d8',1,'$cfg(): config.php'],['../www_2config_8php.html#aed7bed5da2b934c742cb60d23c06f752',1,'$cfg(): config.php'],['../www_2config_8php.html#a1606e0620d5a628b865e0df5c217ce7e',1,'$cfg(): config.php'],['../www_2config_8php.html#a41e3a386ec52e0f05bdcad04acecf619',1,'$cfg(): config.php'],['../www_2config_8php.html#ac2c263a1e16ebd69dbf247e8d82c9f63',1,'$cfg(): config.php'],['../www_2config_8php.html#a9996bf49f150442cf9d564725d0dea24',1,'$cfg(): config.php'],['../www_2config_8php.html#aa7eb09eb019c344553a61b54606cb650',1,'$cfg(): config.php'],['../www_2config_8php.html#a79b711e7ee81b7435a8dba7cb132b34a',1,'$cfg(): config.php'],['../www_2config_8php.html#a8578ffa00c2dbcf5d34a97bcff79058b',1,'$cfg(): config.php'],['../www_2config_8php.html#a50d80d35dbd37739f844a93a36fce557',1,'$cfg(): config.php'],['../www_2config_8php.html#a55031a1c3c2b9d87e37558811b311ff8',1,'$cfg(): config.php'],['../install_8php.html#a449cc4bf6cfd310810993b3ef5251aa5',1,'$cfg(): install.php']]], - ['_24client_5fversion',['$client_version',['../classTicket__Info.html#ac43fbb88dcd0696ad49d5f805f369a61',1,'Ticket_Info']]], - ['_24config',['$config',['../classMyCrypt.html#a49c7011be9c979d9174c52a8b83e5d8e',1,'MyCrypt']]], - ['_24config_5fpath',['$CONFIG_PATH',['../drupal__module_2ryzommanage_2config_8php.html#ae15921e2ebd5885ecf37d31a2cf6ab7a',1,'$CONFIG_PATH(): config.php'],['../www_2config_8php.html#ae15921e2ebd5885ecf37d31a2cf6ab7a',1,'$CONFIG_PATH(): config.php']]], - ['_24connect_5fstate',['$connect_state',['../classTicket__Info.html#a33f4c9badf7f0c5c6728bba0ffacd66e',1,'Ticket_Info']]], - ['_24content',['$content',['../classTicket__Content.html#a57b284fe00866494b33afa80ba729bed',1,'Ticket_Content\$content()'],['../classTicket__Reply.html#a57b284fe00866494b33afa80ba729bed',1,'Ticket_Reply\$content()']]], - ['_24country',['$country',['../classWebUsers.html#a1437a5f6eb157f0eb267a26e0ad4f1ba',1,'WebUsers']]], - ['_24cpu_5fid',['$cpu_id',['../classTicket__Info.html#abea88d0d04f0d548115a0e85eef42e42',1,'Ticket_Info']]], - ['_24cpu_5fmask',['$cpu_mask',['../classTicket__Info.html#a9b0c63551b567630d1aa82f33c328ab0',1,'Ticket_Info']]], - ['_24create_5fring',['$CREATE_RING',['../drupal__module_2ryzommanage_2config_8php.html#a16031d9d4e5065229bc3b00dfd4202fa',1,'$CREATE_RING(): config.php'],['../www_2config_8php.html#a16031d9d4e5065229bc3b00dfd4202fa',1,'$CREATE_RING(): config.php']]], - ['_24current',['$current',['../classPagination.html#a2c4c58e377f6c66ca38c8ea97666fc5e',1,'Pagination']]], - ['_24db',['$db',['../classMail__Handler.html#a1fa3127fc82f96b1436d871ef02be319',1,'Mail_Handler\$db()'],['../classQuerycache.html#a1fa3127fc82f96b1436d871ef02be319',1,'Querycache\$db()']]], - ['_24default_5flanguage',['$DEFAULT_LANGUAGE',['../drupal__module_2ryzommanage_2config_8php.html#a7b56c2ed5a82ceb21fc73cef77beb150',1,'$DEFAULT_LANGUAGE(): config.php'],['../www_2config_8php.html#a7b56c2ed5a82ceb21fc73cef77beb150',1,'$DEFAULT_LANGUAGE(): config.php']]], - ['_24element_5farray',['$element_array',['../classPagination.html#a8fa0f6a15481ba69e7be913eaa15594c',1,'Pagination']]], - ['_24email',['$email',['../classWebUsers.html#ad634f418b20382e2802f80532d76d3cd',1,'WebUsers']]], - ['_24externid',['$externId',['../classTicket__User.html#af51400fe5820e964cb38fcc60b3afd84',1,'Ticket_User']]], - ['_24firstname',['$firstname',['../classWebUsers.html#a55793c72c535d153ffd3f0e43377898b',1,'WebUsers']]], - ['_24force_5fingame',['$FORCE_INGAME',['../drupal__module_2ryzommanage_2config_8php.html#aabd939b29ed900f5fc489f1a957fc6ce',1,'$FORCE_INGAME(): config.php'],['../www_2config_8php.html#aabd939b29ed900f5fc489f1a957fc6ce',1,'$FORCE_INGAME(): config.php']]], - ['_24gender',['$gender',['../classWebUsers.html#a0f1d7cfb9dc6f494b9014885205fc47e',1,'WebUsers']]], - ['_24group',['$group',['../classForwarded.html#ad530a85733b0ec1dc321859fd8faa0dc',1,'Forwarded\$group()'],['../classIn__Support__Group.html#ad530a85733b0ec1dc321859fd8faa0dc',1,'In_Support_Group\$group()']]], - ['_24groupemail',['$groupEmail',['../classSupport__Group.html#ab7ad611af238b28f1f65a32cb152acd1',1,'Support_Group']]], - ['_24hidden',['$hidden',['../classTicket__Reply.html#a4a374564d2858d8ae869a8fb890aad56',1,'Ticket_Reply']]], - ['_24ht',['$ht',['../classTicket__Info.html#a969583a6605ed731abf5849a5202db1e',1,'Ticket_Info']]], - ['_24imageloc_5fwebpath',['$IMAGELOC_WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#a16820074dcd11e4881ca6461377db000',1,'$IMAGELOC_WEBPATH(): config.php'],['../www_2config_8php.html#a16820074dcd11e4881ca6461377db000',1,'$IMAGELOC_WEBPATH(): config.php']]], - ['_24imap_5fmailserver',['$iMAP_MailServer',['../classSupport__Group.html#ad9f2ef2089fe446a9ac49a19a450d636',1,'Support_Group']]], - ['_24imap_5fpassword',['$iMAP_Password',['../classSupport__Group.html#a4166a2fc4b594ee425d7f40870e16455',1,'Support_Group']]], - ['_24imap_5fusername',['$iMAP_Username',['../classSupport__Group.html#a2b549eb4d5773efd741a2990817af0ea',1,'Support_Group']]], - ['_24ingame_5flayout',['$INGAME_LAYOUT',['../drupal__module_2ryzommanage_2config_8php.html#a0deedf69fea8c97030373e15a68c4cc5',1,'$INGAME_LAYOUT(): config.php'],['../www_2config_8php.html#a0deedf69fea8c97030373e15a68c4cc5',1,'$INGAME_LAYOUT(): config.php']]], - ['_24ingame_5fwebpath',['$INGAME_WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#ae9f6aa9c61501bca7b8851925c636d87',1,'$INGAME_WEBPATH(): config.php'],['../www_2config_8php.html#ae9f6aa9c61501bca7b8851925c636d87',1,'$INGAME_WEBPATH(): config.php']]], - ['_24language',['$language',['../classWebUsers.html#a83170d318260a5a2e2a79dccdd371b10',1,'WebUsers']]], - ['_24last',['$last',['../classPagination.html#acf48db609a946d13953d8060363fd1d3',1,'Pagination']]], - ['_24lastname',['$lastname',['../classWebUsers.html#a1d2ddb6354180329b59e8b90ed94dc7f',1,'WebUsers']]], - ['_24local_5faddress',['$local_address',['../classTicket__Info.html#a467dca5673d4c9f737dac972ab05720c',1,'Ticket_Info']]], - ['_24login',['$login',['../classWebUsers.html#afc31993e855f9631572adfedcfe6f34b',1,'WebUsers']]], - ['_24mail_5fdir',['$MAIL_DIR',['../drupal__module_2ryzommanage_2config_8php.html#a9f8fc644554910de5434f78a5f23044e',1,'$MAIL_DIR(): config.php'],['../www_2config_8php.html#a9f8fc644554910de5434f78a5f23044e',1,'$MAIL_DIR(): config.php']]], - ['_24mail_5fhandler',['$mail_handler',['../mail__cron_8php.html#a160a75d95407d877e9c2542e3ddd8c43',1,'mail_cron.php']]], - ['_24mail_5flog_5fpath',['$MAIL_LOG_PATH',['../drupal__module_2ryzommanage_2config_8php.html#afe6e9ed40480c14cb7a119fb84cb557a',1,'$MAIL_LOG_PATH(): config.php'],['../www_2config_8php.html#afe6e9ed40480c14cb7a119fb84cb557a',1,'$MAIL_LOG_PATH(): config.php']]], - ['_24memory',['$memory',['../classTicket__Info.html#a5e20a9a3e12271b3b8d685805590c9e0',1,'Ticket_Info']]], - ['_24name',['$name',['../classSupport__Group.html#ab2fc40d43824ea3e1ce5d86dee0d763b',1,'Support_Group\$name()'],['../classTicket__Category.html#ab2fc40d43824ea3e1ce5d86dee0d763b',1,'Ticket_Category\$name()']]], - ['_24nel3d',['$nel3d',['../classTicket__Info.html#a9b616e5fbafadc93aa4bdf3ccbf31498',1,'Ticket_Info']]], - ['_24os',['$os',['../classTicket__Info.html#a292791d5d8e3ded85cb2e8ec80dea0d9',1,'Ticket_Info']]], - ['_24pagination',['$pagination',['../classTicket__Queue__Handler.html#a388a4a950e936f746d3b9c1b56450ce7',1,'Ticket_Queue_Handler']]], - ['_24params',['$params',['../classTicket__Queue.html#afe68e6fbe7acfbffc0af0c84a1996466',1,'Ticket_Queue']]], - ['_24patch_5fversion',['$patch_version',['../classTicket__Info.html#a55fc0854f90ed36ab9774ba7bd2af53f',1,'Ticket_Info']]], - ['_24pdo',['$PDO',['../classDBLayer.html#acdb2149c05a21fe144fb05ec524a51f3',1,'DBLayer']]], - ['_24permission',['$permission',['../classTicket__User.html#aad04b6f3304fe6a13d5be37f7cd28938',1,'Ticket_User']]], - ['_24priority',['$priority',['../classTicket.html#a2677e505e860db863720ac4e216fd3f2',1,'Ticket']]], - ['_24processor',['$processor',['../classTicket__Info.html#a11fe8ad69d64b596f8b712b0b7e7e1e3',1,'Ticket_Info']]], - ['_24query',['$query',['../classQuerycache.html#af59a5f7cd609e592c41dc3643efd3c98',1,'Querycache\$query()'],['../classTicket__Log.html#af59a5f7cd609e592c41dc3643efd3c98',1,'Ticket_Log\$query()'],['../classTicket__Queue.html#af59a5f7cd609e592c41dc3643efd3c98',1,'Ticket_Queue\$query()']]], - ['_24queue',['$queue',['../classTicket.html#a4a0b48f6ae2fcb248a4f0288c7c344a6',1,'Ticket\$queue()'],['../classTicket__Queue__Handler.html#a4a0b48f6ae2fcb248a4f0288c7c344a6',1,'Ticket_Queue_Handler\$queue()']]], - ['_24receivemail',['$receiveMail',['../classWebUsers.html#a3c74ba660e348124f36d978b137f691d',1,'WebUsers']]], - ['_24server_5ftick',['$server_tick',['../classTicket__Info.html#aeac33ccad750e9ee81a22414db1224ab',1,'Ticket_Info']]], - ['_24sgroupid',['$sGroupId',['../classSupport__Group.html#a23265908fce0f131e03ba1ede7f42647',1,'Support_Group']]], - ['_24shardid',['$shardid',['../classTicket__Info.html#ac73283a0a8308fb7594543e4a049942c',1,'Ticket_Info']]], - ['_24sid',['$SID',['../classQuerycache.html#a69c31f890638fa4930097cf55ae27995',1,'Querycache']]], - ['_24sitebase',['$SITEBASE',['../drupal__module_2ryzommanage_2config_8php.html#a9eb41824afc2b8150c27648859f07357',1,'$SITEBASE(): config.php'],['../www_2config_8php.html#a9eb41824afc2b8150c27648859f07357',1,'$SITEBASE(): config.php']]], - ['_24status',['$status',['../classTicket.html#a58391ea75f2d29d5d708d7050b641c33',1,'Ticket']]], - ['_24support_5fgroup_5fimap_5fcryptkey',['$SUPPORT_GROUP_IMAP_CRYPTKEY',['../drupal__module_2ryzommanage_2config_8php.html#a3ed2ac4433023af3e95f8912f00125ea',1,'$SUPPORT_GROUP_IMAP_CRYPTKEY(): config.php'],['../www_2config_8php.html#a3ed2ac4433023af3e95f8912f00125ea',1,'$SUPPORT_GROUP_IMAP_CRYPTKEY(): config.php']]], - ['_24tag',['$tag',['../classSupport__Group.html#a81d5015d41ed8ec66e9db8cdc5db9555',1,'Support_Group']]], - ['_24tcategoryid',['$tCategoryId',['../classTicket__Category.html#a0111df4559c9f524272d94df0b7f9d6b',1,'Ticket_Category']]], - ['_24tcontentid',['$tContentId',['../classTicket__Content.html#a2249787a24edd706ae7a54609a601d6f',1,'Ticket_Content']]], - ['_24ticket',['$ticket',['../classAssigned.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Assigned\$ticket()'],['../classForwarded.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Forwarded\$ticket()'],['../classTicket__Info.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Ticket_Info\$ticket()'],['../classTicket__Log.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Ticket_Log\$ticket()'],['../classTicket__Reply.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Ticket_Reply\$ticket()']]], - ['_24ticket_5fcategory',['$ticket_category',['../classTicket.html#a86e470072892575063c478122fb65184',1,'Ticket']]], - ['_24ticket_5flogging',['$TICKET_LOGGING',['../drupal__module_2ryzommanage_2config_8php.html#aa59491d29009336d89423cccd3adc5de',1,'$TICKET_LOGGING(): config.php'],['../www_2config_8php.html#aa59491d29009336d89423cccd3adc5de',1,'$TICKET_LOGGING(): config.php']]], - ['_24ticket_5fmailing_5fsupport',['$TICKET_MAILING_SUPPORT',['../drupal__module_2ryzommanage_2config_8php.html#a23c3d413e56a57bc04d69627a4ed2b14',1,'$TICKET_MAILING_SUPPORT(): config.php'],['../www_2config_8php.html#a23c3d413e56a57bc04d69627a4ed2b14',1,'$TICKET_MAILING_SUPPORT(): config.php']]], - ['_24tid',['$tId',['../classTicket.html#a3eda2fecc2433b6b6b3b957110e937ca',1,'Ticket']]], - ['_24time_5fformat',['$TIME_FORMAT',['../drupal__module_2ryzommanage_2config_8php.html#a613b2c043c06772e7119587b26eb9989',1,'$TIME_FORMAT(): config.php'],['../www_2config_8php.html#a613b2c043c06772e7119587b26eb9989',1,'$TIME_FORMAT(): config.php']]], - ['_24timestamp',['$timestamp',['../classTicket.html#a2b69de9676dd97c675cd4d9bcceb684c',1,'Ticket\$timestamp()'],['../classTicket__Log.html#a2b69de9676dd97c675cd4d9bcceb684c',1,'Ticket_Log\$timestamp()'],['../classTicket__Reply.html#a2b69de9676dd97c675cd4d9bcceb684c',1,'Ticket_Reply\$timestamp()']]], - ['_24tinfoid',['$tInfoId',['../classTicket__Info.html#a4c2ae13b7827d13b9629e3fc57335f8f',1,'Ticket_Info']]], - ['_24title',['$title',['../classTicket.html#ada57e7bb7c152edad18fe2f166188691',1,'Ticket']]], - ['_24tlogid',['$tLogId',['../classTicket__Log.html#a734657bd8aac85b5a33e03646c17eb65',1,'Ticket_Log']]], - ['_24tos_5furl',['$TOS_URL',['../drupal__module_2ryzommanage_2config_8php.html#aef688ce4c627fa2fbd8037fd2cceef78',1,'$TOS_URL(): config.php'],['../www_2config_8php.html#aef688ce4c627fa2fbd8037fd2cceef78',1,'$TOS_URL(): config.php']]], - ['_24treplyid',['$tReplyId',['../classTicket__Reply.html#a29f22c2783e510d4764a99a648a0cc36',1,'Ticket_Reply']]], - ['_24tuserid',['$tUserId',['../classTicket__User.html#a2f1828693b198682ae3e926e63a4c110',1,'Ticket_User']]], - ['_24type',['$type',['../classQuerycache.html#a9a4a6fba2208984cabb3afacadf33919',1,'Querycache']]], - ['_24uid',['$uId',['../classWebUsers.html#a8f11c60ae8f70a5059b97bc0ea9d0de5',1,'WebUsers']]], - ['_24user',['$user',['../classAssigned.html#a598ca4e71b15a1313ec95f0df1027ca5',1,'Assigned\$user()'],['../classIn__Support__Group.html#a598ca4e71b15a1313ec95f0df1027ca5',1,'In_Support_Group\$user()']]], - ['_24user_5fid',['$user_id',['../classTicket__Info.html#af0fcd925f00973e32f7214859dfb3c6b',1,'Ticket_Info']]], - ['_24user_5fposition',['$user_position',['../classTicket__Info.html#afc9fcd144a71e56898632daf43854aa7',1,'Ticket_Info']]], - ['_24view_5fposition',['$view_position',['../classTicket__Info.html#ae325cbe2a7e27757b90b12d595c4dfe9',1,'Ticket_Info']]], - ['_24webpath',['$WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#a562d30b98806af1e001a3ff855e8890a',1,'$WEBPATH(): config.php'],['../www_2config_8php.html#a562d30b98806af1e001a3ff855e8890a',1,'$WEBPATH(): config.php']]] -]; diff --git a/code/web/docs/ams/html/search/all_5f.html b/code/web/docs/ams/html/search/all_5f.html deleted file mode 100644 index 1f27755ab..000000000 --- a/code/web/docs/ams/html/search/all_5f.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_5f.js b/code/web/docs/ams/html/search/all_5f.js deleted file mode 100644 index 844048eb7..000000000 --- a/code/web/docs/ams/html/search/all_5f.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['_5f_5fautoload',['__autoload',['../libinclude_8php.html#a2ecfde85f554ea0b3fef0993aef304a9',1,'libinclude.php']]], - ['_5f_5fconstruct',['__construct',['../classAssigned.html#a095c5d389db211932136b53f25f39685',1,'Assigned\__construct()'],['../classDBLayer.html#a800f8efee13692788b13ee57c5960092',1,'DBLayer\__construct()'],['../classForwarded.html#a095c5d389db211932136b53f25f39685',1,'Forwarded\__construct()'],['../classIn__Support__Group.html#a095c5d389db211932136b53f25f39685',1,'In_Support_Group\__construct()'],['../classMyCrypt.html#af200cbfd49bfea2fecf5629ab2361033',1,'MyCrypt\__construct()'],['../classPagination.html#a2a1aecb8f526796b3d62e8278edc07c3',1,'Pagination\__construct()'],['../classQuerycache.html#a095c5d389db211932136b53f25f39685',1,'Querycache\__construct()'],['../classSupport__Group.html#a095c5d389db211932136b53f25f39685',1,'Support_Group\__construct()'],['../classTicket.html#a095c5d389db211932136b53f25f39685',1,'Ticket\__construct()'],['../classTicket__Category.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Category\__construct()'],['../classTicket__Content.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Content\__construct()'],['../classTicket__Info.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Info\__construct()'],['../classTicket__Log.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Log\__construct()'],['../classTicket__Queue__Handler.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Queue_Handler\__construct()'],['../classTicket__Reply.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Reply\__construct()'],['../classTicket__User.html#a095c5d389db211932136b53f25f39685',1,'Ticket_User\__construct()'],['../classWebUsers.html#a4e63742e531873e01e1e97dd7530539b',1,'WebUsers\__construct($UId=0)'],['../classWebUsers.html#a4e63742e531873e01e1e97dd7530539b',1,'WebUsers\__construct($UId=0)']]] -]; diff --git a/code/web/docs/ams/html/search/all_61.html b/code/web/docs/ams/html/search/all_61.html deleted file mode 100644 index a3164d553..000000000 --- a/code/web/docs/ams/html/search/all_61.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_61.js b/code/web/docs/ams/html/search/all_61.js deleted file mode 100644 index a077db22c..000000000 --- a/code/web/docs/ams/html/search/all_61.js +++ /dev/null @@ -1,13 +0,0 @@ -var searchData= -[ - ['add_5fsgroup',['add_sgroup',['../add__sgroup_8php.html#a45490c056bdd114ef28893fc29286d2b',1,'add_sgroup.php']]], - ['add_5fsgroup_2ephp',['add_sgroup.php',['../add__sgroup_8php.html',1,'']]], - ['add_5fuser',['add_user',['../add__user_8php.html#a69e8de25de7560db0292bb474882a489',1,'add_user.php']]], - ['add_5fuser_2ephp',['add_user.php',['../add__user_8php.html',1,'']]], - ['add_5fuser_5fto_5fsgroup',['add_user_to_sgroup',['../add__user__to__sgroup_8php.html#a6ad0c5a1bfd563e11a107bf0023b6150',1,'add_user_to_sgroup.php']]], - ['add_5fuser_5fto_5fsgroup_2ephp',['add_user_to_sgroup.php',['../add__user__to__sgroup_8php.html',1,'']]], - ['addusertosupportgroup',['addUserToSupportGroup',['../classSupport__Group.html#a4616317379ffef08dbaeea2a9dbba02c',1,'Support_Group']]], - ['assigned',['Assigned',['../classAssigned.html',1,'']]], - ['assigned_2ephp',['assigned.php',['../assigned_8php.html',1,'']]], - ['assignticket',['assignTicket',['../classAssigned.html#a51c3d5b6f78de455619581fd3e591f17',1,'Assigned\assignTicket()'],['../classTicket.html#a51c3d5b6f78de455619581fd3e591f17',1,'Ticket\assignTicket()']]] -]; diff --git a/code/web/docs/ams/html/search/all_63.html b/code/web/docs/ams/html/search/all_63.html deleted file mode 100644 index 56b5ad1e9..000000000 --- a/code/web/docs/ams/html/search/all_63.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_63.js b/code/web/docs/ams/html/search/all_63.js deleted file mode 100644 index c54f2f697..000000000 --- a/code/web/docs/ams/html/search/all_63.js +++ /dev/null @@ -1,51 +0,0 @@ -var searchData= -[ - ['change_5finfo',['change_info',['../change__info_8php.html#a1bbc74a7da07012d55b0b45726534265',1,'change_info.php']]], - ['change_5finfo_2ephp',['change_info.php',['../change__info_8php.html',1,'']]], - ['change_5fmail',['change_mail',['../change__mail_8php.html#a03d0bca67a96c8744bd74623e128ab83',1,'change_mail.php']]], - ['change_5fmail_2ephp',['change_mail.php',['../change__mail_8php.html',1,'']]], - ['change_5fpassword',['change_password',['../change__password_8php.html#a888360ab43db15eba1d5cc3623d4100f',1,'change_password.php']]], - ['change_5fpassword_2ephp',['change_password.php',['../change__password_8php.html',1,'']]], - ['change_5fpermission',['change_permission',['../classTicket__User.html#a78d4d6de74b1ee26cb9192f36e022416',1,'Ticket_User\change_permission()'],['../change__permission_8php.html#a9ad639fafd67bdc579cf3170cd0d26e7',1,'change_permission(): change_permission.php']]], - ['change_5fpermission_2ephp',['change_permission.php',['../change__permission_8php.html',1,'']]], - ['change_5freceivemail',['change_receivemail',['../change__receivemail_8php.html#a22ae748f60d7b4200dce30c94a52c421',1,'change_receivemail.php']]], - ['change_5freceivemail_2ephp',['change_receivemail.php',['../change__receivemail_8php.html',1,'']]], - ['check_5fchange_5fpassword',['check_change_password',['../classUsers.html#a9c78408d50465957eeb8068810315a8e',1,'Users']]], - ['check_5fif_5fgame_5fclient',['check_if_game_client',['../classHelpers.html#a4e3e5309a66456d81a1effdabcc9cd79',1,'Helpers']]], - ['check_5flogin_5fingame',['check_login_ingame',['../classHelpers.html#abd01528a1145831a4fc98eae7ffaca36',1,'Helpers']]], - ['check_5fmethods',['check_methods',['../classMyCrypt.html#ad72fefc790b0bb1ac6edc252427b0970',1,'MyCrypt']]], - ['check_5fregister',['check_Register',['../classUsers.html#a740de04dc3aa7cf3bed959540ffab8f8',1,'Users']]], - ['checkemail',['checkEmail',['../classUsers.html#a76646237ab053cdde386c06aa5437d8a',1,'Users']]], - ['checkemailexists',['checkEmailExists',['../classUsers.html#a37275e677004927b6b1a30e16c5b5b38',1,'Users\checkEmailExists()'],['../classWebUsers.html#a37275e677004927b6b1a30e16c5b5b38',1,'WebUsers\checkEmailExists($email)'],['../classWebUsers.html#a37275e677004927b6b1a30e16c5b5b38',1,'WebUsers\checkEmailExists($email)']]], - ['checkloginmatch',['checkLoginMatch',['../classUsers.html#af0b98012abb190cf4617999f008de27e',1,'Users\checkLoginMatch()'],['../classWebUsers.html#a11894eb69bb2f172baf5186e8f92246d',1,'WebUsers\checkLoginMatch($username, $password)'],['../classWebUsers.html#a11894eb69bb2f172baf5186e8f92246d',1,'WebUsers\checkLoginMatch($username, $password)']]], - ['checkpassword',['checkPassword',['../classUsers.html#a4cb5e34b56fb6de0ec318fb59e90838f',1,'Users']]], - ['checkuser',['checkUser',['../classUsers.html#adfffce17947a9f72d68838db250c9ab8',1,'Users']]], - ['checkusernameexists',['checkUserNameExists',['../classUsers.html#ac3a8cb9a038f6aef0bd98be091274122',1,'Users\checkUserNameExists()'],['../classWebUsers.html#ac3a8cb9a038f6aef0bd98be091274122',1,'WebUsers\checkUserNameExists($username)'],['../classWebUsers.html#ac3a8cb9a038f6aef0bd98be091274122',1,'WebUsers\checkUserNameExists($username)']]], - ['config_2ephp',['config.php',['../www_2config_8php.html',1,'']]], - ['config_2ephp',['config.php',['../drupal__module_2ryzommanage_2config_8php.html',1,'']]], - ['confirmpassword',['confirmPassword',['../classUsers.html#a2f5349025bed3874f08d80652cab2fe0',1,'Users']]], - ['constr_5fexternid',['constr_ExternId',['../classTicket__User.html#a4e5c577ed0a9da4b1c56397912f02ba0',1,'Ticket_User']]], - ['constr_5fsgroupid',['constr_SGroupId',['../classSupport__Group.html#a873beb80bd0b5d572704cdb6d2ec34eb',1,'Support_Group']]], - ['constr_5ftcategoryid',['constr_TCategoryId',['../classTicket__Category.html#a332d2dd59b46fc933a3c9a1b2967803a',1,'Ticket_Category']]], - ['constr_5ftcontentid',['constr_TContentId',['../classTicket__Content.html#aa28ad9a063c1914ff75d19afd25c707f',1,'Ticket_Content']]], - ['constr_5ftlogid',['constr_TLogId',['../classTicket__Log.html#a001ec13f64bb026b1c8a3b3bd02ee22b',1,'Ticket_Log']]], - ['constr_5ftreplyid',['constr_TReplyId',['../classTicket__Reply.html#a4b4493d28e8518a87667d285c49e5e24',1,'Ticket_Reply']]], - ['constr_5ftuserid',['constr_TUserId',['../classTicket__User.html#a10939bce9b667f26d3827993b4e3df1d',1,'Ticket_User']]], - ['create',['create',['../classAssigned.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Assigned\create()'],['../classForwarded.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Forwarded\create()'],['../classIn__Support__Group.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'In_Support_Group\create()'],['../classSupport__Group.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Support_Group\create()'],['../classTicket.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket\create()'],['../classTicket__Content.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket_Content\create()'],['../classTicket__Info.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket_Info\create()'],['../classTicket__Reply.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket_Reply\create()']]], - ['create_5ffolders',['create_folders',['../classHelpers.html#add8ef9ce82106c505f6f04c2a8e3b2b4',1,'Helpers']]], - ['create_5fticket',['create_Ticket',['../classTicket.html#a81b3285033bc3c9e89adfa8da34d61de',1,'Ticket\create_Ticket()'],['../create__ticket_8php.html#a65bcbfccf737c72927d15c06783cd9f4',1,'create_ticket(): create_ticket.php']]], - ['create_5fticket_2ephp',['create_ticket.php',['../create__ticket_8php.html',1,'']]], - ['create_5fticket_5finfo',['create_Ticket_Info',['../classTicket__Info.html#aaa4e26c92338b70e874135af9c02bba9',1,'Ticket_Info']]], - ['createlogentry',['createLogEntry',['../classTicket__Log.html#a345a2da9c23780c7e6aef7134baa1749',1,'Ticket_Log']]], - ['createpermissions',['createPermissions',['../classUsers.html#aeac9f32fd53c97c92e5c774e154399df',1,'Users']]], - ['createqueue',['createQueue',['../classTicket__Queue.html#af077496b6071af47c19a873bf025c1f3',1,'Ticket_Queue\createQueue()'],['../classTicket__Queue__Handler.html#af077496b6071af47c19a873bf025c1f3',1,'Ticket_Queue_Handler\createQueue()']]], - ['createreply',['createReply',['../classTicket.html#af6568341f5052034440f79c0e74707a3',1,'Ticket\createReply()'],['../classTicket__Reply.html#aa6fa056fff4ddafc3eabf3ed72143e1b',1,'Ticket_Reply\createReply()']]], - ['createsupportgroup',['createSupportGroup',['../classSupport__Group.html#a31ee7c68c0ffb77438bb9ff095962568',1,'Support_Group']]], - ['createticket',['createticket',['../createticket_8php.html#aa8253d883a3ba14c6449a13ed2bb9c8f',1,'createticket.php']]], - ['createticket_2ephp',['createticket.php',['../createticket_8php.html',1,'']]], - ['createticketcategory',['createTicketCategory',['../classTicket__Category.html#a506fc7f32de9547e91a5dbb68c391907',1,'Ticket_Category']]], - ['createticketuser',['createTicketUser',['../classTicket__User.html#a37c416f7d3723874f3ac49c7f9f5a21c',1,'Ticket_User']]], - ['createuser',['createUser',['../classUsers.html#ac93aebf1960fb12975b120a2c394a8af',1,'Users']]], - ['createwebuser',['createWebuser',['../classWebUsers.html#a0cb7168a6b8358106512804ff28cea17',1,'WebUsers\createWebuser($name, $pass, $mail)'],['../classWebUsers.html#a0cb7168a6b8358106512804ff28cea17',1,'WebUsers\createWebuser($name, $pass, $mail)']]], - ['cron',['cron',['../classMail__Handler.html#a1b65890aa4eb8c0c6129c3e787a53405',1,'Mail_Handler']]] -]; diff --git a/code/web/docs/ams/html/search/all_64.html b/code/web/docs/ams/html/search/all_64.html deleted file mode 100644 index b53ff083e..000000000 --- a/code/web/docs/ams/html/search/all_64.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_64.js b/code/web/docs/ams/html/search/all_64.js deleted file mode 100644 index a897983e6..000000000 --- a/code/web/docs/ams/html/search/all_64.js +++ /dev/null @@ -1,12 +0,0 @@ -var searchData= -[ - ['dashboard',['dashboard',['../dashboard_8php.html#a54d0c80ff20df9df6439bb87608c375a',1,'dashboard.php']]], - ['dashboard_2ephp',['dashboard.php',['../dashboard_8php.html',1,'']]], - ['dblayer',['DBLayer',['../classDBLayer.html',1,'']]], - ['dblayer_2ephp',['dblayer.php',['../dblayer_8php.html',1,'']]], - ['decode_5futf8',['decode_utf8',['../classMail__Handler.html#a6fc5947eaa45b0724f8720b374481275',1,'Mail_Handler']]], - ['decrypt',['decrypt',['../classMyCrypt.html#aed69cdc691e1155856c905ee1c08d9b7',1,'MyCrypt']]], - ['delete',['delete',['../classAssigned.html#a13bdffdd926f26b825ea57066334ff01',1,'Assigned\delete()'],['../classForwarded.html#a13bdffdd926f26b825ea57066334ff01',1,'Forwarded\delete()'],['../classIn__Support__Group.html#a13bdffdd926f26b825ea57066334ff01',1,'In_Support_Group\delete()'],['../classSupport__Group.html#a13bdffdd926f26b825ea57066334ff01',1,'Support_Group\delete()']]], - ['deletesupportgroup',['deleteSupportGroup',['../classSupport__Group.html#ab4a7d3ba86333a058027c7d58b9137f1',1,'Support_Group']]], - ['deleteuserofsupportgroup',['deleteUserOfSupportGroup',['../classSupport__Group.html#ad2d1a010903640e39545085b93b9a4f1',1,'Support_Group']]] -]; diff --git a/code/web/docs/ams/html/search/all_65.html b/code/web/docs/ams/html/search/all_65.html deleted file mode 100644 index 66cc83487..000000000 --- a/code/web/docs/ams/html/search/all_65.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_65.js b/code/web/docs/ams/html/search/all_65.js deleted file mode 100644 index 537250038..000000000 --- a/code/web/docs/ams/html/search/all_65.js +++ /dev/null @@ -1,9 +0,0 @@ -var searchData= -[ - ['encrypt',['encrypt',['../classMyCrypt.html#a07bcc8ef1d23370470ecb5ae8fc07dfa',1,'MyCrypt']]], - ['error',['error',['../error_8php.html#a43b8d30b879d4f09ceb059b02af2bc02',1,'error.php']]], - ['error_2ephp',['error.php',['../error_8php.html',1,'']]], - ['execute',['execute',['../classDBLayer.html#a9a0e3ecb193fecd94263eda79c54bcc4',1,'DBLayer']]], - ['executereturnid',['executeReturnId',['../classDBLayer.html#a9a8137347ec2d551de3ec54cfb3bdb1a',1,'DBLayer']]], - ['executewithoutparams',['executeWithoutParams',['../classDBLayer.html#a33552c5325c469ac1aa0d049d2312468',1,'DBLayer']]] -]; diff --git a/code/web/docs/ams/html/search/all_66.html b/code/web/docs/ams/html/search/all_66.html deleted file mode 100644 index 3d1f8b35e..000000000 --- a/code/web/docs/ams/html/search/all_66.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_66.js b/code/web/docs/ams/html/search/all_66.js deleted file mode 100644 index 9959a693e..000000000 --- a/code/web/docs/ams/html/search/all_66.js +++ /dev/null @@ -1,6 +0,0 @@ -var searchData= -[ - ['forwarded',['Forwarded',['../classForwarded.html',1,'']]], - ['forwarded_2ephp',['forwarded.php',['../forwarded_8php.html',1,'']]], - ['forwardticket',['forwardTicket',['../classForwarded.html#aa6f01e425a0f845ce55c2d90aeb11db0',1,'Forwarded\forwardTicket()'],['../classTicket.html#a3fdc6def6a0feaf4c2458811b8c75050',1,'Ticket\forwardTicket()']]] -]; diff --git a/code/web/docs/ams/html/search/all_67.html b/code/web/docs/ams/html/search/all_67.html deleted file mode 100644 index 41a459ae7..000000000 --- a/code/web/docs/ams/html/search/all_67.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_67.js b/code/web/docs/ams/html/search/all_67.js deleted file mode 100644 index d55d29ded..000000000 --- a/code/web/docs/ams/html/search/all_67.js +++ /dev/null @@ -1,108 +0,0 @@ -var searchData= -[ - ['generatesalt',['generateSALT',['../classUsers.html#afb7603ac9556c1069fbf1c0062251203',1,'Users']]], - ['get_5femail_5fby_5fuser_5fid',['get_email_by_user_id',['../classTicket__User.html#a7274bc305ccce731091c68d1607cb6e9',1,'Ticket_User']]], - ['get_5fid_5ffrom_5femail',['get_id_from_email',['../classTicket__User.html#a7feeb7a909bf6733de21300d0ea0e1bd',1,'Ticket_User']]], - ['get_5fid_5ffrom_5fusername',['get_id_from_username',['../classTicket__User.html#a0bcfa281f41b948eb42dd18992724543',1,'Ticket_User']]], - ['get_5fmime_5ftype',['get_mime_type',['../classMail__Handler.html#a719c5051ef00fbb0d7c7ce2c78e3b4e1',1,'Mail_Handler']]], - ['get_5fpart',['get_part',['../classMail__Handler.html#ab3a5e8f69692826c6dae96f873859642',1,'Mail_Handler']]], - ['get_5fticket_5fid_5ffrom_5fsubject',['get_ticket_id_from_subject',['../classMail__Handler.html#a8604569b1e012ea3b1fe466018f75ce2',1,'Mail_Handler']]], - ['get_5fusername_5ffrom_5fid',['get_username_from_id',['../classTicket__User.html#a266ff1e60e08dcd8c7e70f22f5a33e93',1,'Ticket_User']]], - ['getaction',['getAction',['../classTicket__Log.html#a189a4abe5faf11f4320d5d3f1d3d1715',1,'Ticket_Log']]], - ['getactiontextarray',['getActionTextArray',['../classTicket__Log.html#ac760071c0ce36337c16d8146fcb3bade',1,'Ticket_Log']]], - ['getallcategories',['getAllCategories',['../classTicket__Category.html#a1e4b8ecfd737337e35976126b521499f',1,'Ticket_Category']]], - ['getalllogs',['getAllLogs',['../classTicket__Log.html#aeaf1c995cc807afe241f6e7bdc684921',1,'Ticket_Log']]], - ['getallsupportgroups',['getAllSupportGroups',['../classSupport__Group.html#ad3fc18cb894f789d19a768ea63d9b673',1,'Support_Group']]], - ['getallusersofsupportgroup',['getAllUsersOfSupportGroup',['../classSupport__Group.html#a7f1662394a31e2a05e9863def178df12',1,'Support_Group']]], - ['getallusersquery',['getAllUsersQuery',['../classWebUsers.html#a2f8e928ed02e462b40e909965250fb7d',1,'WebUsers\getAllUsersQuery()'],['../classWebUsers.html#a2f8e928ed02e462b40e909965250fb7d',1,'WebUsers\getAllUsersQuery()']]], - ['getamountofrows',['getAmountOfRows',['../classPagination.html#ae43f78382809e3cd2aaa3c455cb0b2b4',1,'Pagination']]], - ['getargument',['getArgument',['../classTicket__Log.html#a88ec9370bcbdb60301f89e401c9e64e1',1,'Ticket_Log']]], - ['getassigned',['getAssigned',['../classTicket.html#a8234a4e23319778d234b3957f8b5d06c',1,'Ticket']]], - ['getauthor',['getAuthor',['../classTicket.html#a5286e30390ae3e1b274940286493dd24',1,'Ticket\getAuthor()'],['../classTicket__Log.html#a5286e30390ae3e1b274940286493dd24',1,'Ticket_Log\getAuthor()'],['../classTicket__Reply.html#a5286e30390ae3e1b274940286493dd24',1,'Ticket_Reply\getAuthor()']]], - ['getcategoryname',['getCategoryName',['../classTicket.html#a689e9d131777e7f1219ee0d65b088cb3',1,'Ticket']]], - ['getclient_5fversion',['getClient_Version',['../classTicket__Info.html#a5a9884f9f9b63d4a6ed8c6112704277d',1,'Ticket_Info']]], - ['getconnect_5fstate',['getConnect_State',['../classTicket__Info.html#a51a5247b7c82f60479ccdcfa33041c27',1,'Ticket_Info']]], - ['getcontent',['getContent',['../classTicket__Content.html#a58e43f09a06ce4e29b192c4e17ce7915',1,'Ticket_Content\getContent()'],['../classTicket__Reply.html#a58e43f09a06ce4e29b192c4e17ce7915',1,'Ticket_Reply\getContent()']]], - ['getcountryarray',['getCountryArray',['../drupal__module_2ryzommanage_2inc_2settings_8php.html#a9342547984d3c9a5ece41572951f8edf',1,'getCountryArray(): settings.php'],['../www_2html_2inc_2settings_8php.html#a9342547984d3c9a5ece41572951f8edf',1,'getCountryArray(): settings.php']]], - ['getcpu_5fmask',['getCPU_Mask',['../classTicket__Info.html#ae85e54574e6e0b17cd33b8c49255d228',1,'Ticket_Info']]], - ['getcpuid',['getCPUId',['../classTicket__Info.html#aba21caccb000efb673b8b66ca70a36c7',1,'Ticket_Info']]], - ['getcurrent',['getCurrent',['../classPagination.html#ad926899d7cac34a3f1a90e552d8eb27d',1,'Pagination']]], - ['getdb',['getDb',['../classQuerycache.html#aceb656ee5135578ab3a9947252caa772',1,'Querycache']]], - ['getelements',['getElements',['../classPagination.html#a97a3a3e912139aa222a7ca13fdb27d33',1,'Pagination']]], - ['getemail',['getEmail',['../classWebUsers.html#a02a01849f28e2535e888ae4ec87b20f2',1,'WebUsers\getEmail()'],['../classWebUsers.html#a02a01849f28e2535e888ae4ec87b20f2',1,'WebUsers\getEmail()']]], - ['getentireticket',['getEntireTicket',['../classTicket.html#a00572e06f01ae1cadb5949f1b45e8f04',1,'Ticket']]], - ['getexternid',['getExternId',['../classTicket__User.html#ace230deb485c9f115f7fea4ce92442a3',1,'Ticket_User']]], - ['getforwardedgroupid',['getForwardedGroupId',['../classTicket.html#aedbfa4efd5aaa96ac713817d12156f7e',1,'Ticket']]], - ['getforwardedgroupname',['getForwardedGroupName',['../classTicket.html#a34e17d1cc053a7b86ce2b58a3a347c7e',1,'Ticket']]], - ['getgroup',['getGroup',['../classForwarded.html#a4f44e7bc9de772c21b4304d11e87bf16',1,'Forwarded\getGroup()'],['../classIn__Support__Group.html#a4f44e7bc9de772c21b4304d11e87bf16',1,'In_Support_Group\getGroup()'],['../classSupport__Group.html#af6697615443145a2981e62aa741c3afa',1,'Support_Group\getGroup()']]], - ['getgroupemail',['getGroupEmail',['../classSupport__Group.html#a9d0f36a53db49c1f57e3cab8a61a7d90',1,'Support_Group']]], - ['getgroups',['getGroups',['../classSupport__Group.html#a562142b89699a1063ea9769030250365',1,'Support_Group']]], - ['gethidden',['getHidden',['../classTicket__Reply.html#a1d032efbce2b4edb7c269a1e13562f40',1,'Ticket_Reply']]], - ['getht',['getHT',['../classTicket__Info.html#a90d3c0edc1e767875c7fb98880886e73',1,'Ticket_Info']]], - ['getid',['getId',['../classWebUsers.html#a585ef354b38d0fad9d92f45e183b639f',1,'WebUsers\getId($username)'],['../classWebUsers.html#a585ef354b38d0fad9d92f45e183b639f',1,'WebUsers\getId($username)']]], - ['getidfromemail',['getIdFromEmail',['../classWebUsers.html#aee8d6b322defc5dfe8e47f382becca62',1,'WebUsers\getIdFromEmail($email)'],['../classWebUsers.html#aee8d6b322defc5dfe8e47f382becca62',1,'WebUsers\getIdFromEmail($email)']]], - ['getimap_5fmailserver',['getIMAP_MailServer',['../classSupport__Group.html#a30d67354e52f95489b93923440ff0661',1,'Support_Group']]], - ['getimap_5fpassword',['getIMAP_Password',['../classSupport__Group.html#a4983db184794db8f05ce93f5ba11ba7e',1,'Support_Group']]], - ['getimap_5fusername',['getIMAP_Username',['../classSupport__Group.html#a0ace9f66f2541d29e060cb7728030e93',1,'Support_Group']]], - ['getinfo',['getInfo',['../classWebUsers.html#a164026f74736817927e1cacd282a2e28',1,'WebUsers\getInfo()'],['../classWebUsers.html#a164026f74736817927e1cacd282a2e28',1,'WebUsers\getInfo()']]], - ['getlanguage',['getLanguage',['../classWebUsers.html#afcef2403c4111bc44ef0530f1e493909',1,'WebUsers\getLanguage()'],['../classWebUsers.html#afcef2403c4111bc44ef0530f1e493909',1,'WebUsers\getLanguage()']]], - ['getlast',['getLast',['../classPagination.html#a9316ede6960667d832997c8e20223623',1,'Pagination']]], - ['getlatestreply',['getLatestReply',['../classTicket.html#a3a4ce7e9c445dd245b3370304d0afd92',1,'Ticket']]], - ['getlinks',['getLinks',['../classPagination.html#aeecf550e63b55ecd5d737ecc46e07d3a',1,'Pagination']]], - ['getlocal_5faddress',['getLocal_Address',['../classTicket__Info.html#a49b4c851eff2f3d06531a39baa8423f5',1,'Ticket_Info']]], - ['getlogsofticket',['getLogsOfTicket',['../classTicket__Log.html#a37ad4d95b0bb2d5a6dfc2dd7c3744292',1,'Ticket_Log']]], - ['getmemory',['getMemory',['../classTicket__Info.html#a144248575cd034a40315155a9b48ff87',1,'Ticket_Info']]], - ['getmodsandadmins',['getModsAndAdmins',['../classTicket__User.html#a71099747902fb7e064ec1d4128ea4576',1,'Ticket_User']]], - ['getname',['getName',['../classSupport__Group.html#a3d0963e68bb313b163a73f2803c64600',1,'Support_Group\getName()'],['../classTicket__Category.html#a3d0963e68bb313b163a73f2803c64600',1,'Ticket_Category\getName()']]], - ['getnel3d',['getNel3D',['../classTicket__Info.html#abe3ae528bfd5495720c3adeff59fe11e',1,'Ticket_Info']]], - ['getnewestticket',['getNewestTicket',['../classTicket__Queue__Handler.html#ab5a79318a0c771083f03400093b3b2ec',1,'Ticket_Queue_Handler']]], - ['getnroftickets',['getNrOfTickets',['../classTicket__Queue__Handler.html#ada8f87ed8466c5e0477fa20359c3c8ad',1,'Ticket_Queue_Handler']]], - ['getnrofticketsassignedwaiting',['getNrOfTicketsAssignedWaiting',['../classTicket__Queue__Handler.html#a0d3daaaf5c79188eb62bb3adda11fa2a',1,'Ticket_Queue_Handler']]], - ['getnrofticketstodo',['getNrOfTicketsToDo',['../classTicket__Queue__Handler.html#ae8d1a2a66991583c05c173147e8dc657',1,'Ticket_Queue_Handler']]], - ['getos',['getOS',['../classTicket__Info.html#a9a1b88474ad97701d67a752d0c4d65c5',1,'Ticket_Info']]], - ['getpagination',['getPagination',['../classTicket__Queue__Handler.html#ab45a102a508e9727b108e8f24486c464',1,'Ticket_Queue_Handler']]], - ['getparams',['getParams',['../classTicket__Queue.html#ae32cd7c32721b02d676bb63b4b1366db',1,'Ticket_Queue']]], - ['getpatch_5fversion',['getPatch_Version',['../classTicket__Info.html#a6e41e115b03a1f152bd2c28c77d5fbac',1,'Ticket_Info']]], - ['getpermission',['getPermission',['../classTicket__User.html#a478067ecf173884c2ee3e5b94e746200',1,'Ticket_User']]], - ['getpriority',['getPriority',['../classTicket.html#a1e7a3c168dcd0901a0d2669c67575b55',1,'Ticket']]], - ['getpriorityarray',['getPriorityArray',['../classTicket.html#a509625cccc0b41f4ab3a658df705b3dc',1,'Ticket']]], - ['getprioritytext',['getPriorityText',['../classTicket.html#ae07f7808a12f2789593722f3293bd105',1,'Ticket']]], - ['getprocessor',['getProcessor',['../classTicket__Info.html#a3ace868ad456ff61f545cb44ee01c562',1,'Ticket_Info']]], - ['getquery',['getQuery',['../classQuerycache.html#a55f162785567258fe5138af282e588c2',1,'Querycache\getQuery()'],['../classTicket__Log.html#a55f162785567258fe5138af282e588c2',1,'Ticket_Log\getQuery()'],['../classTicket__Queue.html#a55f162785567258fe5138af282e588c2',1,'Ticket_Queue\getQuery()']]], - ['getqueue',['getQueue',['../classTicket.html#aa7a8055e5ee1eb792f29443ddb79c4d3',1,'Ticket']]], - ['getreceivemail',['getReceiveMail',['../classWebUsers.html#ae4680f622bd8d571530615fb616d37e7',1,'WebUsers\getReceiveMail()'],['../classWebUsers.html#ae4680f622bd8d571530615fb616d37e7',1,'WebUsers\getReceiveMail()']]], - ['getrepliesofticket',['getRepliesOfTicket',['../classTicket__Reply.html#a7e80a6437bb6ee90be42a32f3a82fe76',1,'Ticket_Reply']]], - ['getserver_5ftick',['getServer_Tick',['../classTicket__Info.html#a5a5799e4e54d3fa4858716b4464710c0',1,'Ticket_Info']]], - ['getsgroupid',['getSGroupId',['../classSupport__Group.html#a77d0961efe9609ebb268f8672e71bba4',1,'Support_Group']]], - ['getsgroupofticket',['getSGroupOfTicket',['../classForwarded.html#a4de002d45322cf62ce493f49933d33bd',1,'Forwarded']]], - ['getshardid',['getShardId',['../classTicket__Info.html#a36306b5367015050fb516fcaaff8351f',1,'Ticket_Info']]], - ['getsid',['getSID',['../classQuerycache.html#a5bac91964d19751986cccad6fad28dda',1,'Querycache']]], - ['getstatus',['getStatus',['../classTicket.html#a9d21636071f529e2154051d3ea6e5921',1,'Ticket']]], - ['getstatusarray',['getStatusArray',['../classTicket.html#aa728c6a1f8ddd7030acbf5a4ca913b50',1,'Ticket']]], - ['getstatustext',['getStatusText',['../classTicket.html#aab26af198dc3a59295747084b85435ff',1,'Ticket']]], - ['gettag',['getTag',['../classSupport__Group.html#ab86ba36154b20e6bbfa3ba705f12f9d6',1,'Support_Group']]], - ['gettcategoryid',['getTCategoryId',['../classTicket__Category.html#acb530a119e5e52230a92ece95cc7ec82',1,'Ticket_Category']]], - ['gettcontentid',['getTContentId',['../classTicket__Content.html#a9245dceab917ad08e5244c9395b347ae',1,'Ticket_Content']]], - ['getticket',['getTicket',['../classAssigned.html#a42ddf34a72af750b7013fa309b67e46c',1,'Assigned\getTicket()'],['../classForwarded.html#a42ddf34a72af750b7013fa309b67e46c',1,'Forwarded\getTicket()'],['../classTicket__Info.html#a42ddf34a72af750b7013fa309b67e46c',1,'Ticket_Info\getTicket()'],['../classTicket__Log.html#a42ddf34a72af750b7013fa309b67e46c',1,'Ticket_Log\getTicket()'],['../classTicket__Reply.html#a42ddf34a72af750b7013fa309b67e46c',1,'Ticket_Reply\getTicket()']]], - ['getticket_5fcategory',['getTicket_Category',['../classTicket.html#addff2fc457fe07664f4eb39efcea45f9',1,'Ticket']]], - ['gettickets',['getTickets',['../classTicket__Queue__Handler.html#a45e8c11ba9485041fa92c7c470a8f9f9',1,'Ticket_Queue_Handler']]], - ['getticketsof',['getTicketsOf',['../classTicket.html#aa426904463cd0eb50d9b2f4becdd242f',1,'Ticket']]], - ['gettid',['getTId',['../classTicket.html#aa7af74696d9898008992c494cec136dd',1,'Ticket']]], - ['gettimestamp',['getTimestamp',['../classTicket.html#a92aa1d82129ec8cd803d64c28efcb30f',1,'Ticket\getTimestamp()'],['../classTicket__Log.html#a92aa1d82129ec8cd803d64c28efcb30f',1,'Ticket_Log\getTimestamp()'],['../classTicket__Reply.html#a92aa1d82129ec8cd803d64c28efcb30f',1,'Ticket_Reply\getTimestamp()']]], - ['gettinfoid',['getTInfoId',['../classTicket__Info.html#ad7c7ccc1926763c252d32d1fee5a7f69',1,'Ticket_Info']]], - ['gettitle',['getTitle',['../classTicket.html#a95e859a4588a39a1824b717378a84c29',1,'Ticket']]], - ['gettlogid',['getTLogId',['../classTicket__Log.html#ab174d340ee116d8cc3aa377003421fc5',1,'Ticket_Log']]], - ['gettreplyid',['getTReplyId',['../classTicket__Reply.html#ade0c35755c1a1af8fa4c9bae8b4c51f1',1,'Ticket_Reply']]], - ['gettuserid',['getTUserId',['../classTicket__User.html#a4a31c27c61f9794200b647bf810461f5',1,'Ticket_User']]], - ['gettype',['getType',['../classQuerycache.html#a830b5c75df72b32396701bc563fbe3c7',1,'Querycache']]], - ['getuid',['getUId',['../classWebUsers.html#aa36a98da4146d85e7813e99df7d97497',1,'WebUsers\getUId()'],['../classWebUsers.html#aa36a98da4146d85e7813e99df7d97497',1,'WebUsers\getUId()']]], - ['getuser',['getUser',['../classAssigned.html#ae81b7186fb97a7c6457edcc68c9aa2ef',1,'Assigned\getUser()'],['../classIn__Support__Group.html#ae81b7186fb97a7c6457edcc68c9aa2ef',1,'In_Support_Group\getUser()']]], - ['getuser_5fid',['getUser_Id',['../classTicket__Info.html#a9c2fe31c14609e2255773d5a4dd154d8',1,'Ticket_Info']]], - ['getuser_5fposition',['getUser_Position',['../classTicket__Info.html#a3f5a46d846543219d6321d2f8751d1f0',1,'Ticket_Info']]], - ['getuserassignedtoticket',['getUserAssignedToTicket',['../classAssigned.html#afcfb156712a9477a97423a49238d13c5',1,'Assigned']]], - ['getusername',['getUsername',['../classWebUsers.html#a81b37a3c9d639574e394f80c1138c75e',1,'WebUsers\getUsername()'],['../classWebUsers.html#a81b37a3c9d639574e394f80c1138c75e',1,'WebUsers\getUsername()']]], - ['getusers',['getUsers',['../classWebUsers.html#a0fc10b64683021b70c7eb95fb514c119',1,'WebUsers\getUsers()'],['../classWebUsers.html#a0fc10b64683021b70c7eb95fb514c119',1,'WebUsers\getUsers()']]], - ['getview_5fposition',['getView_Position',['../classTicket__Info.html#a525dbd26fc788c7c152f6c686a9a5d11',1,'Ticket_Info']]], - ['gui_5felements',['Gui_Elements',['../classGui__Elements.html',1,'']]], - ['gui_5felements_2ephp',['gui_elements.php',['../gui__elements_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_68.html b/code/web/docs/ams/html/search/all_68.html deleted file mode 100644 index 6df909782..000000000 --- a/code/web/docs/ams/html/search/all_68.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_68.js b/code/web/docs/ams/html/search/all_68.js deleted file mode 100644 index 551ff1628..000000000 --- a/code/web/docs/ams/html/search/all_68.js +++ /dev/null @@ -1,8 +0,0 @@ -var searchData= -[ - ['handle_5flanguage',['handle_language',['../classHelpers.html#a334920d0652c160c6145d3bd7be31a22',1,'Helpers']]], - ['hashiv',['hashIV',['../classMyCrypt.html#a1bdf94a5906655bf0965338c9d17ab27',1,'MyCrypt']]], - ['hasinfo',['hasInfo',['../classTicket.html#afca07df3cc25a0e1a15d3f69bd6afa62',1,'Ticket']]], - ['helpers',['Helpers',['../classHelpers.html',1,'']]], - ['helpers_2ephp',['helpers.php',['../helpers_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_69.html b/code/web/docs/ams/html/search/all_69.html deleted file mode 100644 index 1a00b554d..000000000 --- a/code/web/docs/ams/html/search/all_69.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_69.js b/code/web/docs/ams/html/search/all_69.js deleted file mode 100644 index a0e19a9ec..000000000 --- a/code/web/docs/ams/html/search/all_69.js +++ /dev/null @@ -1,14 +0,0 @@ -var searchData= -[ - ['in_5fsupport_5fgroup',['In_Support_Group',['../classIn__Support__Group.html',1,'']]], - ['in_5fsupport_5fgroup_2ephp',['in_support_group.php',['../in__support__group_8php.html',1,'']]], - ['incoming_5fmail_5fhandler',['incoming_mail_handler',['../classMail__Handler.html#a2896dabadb8e435de7ba7bbb258f8a96',1,'Mail_Handler']]], - ['index_2ephp',['index.php',['../index_8php.html',1,'']]], - ['info_2ephp',['info.php',['../info_8php.html',1,'']]], - ['install_2ephp',['install.php',['../install_8php.html',1,'']]], - ['isadmin',['isAdmin',['../classTicket__User.html#ae8a7d91474cde916fced2127fab426d2',1,'Ticket_User']]], - ['isassigned',['isAssigned',['../classAssigned.html#ade127364a5e5635077119b7217b6059c',1,'Assigned']]], - ['isforwarded',['isForwarded',['../classForwarded.html#ac1fa2045188edf04b07c523e1c6f68a0',1,'Forwarded']]], - ['isloggedin',['isLoggedIn',['../classWebUsers.html#a33bdd79e5da367ebddd4cfbdbbfc7cff',1,'WebUsers\isLoggedIn()'],['../classWebUsers.html#a33bdd79e5da367ebddd4cfbdbbfc7cff',1,'WebUsers\isLoggedIn()']]], - ['ismod',['isMod',['../classTicket__User.html#a8d88cdbf205bf7d24be03157d25bb7d8',1,'Ticket_User']]] -]; diff --git a/code/web/docs/ams/html/search/all_6c.html b/code/web/docs/ams/html/search/all_6c.html deleted file mode 100644 index f6383cc22..000000000 --- a/code/web/docs/ams/html/search/all_6c.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_6c.js b/code/web/docs/ams/html/search/all_6c.js deleted file mode 100644 index d76ada768..000000000 --- a/code/web/docs/ams/html/search/all_6c.js +++ /dev/null @@ -1,28 +0,0 @@ -var searchData= -[ - ['libinclude_2ephp',['libinclude.php',['../libinclude_8php.html',1,'']]], - ['load',['load',['../classAssigned.html#a689011be59ec3d216ebe6852f07ab37f',1,'Assigned\load()'],['../classForwarded.html#a689011be59ec3d216ebe6852f07ab37f',1,'Forwarded\load()']]], - ['load_5fwith_5fsgroupid',['load_With_SGroupId',['../classSupport__Group.html#a6beae177f45da42a57b100b5481f49bf',1,'Support_Group']]], - ['load_5fwith_5fsid',['load_With_SID',['../classQuerycache.html#ae960510ccb242704233c38d787242f53',1,'Querycache']]], - ['load_5fwith_5ftcategoryid',['load_With_TCategoryId',['../classTicket__Category.html#ab3a70940917530d91a39536a6d45a21d',1,'Ticket_Category']]], - ['load_5fwith_5ftcontentid',['load_With_TContentId',['../classTicket__Content.html#ad8b1226537a055701bcc3fe4af87257b',1,'Ticket_Content']]], - ['load_5fwith_5fticket',['load_With_Ticket',['../classTicket__Info.html#afcf4006cdd19b05919b5df34d3345ad2',1,'Ticket_Info']]], - ['load_5fwith_5ftid',['load_With_TId',['../classTicket.html#ac17d9e1158fb77707da1f6cd3e425d54',1,'Ticket']]], - ['load_5fwith_5ftinfoid',['load_With_TInfoId',['../classTicket__Info.html#a1681685f76483b7944bf6848b29caa4a',1,'Ticket_Info']]], - ['load_5fwith_5ftlogid',['load_With_TLogId',['../classTicket__Log.html#a76e8e991002c7e408f7b182556cdeade',1,'Ticket_Log']]], - ['load_5fwith_5ftreplyid',['load_With_TReplyId',['../classTicket__Reply.html#ac9a387c63aad0b81a8161d2515f697d9',1,'Ticket_Reply']]], - ['load_5fwith_5ftuserid',['load_With_TUserId',['../classTicket__User.html#af43df1ba39e073e4b3a0120e6e4d3140',1,'Ticket_User']]], - ['loadallclosedtickets',['loadAllClosedTickets',['../classTicket__Queue.html#af2a9b20ac9dc0e1992f717abbb418be7',1,'Ticket_Queue']]], - ['loadallnotassignedtickets',['loadAllNotAssignedTickets',['../classTicket__Queue.html#a771627a0bd387cd666474a6ef0d5eaaf',1,'Ticket_Queue']]], - ['loadallopentickets',['loadAllOpenTickets',['../classTicket__Queue.html#a3a1cf8a88a3604e093f7d276050f1c49',1,'Ticket_Queue']]], - ['loadalltickets',['loadAllTickets',['../classTicket__Queue.html#a80542bde30a8a589f1d088422cb7719b',1,'Ticket_Queue']]], - ['loadassignedandwaiting',['loadAssignedandWaiting',['../classTicket__Queue.html#a348c76f7ae32437b7e91b57671d6f33d',1,'Ticket_Queue']]], - ['loadtemplate',['loadTemplate',['../classHelpers.html#a78997ab39ba0237dc7a5441b58601211',1,'Helpers']]], - ['loadtodotickets',['loadToDoTickets',['../classTicket__Queue.html#ad88848edf9a9132eb0cfcac904a8459f',1,'Ticket_Queue']]], - ['login',['login',['../func_2login_8php.html#aa311da27ba5706f5710cea7706c8eae1',1,'login(): login.php'],['../inc_2login_8php.html#aa311da27ba5706f5710cea7706c8eae1',1,'login(): login.php']]], - ['login_2ephp',['login.php',['../func_2login_8php.html',1,'']]], - ['login_2ephp',['login.php',['../inc_2login_8php.html',1,'']]], - ['logout',['logout',['../drupal__module_2ryzommanage_2inc_2logout_8php.html#a082405d89acd6835c3a7c7a08a7adbab',1,'logout(): logout.php'],['../www_2html_2inc_2logout_8php.html#a082405d89acd6835c3a7c7a08a7adbab',1,'logout(): logout.php']]], - ['logout_2ephp',['logout.php',['../www_2html_2inc_2logout_8php.html',1,'']]], - ['logout_2ephp',['logout.php',['../drupal__module_2ryzommanage_2inc_2logout_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_6d.html b/code/web/docs/ams/html/search/all_6d.html deleted file mode 100644 index 2e27d4d64..000000000 --- a/code/web/docs/ams/html/search/all_6d.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_6d.js b/code/web/docs/ams/html/search/all_6d.js deleted file mode 100644 index fb08a60ab..000000000 --- a/code/web/docs/ams/html/search/all_6d.js +++ /dev/null @@ -1,13 +0,0 @@ -var searchData= -[ - ['mail_5fcron_2ephp',['mail_cron.php',['../mail__cron_8php.html',1,'']]], - ['mail_5ffork',['mail_fork',['../classMail__Handler.html#ac6f9bcfab65cc93fdd4723284fff6b7a',1,'Mail_Handler']]], - ['mail_5fhandler',['Mail_Handler',['../classMail__Handler.html',1,'']]], - ['mail_5fhandler_2ephp',['mail_handler.php',['../mail__handler_8php.html',1,'']]], - ['make_5ftable',['make_table',['../classGui__Elements.html#a639930203d81ff01840ac90a51cbbfe7',1,'Gui_Elements']]], - ['make_5ftable_5fwith_5fkey_5fis_5fid',['make_table_with_key_is_id',['../classGui__Elements.html#ae3c8c19fce4cdd7d87d4ae759ab06f24',1,'Gui_Elements']]], - ['modify_5femail_5fof_5fsgroup',['modify_email_of_sgroup',['../modify__email__of__sgroup_8php.html#acb8c4a7ad3e36662d1d22ba56a98d0ab',1,'modify_email_of_sgroup.php']]], - ['modify_5femail_5fof_5fsgroup_2ephp',['modify_email_of_sgroup.php',['../modify__email__of__sgroup_8php.html',1,'']]], - ['mycrypt',['MyCrypt',['../classMyCrypt.html',1,'']]], - ['mycrypt_2ephp',['mycrypt.php',['../mycrypt_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_6e.html b/code/web/docs/ams/html/search/all_6e.html deleted file mode 100644 index 1f92ee5b6..000000000 --- a/code/web/docs/ams/html/search/all_6e.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_6e.js b/code/web/docs/ams/html/search/all_6e.js deleted file mode 100644 index 0831ed960..000000000 --- a/code/web/docs/ams/html/search/all_6e.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['new_5fmessage_5fid',['new_message_id',['../classMail__Handler.html#a667ca75b6c659157d855c3d19978a436',1,'Mail_Handler']]] -]; diff --git a/code/web/docs/ams/html/search/all_6f.html b/code/web/docs/ams/html/search/all_6f.html deleted file mode 100644 index 61827e82e..000000000 --- a/code/web/docs/ams/html/search/all_6f.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_6f.js b/code/web/docs/ams/html/search/all_6f.js deleted file mode 100644 index f8a8b3016..000000000 --- a/code/web/docs/ams/html/search/all_6f.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['outputtime',['outputTime',['../classHelpers.html#a4370c805a72fe32c03b178b03ad2e393',1,'Helpers']]] -]; diff --git a/code/web/docs/ams/html/search/all_70.html b/code/web/docs/ams/html/search/all_70.html deleted file mode 100644 index 0340151b6..000000000 --- a/code/web/docs/ams/html/search/all_70.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_70.js b/code/web/docs/ams/html/search/all_70.js deleted file mode 100644 index e09f3f7d0..000000000 --- a/code/web/docs/ams/html/search/all_70.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['pagination',['Pagination',['../classPagination.html',1,'']]], - ['pagination_2ephp',['pagination.php',['../pagination_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_71.html b/code/web/docs/ams/html/search/all_71.html deleted file mode 100644 index b4dc1e6ee..000000000 --- a/code/web/docs/ams/html/search/all_71.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_71.js b/code/web/docs/ams/html/search/all_71.js deleted file mode 100644 index 8b0805dd8..000000000 --- a/code/web/docs/ams/html/search/all_71.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['querycache',['Querycache',['../classQuerycache.html',1,'']]], - ['querycache_2ephp',['querycache.php',['../querycache_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_72.html b/code/web/docs/ams/html/search/all_72.html deleted file mode 100644 index 0ab18d65f..000000000 --- a/code/web/docs/ams/html/search/all_72.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_72.js b/code/web/docs/ams/html/search/all_72.js deleted file mode 100644 index ece0a9538..000000000 --- a/code/web/docs/ams/html/search/all_72.js +++ /dev/null @@ -1,7 +0,0 @@ -var searchData= -[ - ['register',['register',['../register_8php.html#acc294a6cc8e69743746820e3d15e3f78',1,'register.php']]], - ['register_2ephp',['register.php',['../register_8php.html',1,'']]], - ['reply_5fon_5fticket',['reply_on_ticket',['../reply__on__ticket_8php.html#a79f0a445c77e8e1e59eb9e72cbf39dba',1,'reply_on_ticket.php']]], - ['reply_5fon_5fticket_2ephp',['reply_on_ticket.php',['../reply__on__ticket_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_73.html b/code/web/docs/ams/html/search/all_73.html deleted file mode 100644 index 1ec8f174d..000000000 --- a/code/web/docs/ams/html/search/all_73.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_73.js b/code/web/docs/ams/html/search/all_73.js deleted file mode 100644 index aee17ff0a..000000000 --- a/code/web/docs/ams/html/search/all_73.js +++ /dev/null @@ -1,90 +0,0 @@ -var searchData= -[ - ['send_5fmail',['send_mail',['../classMail__Handler.html#a50308ad0711aee080dacef7e3f574699',1,'Mail_Handler']]], - ['send_5fticketing_5fmail',['send_ticketing_mail',['../classMail__Handler.html#abe649044c8b8bd8eb05787a401865e6d',1,'Mail_Handler']]], - ['set',['set',['../classAssigned.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Assigned\set()'],['../classForwarded.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Forwarded\set()'],['../classIn__Support__Group.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'In_Support_Group\set()'],['../classQuerycache.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Querycache\set()'],['../classSupport__Group.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Support_Group\set()'],['../classTicket.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket\set()'],['../classTicket__Info.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_Info\set()'],['../classTicket__Log.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_Log\set()'],['../classTicket__Reply.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_Reply\set()'],['../classTicket__User.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_User\set()'],['../classWebUsers.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'WebUsers\set($values)'],['../classWebUsers.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'WebUsers\set($values)']]], - ['setamsemail',['setAmsEmail',['../classUsers.html#ad1cbb1fe6ee72f46dc385bec6e274363',1,'Users']]], - ['setamspassword',['setAmsPassword',['../classUsers.html#ab89812058b0a71baf492af4652d67501',1,'Users']]], - ['setauthor',['setAuthor',['../classTicket.html#a0c8f116992af7c8737c70119dae00d45',1,'Ticket\setAuthor()'],['../classTicket__Log.html#a0c8f116992af7c8737c70119dae00d45',1,'Ticket_Log\setAuthor()'],['../classTicket__Reply.html#a0c8f116992af7c8737c70119dae00d45',1,'Ticket_Reply\setAuthor()']]], - ['setclient_5fversion',['setClient_Version',['../classTicket__Info.html#af06e75f73ae40120cc371f6ddd9ab49c',1,'Ticket_Info']]], - ['setconnect_5fstate',['setConnect_State',['../classTicket__Info.html#a4de823fc3a051d3aac3d526badef313c',1,'Ticket_Info']]], - ['setcontent',['setContent',['../classTicket__Content.html#a76e94f05c5cc0044993a35492097df4d',1,'Ticket_Content\setContent()'],['../classTicket__Reply.html#a76e94f05c5cc0044993a35492097df4d',1,'Ticket_Reply\setContent()']]], - ['setcpu_5fmask',['setCPU_Mask',['../classTicket__Info.html#a5f19999ab39a2ac0b7d6f2ced9223ae6',1,'Ticket_Info']]], - ['setcpuid',['setCPUId',['../classTicket__Info.html#af1f04d3bdcbaf28b246eb94a484f397c',1,'Ticket_Info']]], - ['setdb',['setDb',['../classQuerycache.html#afa9c249972ca269a2b1a399ed2faf9b4',1,'Querycache']]], - ['setemail',['setEmail',['../classWebUsers.html#a0cd214763f395718db166fbd598689f4',1,'WebUsers\setEmail($user, $mail)'],['../classWebUsers.html#a0cd214763f395718db166fbd598689f4',1,'WebUsers\setEmail($user, $mail)']]], - ['setexternid',['setExternId',['../classTicket__User.html#ad38846bb954052a5293ae2d26cf810d2',1,'Ticket_User']]], - ['setgroup',['setGroup',['../classForwarded.html#a3116db27c2e2f33cbb10a9488db34da3',1,'Forwarded\setGroup()'],['../classIn__Support__Group.html#a3116db27c2e2f33cbb10a9488db34da3',1,'In_Support_Group\setGroup()']]], - ['setgroupemail',['setGroupEmail',['../classSupport__Group.html#abbb0e975fd21a42439970ebb3eba5fea',1,'Support_Group']]], - ['sethidden',['setHidden',['../classTicket__Reply.html#a0b67f1016974c7b153b8944a94c88045',1,'Ticket_Reply']]], - ['setht',['setHT',['../classTicket__Info.html#a9ef93ff2fede4bd9b1cb8da2129dee20',1,'Ticket_Info']]], - ['setimap_5fmailserver',['setIMAP_MailServer',['../classSupport__Group.html#a71f266f2bba1fc4fb6df4cf083988938',1,'Support_Group']]], - ['setimap_5fpassword',['setIMAP_Password',['../classSupport__Group.html#ad6fcb63d4ae129567e8bea8786a75d87',1,'Support_Group']]], - ['setimap_5fusername',['setIMAP_Username',['../classSupport__Group.html#a6856519261b543f27bc001616c2881eb',1,'Support_Group']]], - ['setlanguage',['setLanguage',['../classWebUsers.html#a5ab1bd5f0959a3c33a46c176d9412c80',1,'WebUsers\setLanguage($user, $language)'],['../classWebUsers.html#a5ab1bd5f0959a3c33a46c176d9412c80',1,'WebUsers\setLanguage($user, $language)']]], - ['setlocal_5faddress',['setLocal_Address',['../classTicket__Info.html#a144b42f39cea6b24624c6c547df6aeeb',1,'Ticket_Info']]], - ['setmemory',['setMemory',['../classTicket__Info.html#a6f6f6925a18d24d2ecd5166a325be609',1,'Ticket_Info']]], - ['setname',['setName',['../classSupport__Group.html#aa3dcc220094e19fef1f918a3a917dba7',1,'Support_Group\setName()'],['../classTicket__Category.html#aa3dcc220094e19fef1f918a3a917dba7',1,'Ticket_Category\setName()']]], - ['setnel3d',['setNel3D',['../classTicket__Info.html#a77fbf6da57aa02e075be0905dc6cdd48',1,'Ticket_Info']]], - ['setos',['setOS',['../classTicket__Info.html#aacb7cbb0f04959ae64ba1c3aac36df54',1,'Ticket_Info']]], - ['setpassword',['setPassword',['../classWebUsers.html#a91506e5f74c9884045e865ef7c314fed',1,'WebUsers\setPassword($user, $pass)'],['../classWebUsers.html#a91506e5f74c9884045e865ef7c314fed',1,'WebUsers\setPassword($user, $pass)']]], - ['setpatch_5fversion',['setPatch_Version',['../classTicket__Info.html#a1d0f55ed3b50a72bf882591474d2ff72',1,'Ticket_Info']]], - ['setpermission',['setPermission',['../classTicket__User.html#adf7c497fb026ee6e05f6ece91f541839',1,'Ticket_User']]], - ['setpriority',['setPriority',['../classTicket.html#a3080d0b46978a8f82022bbb6e5fc0c1c',1,'Ticket']]], - ['setprocessor',['setProcessor',['../classTicket__Info.html#a8b66f72ec1928b89058cd0a9b4dd8c11',1,'Ticket_Info']]], - ['setquery',['setQuery',['../classQuerycache.html#adbd6075ec5d3bd84122e52b0134ed8e7',1,'Querycache\setQuery()'],['../classTicket__Log.html#adbd6075ec5d3bd84122e52b0134ed8e7',1,'Ticket_Log\setQuery()']]], - ['setqueue',['setQueue',['../classTicket.html#a1595d3fe708fe4f453922054407a1c03',1,'Ticket']]], - ['setreceivemail',['setReceiveMail',['../classWebUsers.html#aa0f439ff7a5cd6377a557f545fbeb45c',1,'WebUsers\setReceiveMail($user, $receivemail)'],['../classWebUsers.html#aa0f439ff7a5cd6377a557f545fbeb45c',1,'WebUsers\setReceiveMail($user, $receivemail)']]], - ['setserver_5ftick',['setServer_Tick',['../classTicket__Info.html#ab6ff52082590b43d90f8f37fd5b31086',1,'Ticket_Info']]], - ['setsgroupid',['setSGroupId',['../classSupport__Group.html#aa49cb914be98fc354a45584c6f2b8be1',1,'Support_Group']]], - ['setshardid',['setShardId',['../classTicket__Info.html#a4026e593012113e253b80e3bbd5f6c13',1,'Ticket_Info']]], - ['setsid',['setSID',['../classQuerycache.html#a2f536a1f8c8e463eb0346ac375f2a24d',1,'Querycache']]], - ['setstatus',['setStatus',['../classTicket.html#a66605893c4afc9855f1e0cf8ccccac09',1,'Ticket']]], - ['settag',['setTag',['../classSupport__Group.html#a4de944a53debc51843530fe96296f220',1,'Support_Group']]], - ['settcategoryid',['setTCategoryId',['../classTicket__Category.html#a39a64c3f7ab33ba3f5a67c31647e889f',1,'Ticket_Category']]], - ['settcontentid',['setTContentId',['../classTicket__Content.html#ae07366727208e060372063e96591c5d4',1,'Ticket_Content']]], - ['setticket',['setTicket',['../classAssigned.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Assigned\setTicket()'],['../classForwarded.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Forwarded\setTicket()'],['../classTicket__Info.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Ticket_Info\setTicket()'],['../classTicket__Log.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Ticket_Log\setTicket()'],['../classTicket__Reply.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Ticket_Reply\setTicket()']]], - ['setticket_5fcategory',['setTicket_Category',['../classTicket.html#a4e38b2a263b5a934b76cd77f026308c3',1,'Ticket']]], - ['settid',['setTId',['../classTicket.html#a8c72dc7b09645b390043f5a4664e7c7f',1,'Ticket']]], - ['settimestamp',['setTimestamp',['../classTicket.html#a4e05995d5cc78cdc9ffe72d864811ac6',1,'Ticket\setTimestamp()'],['../classTicket__Log.html#aa8903a0020a17d745524806f4e751f4c',1,'Ticket_Log\setTimestamp()'],['../classTicket__Reply.html#aa8903a0020a17d745524806f4e751f4c',1,'Ticket_Reply\setTimestamp()']]], - ['settinfoid',['setTInfoId',['../classTicket__Info.html#a5e98fba0b50f74645a2fdaa8f4d0c1ea',1,'Ticket_Info']]], - ['settings',['settings',['../drupal__module_2ryzommanage_2inc_2settings_8php.html#ad7354383714c6ae99d6ee1bfb95ab49f',1,'settings(): settings.php'],['../www_2html_2inc_2settings_8php.html#ad7354383714c6ae99d6ee1bfb95ab49f',1,'settings(): settings.php']]], - ['settings_2ephp',['settings.php',['../drupal__module_2ryzommanage_2inc_2settings_8php.html',1,'']]], - ['settings_2ephp',['settings.php',['../www_2html_2inc_2settings_8php.html',1,'']]], - ['settitle',['setTitle',['../classTicket.html#ac765da6fa83b06ea39c0edc9b3e6c6c0',1,'Ticket']]], - ['settlogid',['setTLogId',['../classTicket__Log.html#aca708aae8c7320e11d9e08936ec74dec',1,'Ticket_Log']]], - ['settreplyid',['setTReplyId',['../classTicket__Reply.html#a7b91b481de87eb1515212d62b298cb94',1,'Ticket_Reply']]], - ['settuserid',['setTUserId',['../classTicket__User.html#a0faf8954e86346e7b566870b1a3c0a4a',1,'Ticket_User']]], - ['settype',['setType',['../classQuerycache.html#a0f29af8d4b9fdd8959739727a33acee5',1,'Querycache']]], - ['setuser',['setUser',['../classAssigned.html#af560ca7f201e2f871384a150e8ffd9aa',1,'Assigned\setUser()'],['../classIn__Support__Group.html#af560ca7f201e2f871384a150e8ffd9aa',1,'In_Support_Group\setUser()']]], - ['setuser_5fid',['setUser_Id',['../classTicket__Info.html#aec77405f6e096f2c0493383724f33034',1,'Ticket_Info']]], - ['setuser_5fposition',['setUser_Position',['../classTicket__Info.html#a41cfb7786d3252b2ec7aec42d77add9f',1,'Ticket_Info']]], - ['setview_5fposition',['setView_Position',['../classTicket__Info.html#a58912ec04451ab232d88bd78b6a8c2ea',1,'Ticket_Info']]], - ['sgroup_5flist',['sgroup_list',['../sgroup__list_8php.html#ab3af46486585b0ddced2de27a5d7a000',1,'sgroup_list.php']]], - ['sgroup_5flist_2ephp',['sgroup_list.php',['../sgroup__list_8php.html',1,'']]], - ['show_5fqueue',['show_queue',['../show__queue_8php.html#a48695b07fef725dbf0b4f261b1fe1547',1,'show_queue.php']]], - ['show_5fqueue_2ephp',['show_queue.php',['../show__queue_8php.html',1,'']]], - ['show_5freply',['show_reply',['../show__reply_8php.html#ad8e51d3b3a4bf996fb07199a08ca9a3e',1,'show_reply.php']]], - ['show_5freply_2ephp',['show_reply.php',['../show__reply_8php.html',1,'']]], - ['show_5fsgroup',['show_sgroup',['../show__sgroup_8php.html#a118719426cb30ed43e39c2af24cfea2d',1,'show_sgroup.php']]], - ['show_5fsgroup_2ephp',['show_sgroup.php',['../show__sgroup_8php.html',1,'']]], - ['show_5fticket',['show_ticket',['../show__ticket_8php.html#a1249d6cae97f6949ce3a7754fa1b7016',1,'show_ticket.php']]], - ['show_5fticket_2ephp',['show_ticket.php',['../show__ticket_8php.html',1,'']]], - ['show_5fticket_5finfo',['show_ticket_info',['../show__ticket__info_8php.html#a579a5c89b55189455a8237369a78f0d8',1,'show_ticket_info.php']]], - ['show_5fticket_5finfo_2ephp',['show_ticket_info.php',['../show__ticket__info_8php.html',1,'']]], - ['show_5fticket_5flog',['show_ticket_log',['../show__ticket__log_8php.html#ab37298a659581e85338601f2259ead49',1,'show_ticket_log.php']]], - ['show_5fticket_5flog_2ephp',['show_ticket_log.php',['../show__ticket__log_8php.html',1,'']]], - ['show_5fuser',['show_user',['../drupal__module_2ryzommanage_2inc_2show__user_8php.html#ac755ca62882d4caca41c7822793b8812',1,'show_user(): show_user.php'],['../www_2html_2inc_2show__user_8php.html#ac755ca62882d4caca41c7822793b8812',1,'show_user(): show_user.php']]], - ['show_5fuser_2ephp',['show_user.php',['../drupal__module_2ryzommanage_2inc_2show__user_8php.html',1,'']]], - ['show_5fuser_2ephp',['show_user.php',['../www_2html_2inc_2show__user_8php.html',1,'']]], - ['support_5fgroup',['Support_Group',['../classSupport__Group.html',1,'']]], - ['support_5fgroup_2ephp',['support_group.php',['../support__group_8php.html',1,'']]], - ['supportgroup_5fentrynotexists',['supportGroup_EntryNotExists',['../classSupport__Group.html#aa557f337f57a3bb530f1f04df78c0f1e',1,'Support_Group']]], - ['supportgroup_5fexists',['supportGroup_Exists',['../classSupport__Group.html#ac235662693dcc9c2be51e6f1a2c426b6',1,'Support_Group']]], - ['sync',['Sync',['../classSync.html',1,'']]], - ['sync_2ephp',['sync.php',['../sync_8php.html',1,'']]], - ['sync_5fcron_2ephp',['sync_cron.php',['../sync__cron_8php.html',1,'']]], - ['syncdata',['syncdata',['../classSync.html#ad1211cc677b7aafcc4ebcc25f3cacdda',1,'Sync']]], - ['syncing',['syncing',['../syncing_8php.html#a8d4df31796dab54a8d0c9c9ec32cf7f9',1,'syncing.php']]], - ['syncing_2ephp',['syncing.php',['../syncing_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_74.html b/code/web/docs/ams/html/search/all_74.html deleted file mode 100644 index fdc6589d0..000000000 --- a/code/web/docs/ams/html/search/all_74.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_74.js b/code/web/docs/ams/html/search/all_74.js deleted file mode 100644 index 4c4c97839..000000000 --- a/code/web/docs/ams/html/search/all_74.js +++ /dev/null @@ -1,24 +0,0 @@ -var searchData= -[ - ['ticket',['Ticket',['../classTicket.html',1,'']]], - ['ticket_2ephp',['ticket.php',['../ticket_8php.html',1,'']]], - ['ticket_5fcategory',['Ticket_Category',['../classTicket__Category.html',1,'']]], - ['ticket_5fcategory_2ephp',['ticket_category.php',['../ticket__category_8php.html',1,'']]], - ['ticket_5fcontent',['Ticket_Content',['../classTicket__Content.html',1,'']]], - ['ticket_5fcontent_2ephp',['ticket_content.php',['../ticket__content_8php.html',1,'']]], - ['ticket_5finfo',['Ticket_Info',['../classTicket__Info.html',1,'']]], - ['ticket_5finfo_2ephp',['ticket_info.php',['../ticket__info_8php.html',1,'']]], - ['ticket_5flog',['Ticket_Log',['../classTicket__Log.html',1,'']]], - ['ticket_5flog_2ephp',['ticket_log.php',['../ticket__log_8php.html',1,'']]], - ['ticket_5fqueue',['Ticket_Queue',['../classTicket__Queue.html',1,'']]], - ['ticket_5fqueue_2ephp',['ticket_queue.php',['../ticket__queue_8php.html',1,'']]], - ['ticket_5fqueue_5fhandler',['Ticket_Queue_Handler',['../classTicket__Queue__Handler.html',1,'']]], - ['ticket_5fqueue_5fhandler_2ephp',['ticket_queue_handler.php',['../ticket__queue__handler_8php.html',1,'']]], - ['ticket_5freply',['Ticket_Reply',['../classTicket__Reply.html',1,'']]], - ['ticket_5freply_2ephp',['ticket_reply.php',['../ticket__reply_8php.html',1,'']]], - ['ticket_5fuser',['Ticket_User',['../classTicket__User.html',1,'']]], - ['ticket_5fuser_2ephp',['ticket_user.php',['../ticket__user_8php.html',1,'']]], - ['ticketexists',['ticketExists',['../classTicket.html#a091d7ec56d4dc4bf980b81e8069b76d0',1,'Ticket']]], - ['tickethasinfo',['TicketHasInfo',['../classTicket__Info.html#a361217eb1d85e13aa534dabfbbd64a86',1,'Ticket_Info']]], - ['time_5felapsed_5fstring',['time_elapsed_string',['../classGui__Elements.html#a04d9bc70e65231a470426f0a94b7583d',1,'Gui_Elements']]] -]; diff --git a/code/web/docs/ams/html/search/all_75.html b/code/web/docs/ams/html/search/all_75.html deleted file mode 100644 index ab8455ed5..000000000 --- a/code/web/docs/ams/html/search/all_75.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_75.js b/code/web/docs/ams/html/search/all_75.js deleted file mode 100644 index ad5f4cb36..000000000 --- a/code/web/docs/ams/html/search/all_75.js +++ /dev/null @@ -1,12 +0,0 @@ -var searchData= -[ - ['unassignticket',['unAssignTicket',['../classAssigned.html#a8263a9c223957bb558a2c16d4431ca29',1,'Assigned\unAssignTicket()'],['../classTicket.html#a8263a9c223957bb558a2c16d4431ca29',1,'Ticket\unAssignTicket()']]], - ['update',['update',['../classQuerycache.html#a842e4774e3b3601a005b995c02f7e883',1,'Querycache\update()'],['../classSupport__Group.html#a842e4774e3b3601a005b995c02f7e883',1,'Support_Group\update()'],['../classTicket.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket\update()'],['../classTicket__Category.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Category\update()'],['../classTicket__Content.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Content\update()'],['../classTicket__Log.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Log\update()'],['../classTicket__Reply.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Reply\update()'],['../classTicket__User.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_User\update()']]], - ['updateticketstatus',['updateTicketStatus',['../classTicket.html#a6da2625040e9f06c583e9303082c556f',1,'Ticket']]], - ['updateticketstatusandpriority',['updateTicketStatusAndPriority',['../classTicket.html#a64f08c8987c9eb00d4bfc9ef94e45326',1,'Ticket']]], - ['userexistsinsgroup',['userExistsInSGroup',['../classIn__Support__Group.html#a1a25afa24efc6c01ffd236f735281543',1,'In_Support_Group']]], - ['userlist',['userlist',['../userlist_8php.html#a55709a05f18e09358e2b02531eb859ad',1,'userlist.php']]], - ['userlist_2ephp',['userlist.php',['../userlist_8php.html',1,'']]], - ['users',['Users',['../classUsers.html',1,'']]], - ['users_2ephp',['users.php',['../users_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/all_76.html b/code/web/docs/ams/html/search/all_76.html deleted file mode 100644 index 0ff5edd34..000000000 --- a/code/web/docs/ams/html/search/all_76.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_76.js b/code/web/docs/ams/html/search/all_76.js deleted file mode 100644 index 1566125d3..000000000 --- a/code/web/docs/ams/html/search/all_76.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['validemail',['validEmail',['../classUsers.html#a73637e760498c5cea55074896ec982ac',1,'Users']]] -]; diff --git a/code/web/docs/ams/html/search/all_77.html b/code/web/docs/ams/html/search/all_77.html deleted file mode 100644 index 73323d316..000000000 --- a/code/web/docs/ams/html/search/all_77.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/all_77.js b/code/web/docs/ams/html/search/all_77.js deleted file mode 100644 index 5a36cb483..000000000 --- a/code/web/docs/ams/html/search/all_77.js +++ /dev/null @@ -1,7 +0,0 @@ -var searchData= -[ - ['webusers',['WebUsers',['../classWebUsers.html',1,'']]], - ['webusers_2ephp',['webusers.php',['../drupal__module_2ryzommanage_2autoload_2webusers_8php.html',1,'']]], - ['webusers_2ephp',['webusers.php',['../www_2html_2autoload_2webusers_8php.html',1,'']]], - ['write_5fuser',['write_user',['../add__user_8php.html#a09df49f177966f5b08af71ec43760e0c',1,'add_user.php']]] -]; diff --git a/code/web/docs/ams/html/search/classes_61.html b/code/web/docs/ams/html/search/classes_61.html deleted file mode 100644 index 85e5d72a3..000000000 --- a/code/web/docs/ams/html/search/classes_61.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_61.js b/code/web/docs/ams/html/search/classes_61.js deleted file mode 100644 index 39d4914a1..000000000 --- a/code/web/docs/ams/html/search/classes_61.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['assigned',['Assigned',['../classAssigned.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_64.html b/code/web/docs/ams/html/search/classes_64.html deleted file mode 100644 index 590270830..000000000 --- a/code/web/docs/ams/html/search/classes_64.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_64.js b/code/web/docs/ams/html/search/classes_64.js deleted file mode 100644 index db9b214c1..000000000 --- a/code/web/docs/ams/html/search/classes_64.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['dblayer',['DBLayer',['../classDBLayer.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_66.html b/code/web/docs/ams/html/search/classes_66.html deleted file mode 100644 index 941988c65..000000000 --- a/code/web/docs/ams/html/search/classes_66.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_66.js b/code/web/docs/ams/html/search/classes_66.js deleted file mode 100644 index 518614d90..000000000 --- a/code/web/docs/ams/html/search/classes_66.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['forwarded',['Forwarded',['../classForwarded.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_67.html b/code/web/docs/ams/html/search/classes_67.html deleted file mode 100644 index 78b514df0..000000000 --- a/code/web/docs/ams/html/search/classes_67.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_67.js b/code/web/docs/ams/html/search/classes_67.js deleted file mode 100644 index e85658e41..000000000 --- a/code/web/docs/ams/html/search/classes_67.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['gui_5felements',['Gui_Elements',['../classGui__Elements.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_68.html b/code/web/docs/ams/html/search/classes_68.html deleted file mode 100644 index 475eeb738..000000000 --- a/code/web/docs/ams/html/search/classes_68.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_68.js b/code/web/docs/ams/html/search/classes_68.js deleted file mode 100644 index 9e86cb7a3..000000000 --- a/code/web/docs/ams/html/search/classes_68.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['helpers',['Helpers',['../classHelpers.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_69.html b/code/web/docs/ams/html/search/classes_69.html deleted file mode 100644 index 961dbea27..000000000 --- a/code/web/docs/ams/html/search/classes_69.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_69.js b/code/web/docs/ams/html/search/classes_69.js deleted file mode 100644 index 49e6133b0..000000000 --- a/code/web/docs/ams/html/search/classes_69.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['in_5fsupport_5fgroup',['In_Support_Group',['../classIn__Support__Group.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_6d.html b/code/web/docs/ams/html/search/classes_6d.html deleted file mode 100644 index abe6f0d1d..000000000 --- a/code/web/docs/ams/html/search/classes_6d.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_6d.js b/code/web/docs/ams/html/search/classes_6d.js deleted file mode 100644 index ae1e0f417..000000000 --- a/code/web/docs/ams/html/search/classes_6d.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['mail_5fhandler',['Mail_Handler',['../classMail__Handler.html',1,'']]], - ['mycrypt',['MyCrypt',['../classMyCrypt.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_70.html b/code/web/docs/ams/html/search/classes_70.html deleted file mode 100644 index e4b520874..000000000 --- a/code/web/docs/ams/html/search/classes_70.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_70.js b/code/web/docs/ams/html/search/classes_70.js deleted file mode 100644 index 157d7c6b6..000000000 --- a/code/web/docs/ams/html/search/classes_70.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['pagination',['Pagination',['../classPagination.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_71.html b/code/web/docs/ams/html/search/classes_71.html deleted file mode 100644 index 80a4fbb83..000000000 --- a/code/web/docs/ams/html/search/classes_71.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_71.js b/code/web/docs/ams/html/search/classes_71.js deleted file mode 100644 index e2ca060ac..000000000 --- a/code/web/docs/ams/html/search/classes_71.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['querycache',['Querycache',['../classQuerycache.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_73.html b/code/web/docs/ams/html/search/classes_73.html deleted file mode 100644 index a1bf0b912..000000000 --- a/code/web/docs/ams/html/search/classes_73.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_73.js b/code/web/docs/ams/html/search/classes_73.js deleted file mode 100644 index 8941e45df..000000000 --- a/code/web/docs/ams/html/search/classes_73.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['support_5fgroup',['Support_Group',['../classSupport__Group.html',1,'']]], - ['sync',['Sync',['../classSync.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_74.html b/code/web/docs/ams/html/search/classes_74.html deleted file mode 100644 index f7f27cea7..000000000 --- a/code/web/docs/ams/html/search/classes_74.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_74.js b/code/web/docs/ams/html/search/classes_74.js deleted file mode 100644 index 90ec7727d..000000000 --- a/code/web/docs/ams/html/search/classes_74.js +++ /dev/null @@ -1,12 +0,0 @@ -var searchData= -[ - ['ticket',['Ticket',['../classTicket.html',1,'']]], - ['ticket_5fcategory',['Ticket_Category',['../classTicket__Category.html',1,'']]], - ['ticket_5fcontent',['Ticket_Content',['../classTicket__Content.html',1,'']]], - ['ticket_5finfo',['Ticket_Info',['../classTicket__Info.html',1,'']]], - ['ticket_5flog',['Ticket_Log',['../classTicket__Log.html',1,'']]], - ['ticket_5fqueue',['Ticket_Queue',['../classTicket__Queue.html',1,'']]], - ['ticket_5fqueue_5fhandler',['Ticket_Queue_Handler',['../classTicket__Queue__Handler.html',1,'']]], - ['ticket_5freply',['Ticket_Reply',['../classTicket__Reply.html',1,'']]], - ['ticket_5fuser',['Ticket_User',['../classTicket__User.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_75.html b/code/web/docs/ams/html/search/classes_75.html deleted file mode 100644 index 807d7426e..000000000 --- a/code/web/docs/ams/html/search/classes_75.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_75.js b/code/web/docs/ams/html/search/classes_75.js deleted file mode 100644 index 432c5d270..000000000 --- a/code/web/docs/ams/html/search/classes_75.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['users',['Users',['../classUsers.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/classes_77.html b/code/web/docs/ams/html/search/classes_77.html deleted file mode 100644 index e3967e972..000000000 --- a/code/web/docs/ams/html/search/classes_77.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/classes_77.js b/code/web/docs/ams/html/search/classes_77.js deleted file mode 100644 index 0e579ee3d..000000000 --- a/code/web/docs/ams/html/search/classes_77.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['webusers',['WebUsers',['../classWebUsers.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/close.png b/code/web/docs/ams/html/search/close.png deleted file mode 100644 index 9342d3dfeea7b7c4ee610987e717804b5a42ceb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 273 zcmV+s0q*{ZP)4(RlMby96)VwnbG{ zbe&}^BDn7x>$<{ck4zAK-=nT;=hHG)kmplIF${xqm8db3oX6wT3bvp`TE@m0cg;b) zBuSL}5?N7O(iZLdAlz@)b)Rd~DnSsSX&P5qC`XwuFwcAYLC+d2>+1(8on;wpt8QIC X2MT$R4iQDd00000NkvXXu0mjfia~GN diff --git a/code/web/docs/ams/html/search/files_61.html b/code/web/docs/ams/html/search/files_61.html deleted file mode 100644 index 5a8e45499..000000000 --- a/code/web/docs/ams/html/search/files_61.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_61.js b/code/web/docs/ams/html/search/files_61.js deleted file mode 100644 index db9b27c9e..000000000 --- a/code/web/docs/ams/html/search/files_61.js +++ /dev/null @@ -1,7 +0,0 @@ -var searchData= -[ - ['add_5fsgroup_2ephp',['add_sgroup.php',['../add__sgroup_8php.html',1,'']]], - ['add_5fuser_2ephp',['add_user.php',['../add__user_8php.html',1,'']]], - ['add_5fuser_5fto_5fsgroup_2ephp',['add_user_to_sgroup.php',['../add__user__to__sgroup_8php.html',1,'']]], - ['assigned_2ephp',['assigned.php',['../assigned_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_63.html b/code/web/docs/ams/html/search/files_63.html deleted file mode 100644 index 6611a5b91..000000000 --- a/code/web/docs/ams/html/search/files_63.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_63.js b/code/web/docs/ams/html/search/files_63.js deleted file mode 100644 index 47c38c050..000000000 --- a/code/web/docs/ams/html/search/files_63.js +++ /dev/null @@ -1,12 +0,0 @@ -var searchData= -[ - ['change_5finfo_2ephp',['change_info.php',['../change__info_8php.html',1,'']]], - ['change_5fmail_2ephp',['change_mail.php',['../change__mail_8php.html',1,'']]], - ['change_5fpassword_2ephp',['change_password.php',['../change__password_8php.html',1,'']]], - ['change_5fpermission_2ephp',['change_permission.php',['../change__permission_8php.html',1,'']]], - ['change_5freceivemail_2ephp',['change_receivemail.php',['../change__receivemail_8php.html',1,'']]], - ['config_2ephp',['config.php',['../www_2config_8php.html',1,'']]], - ['config_2ephp',['config.php',['../drupal__module_2ryzommanage_2config_8php.html',1,'']]], - ['create_5fticket_2ephp',['create_ticket.php',['../create__ticket_8php.html',1,'']]], - ['createticket_2ephp',['createticket.php',['../createticket_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_64.html b/code/web/docs/ams/html/search/files_64.html deleted file mode 100644 index 1a32bf882..000000000 --- a/code/web/docs/ams/html/search/files_64.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_64.js b/code/web/docs/ams/html/search/files_64.js deleted file mode 100644 index 8307e204b..000000000 --- a/code/web/docs/ams/html/search/files_64.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['dashboard_2ephp',['dashboard.php',['../dashboard_8php.html',1,'']]], - ['dblayer_2ephp',['dblayer.php',['../dblayer_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_65.html b/code/web/docs/ams/html/search/files_65.html deleted file mode 100644 index 1eadd1b02..000000000 --- a/code/web/docs/ams/html/search/files_65.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_65.js b/code/web/docs/ams/html/search/files_65.js deleted file mode 100644 index ec7451ee2..000000000 --- a/code/web/docs/ams/html/search/files_65.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['error_2ephp',['error.php',['../error_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_66.html b/code/web/docs/ams/html/search/files_66.html deleted file mode 100644 index c05640363..000000000 --- a/code/web/docs/ams/html/search/files_66.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_66.js b/code/web/docs/ams/html/search/files_66.js deleted file mode 100644 index ab77df41b..000000000 --- a/code/web/docs/ams/html/search/files_66.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['forwarded_2ephp',['forwarded.php',['../forwarded_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_67.html b/code/web/docs/ams/html/search/files_67.html deleted file mode 100644 index d5df283f3..000000000 --- a/code/web/docs/ams/html/search/files_67.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_67.js b/code/web/docs/ams/html/search/files_67.js deleted file mode 100644 index e6e52c243..000000000 --- a/code/web/docs/ams/html/search/files_67.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['gui_5felements_2ephp',['gui_elements.php',['../gui__elements_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_68.html b/code/web/docs/ams/html/search/files_68.html deleted file mode 100644 index 8ead5893f..000000000 --- a/code/web/docs/ams/html/search/files_68.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_68.js b/code/web/docs/ams/html/search/files_68.js deleted file mode 100644 index 05d1801f3..000000000 --- a/code/web/docs/ams/html/search/files_68.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['helpers_2ephp',['helpers.php',['../helpers_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_69.html b/code/web/docs/ams/html/search/files_69.html deleted file mode 100644 index 7fbd757cd..000000000 --- a/code/web/docs/ams/html/search/files_69.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_69.js b/code/web/docs/ams/html/search/files_69.js deleted file mode 100644 index 74065c1ec..000000000 --- a/code/web/docs/ams/html/search/files_69.js +++ /dev/null @@ -1,7 +0,0 @@ -var searchData= -[ - ['in_5fsupport_5fgroup_2ephp',['in_support_group.php',['../in__support__group_8php.html',1,'']]], - ['index_2ephp',['index.php',['../index_8php.html',1,'']]], - ['info_2ephp',['info.php',['../info_8php.html',1,'']]], - ['install_2ephp',['install.php',['../install_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_6c.html b/code/web/docs/ams/html/search/files_6c.html deleted file mode 100644 index 642a54585..000000000 --- a/code/web/docs/ams/html/search/files_6c.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_6c.js b/code/web/docs/ams/html/search/files_6c.js deleted file mode 100644 index 3b8359fc2..000000000 --- a/code/web/docs/ams/html/search/files_6c.js +++ /dev/null @@ -1,8 +0,0 @@ -var searchData= -[ - ['libinclude_2ephp',['libinclude.php',['../libinclude_8php.html',1,'']]], - ['login_2ephp',['login.php',['../inc_2login_8php.html',1,'']]], - ['login_2ephp',['login.php',['../func_2login_8php.html',1,'']]], - ['logout_2ephp',['logout.php',['../www_2html_2inc_2logout_8php.html',1,'']]], - ['logout_2ephp',['logout.php',['../drupal__module_2ryzommanage_2inc_2logout_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_6d.html b/code/web/docs/ams/html/search/files_6d.html deleted file mode 100644 index d9d93006b..000000000 --- a/code/web/docs/ams/html/search/files_6d.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_6d.js b/code/web/docs/ams/html/search/files_6d.js deleted file mode 100644 index b19770b9b..000000000 --- a/code/web/docs/ams/html/search/files_6d.js +++ /dev/null @@ -1,7 +0,0 @@ -var searchData= -[ - ['mail_5fcron_2ephp',['mail_cron.php',['../mail__cron_8php.html',1,'']]], - ['mail_5fhandler_2ephp',['mail_handler.php',['../mail__handler_8php.html',1,'']]], - ['modify_5femail_5fof_5fsgroup_2ephp',['modify_email_of_sgroup.php',['../modify__email__of__sgroup_8php.html',1,'']]], - ['mycrypt_2ephp',['mycrypt.php',['../mycrypt_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_70.html b/code/web/docs/ams/html/search/files_70.html deleted file mode 100644 index abcae9a6f..000000000 --- a/code/web/docs/ams/html/search/files_70.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_70.js b/code/web/docs/ams/html/search/files_70.js deleted file mode 100644 index f1c0593fa..000000000 --- a/code/web/docs/ams/html/search/files_70.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['pagination_2ephp',['pagination.php',['../pagination_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_71.html b/code/web/docs/ams/html/search/files_71.html deleted file mode 100644 index bb4ccc7cc..000000000 --- a/code/web/docs/ams/html/search/files_71.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_71.js b/code/web/docs/ams/html/search/files_71.js deleted file mode 100644 index c2eeb72ca..000000000 --- a/code/web/docs/ams/html/search/files_71.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['querycache_2ephp',['querycache.php',['../querycache_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_72.html b/code/web/docs/ams/html/search/files_72.html deleted file mode 100644 index 609fb48fc..000000000 --- a/code/web/docs/ams/html/search/files_72.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_72.js b/code/web/docs/ams/html/search/files_72.js deleted file mode 100644 index 721d27957..000000000 --- a/code/web/docs/ams/html/search/files_72.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['register_2ephp',['register.php',['../register_8php.html',1,'']]], - ['reply_5fon_5fticket_2ephp',['reply_on_ticket.php',['../reply__on__ticket_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_73.html b/code/web/docs/ams/html/search/files_73.html deleted file mode 100644 index e0de9e6b5..000000000 --- a/code/web/docs/ams/html/search/files_73.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_73.js b/code/web/docs/ams/html/search/files_73.js deleted file mode 100644 index 2ce5655bb..000000000 --- a/code/web/docs/ams/html/search/files_73.js +++ /dev/null @@ -1,18 +0,0 @@ -var searchData= -[ - ['settings_2ephp',['settings.php',['../drupal__module_2ryzommanage_2inc_2settings_8php.html',1,'']]], - ['settings_2ephp',['settings.php',['../www_2html_2inc_2settings_8php.html',1,'']]], - ['sgroup_5flist_2ephp',['sgroup_list.php',['../sgroup__list_8php.html',1,'']]], - ['show_5fqueue_2ephp',['show_queue.php',['../show__queue_8php.html',1,'']]], - ['show_5freply_2ephp',['show_reply.php',['../show__reply_8php.html',1,'']]], - ['show_5fsgroup_2ephp',['show_sgroup.php',['../show__sgroup_8php.html',1,'']]], - ['show_5fticket_2ephp',['show_ticket.php',['../show__ticket_8php.html',1,'']]], - ['show_5fticket_5finfo_2ephp',['show_ticket_info.php',['../show__ticket__info_8php.html',1,'']]], - ['show_5fticket_5flog_2ephp',['show_ticket_log.php',['../show__ticket__log_8php.html',1,'']]], - ['show_5fuser_2ephp',['show_user.php',['../www_2html_2inc_2show__user_8php.html',1,'']]], - ['show_5fuser_2ephp',['show_user.php',['../drupal__module_2ryzommanage_2inc_2show__user_8php.html',1,'']]], - ['support_5fgroup_2ephp',['support_group.php',['../support__group_8php.html',1,'']]], - ['sync_2ephp',['sync.php',['../sync_8php.html',1,'']]], - ['sync_5fcron_2ephp',['sync_cron.php',['../sync__cron_8php.html',1,'']]], - ['syncing_2ephp',['syncing.php',['../syncing_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_74.html b/code/web/docs/ams/html/search/files_74.html deleted file mode 100644 index 017b3fe9f..000000000 --- a/code/web/docs/ams/html/search/files_74.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_74.js b/code/web/docs/ams/html/search/files_74.js deleted file mode 100644 index 47b5068e4..000000000 --- a/code/web/docs/ams/html/search/files_74.js +++ /dev/null @@ -1,12 +0,0 @@ -var searchData= -[ - ['ticket_2ephp',['ticket.php',['../ticket_8php.html',1,'']]], - ['ticket_5fcategory_2ephp',['ticket_category.php',['../ticket__category_8php.html',1,'']]], - ['ticket_5fcontent_2ephp',['ticket_content.php',['../ticket__content_8php.html',1,'']]], - ['ticket_5finfo_2ephp',['ticket_info.php',['../ticket__info_8php.html',1,'']]], - ['ticket_5flog_2ephp',['ticket_log.php',['../ticket__log_8php.html',1,'']]], - ['ticket_5fqueue_2ephp',['ticket_queue.php',['../ticket__queue_8php.html',1,'']]], - ['ticket_5fqueue_5fhandler_2ephp',['ticket_queue_handler.php',['../ticket__queue__handler_8php.html',1,'']]], - ['ticket_5freply_2ephp',['ticket_reply.php',['../ticket__reply_8php.html',1,'']]], - ['ticket_5fuser_2ephp',['ticket_user.php',['../ticket__user_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_75.html b/code/web/docs/ams/html/search/files_75.html deleted file mode 100644 index 8ea7b3d4b..000000000 --- a/code/web/docs/ams/html/search/files_75.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_75.js b/code/web/docs/ams/html/search/files_75.js deleted file mode 100644 index 2d05f2341..000000000 --- a/code/web/docs/ams/html/search/files_75.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['userlist_2ephp',['userlist.php',['../userlist_8php.html',1,'']]], - ['users_2ephp',['users.php',['../users_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/files_77.html b/code/web/docs/ams/html/search/files_77.html deleted file mode 100644 index 69f689782..000000000 --- a/code/web/docs/ams/html/search/files_77.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/files_77.js b/code/web/docs/ams/html/search/files_77.js deleted file mode 100644 index 5c7ec501b..000000000 --- a/code/web/docs/ams/html/search/files_77.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['webusers_2ephp',['webusers.php',['../drupal__module_2ryzommanage_2autoload_2webusers_8php.html',1,'']]], - ['webusers_2ephp',['webusers.php',['../www_2html_2autoload_2webusers_8php.html',1,'']]] -]; diff --git a/code/web/docs/ams/html/search/functions_5f.html b/code/web/docs/ams/html/search/functions_5f.html deleted file mode 100644 index cb54e927d..000000000 --- a/code/web/docs/ams/html/search/functions_5f.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_5f.js b/code/web/docs/ams/html/search/functions_5f.js deleted file mode 100644 index 844048eb7..000000000 --- a/code/web/docs/ams/html/search/functions_5f.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['_5f_5fautoload',['__autoload',['../libinclude_8php.html#a2ecfde85f554ea0b3fef0993aef304a9',1,'libinclude.php']]], - ['_5f_5fconstruct',['__construct',['../classAssigned.html#a095c5d389db211932136b53f25f39685',1,'Assigned\__construct()'],['../classDBLayer.html#a800f8efee13692788b13ee57c5960092',1,'DBLayer\__construct()'],['../classForwarded.html#a095c5d389db211932136b53f25f39685',1,'Forwarded\__construct()'],['../classIn__Support__Group.html#a095c5d389db211932136b53f25f39685',1,'In_Support_Group\__construct()'],['../classMyCrypt.html#af200cbfd49bfea2fecf5629ab2361033',1,'MyCrypt\__construct()'],['../classPagination.html#a2a1aecb8f526796b3d62e8278edc07c3',1,'Pagination\__construct()'],['../classQuerycache.html#a095c5d389db211932136b53f25f39685',1,'Querycache\__construct()'],['../classSupport__Group.html#a095c5d389db211932136b53f25f39685',1,'Support_Group\__construct()'],['../classTicket.html#a095c5d389db211932136b53f25f39685',1,'Ticket\__construct()'],['../classTicket__Category.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Category\__construct()'],['../classTicket__Content.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Content\__construct()'],['../classTicket__Info.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Info\__construct()'],['../classTicket__Log.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Log\__construct()'],['../classTicket__Queue__Handler.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Queue_Handler\__construct()'],['../classTicket__Reply.html#a095c5d389db211932136b53f25f39685',1,'Ticket_Reply\__construct()'],['../classTicket__User.html#a095c5d389db211932136b53f25f39685',1,'Ticket_User\__construct()'],['../classWebUsers.html#a4e63742e531873e01e1e97dd7530539b',1,'WebUsers\__construct($UId=0)'],['../classWebUsers.html#a4e63742e531873e01e1e97dd7530539b',1,'WebUsers\__construct($UId=0)']]] -]; diff --git a/code/web/docs/ams/html/search/functions_61.html b/code/web/docs/ams/html/search/functions_61.html deleted file mode 100644 index 7f395337e..000000000 --- a/code/web/docs/ams/html/search/functions_61.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_61.js b/code/web/docs/ams/html/search/functions_61.js deleted file mode 100644 index 8bc0ff34b..000000000 --- a/code/web/docs/ams/html/search/functions_61.js +++ /dev/null @@ -1,8 +0,0 @@ -var searchData= -[ - ['add_5fsgroup',['add_sgroup',['../add__sgroup_8php.html#a45490c056bdd114ef28893fc29286d2b',1,'add_sgroup.php']]], - ['add_5fuser',['add_user',['../add__user_8php.html#a69e8de25de7560db0292bb474882a489',1,'add_user.php']]], - ['add_5fuser_5fto_5fsgroup',['add_user_to_sgroup',['../add__user__to__sgroup_8php.html#a6ad0c5a1bfd563e11a107bf0023b6150',1,'add_user_to_sgroup.php']]], - ['addusertosupportgroup',['addUserToSupportGroup',['../classSupport__Group.html#a4616317379ffef08dbaeea2a9dbba02c',1,'Support_Group']]], - ['assignticket',['assignTicket',['../classAssigned.html#a51c3d5b6f78de455619581fd3e591f17',1,'Assigned\assignTicket()'],['../classTicket.html#a51c3d5b6f78de455619581fd3e591f17',1,'Ticket\assignTicket()']]] -]; diff --git a/code/web/docs/ams/html/search/functions_63.html b/code/web/docs/ams/html/search/functions_63.html deleted file mode 100644 index 9ebe11d69..000000000 --- a/code/web/docs/ams/html/search/functions_63.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_63.js b/code/web/docs/ams/html/search/functions_63.js deleted file mode 100644 index dfdf9b93d..000000000 --- a/code/web/docs/ams/html/search/functions_63.js +++ /dev/null @@ -1,42 +0,0 @@ -var searchData= -[ - ['change_5finfo',['change_info',['../change__info_8php.html#a1bbc74a7da07012d55b0b45726534265',1,'change_info.php']]], - ['change_5fmail',['change_mail',['../change__mail_8php.html#a03d0bca67a96c8744bd74623e128ab83',1,'change_mail.php']]], - ['change_5fpassword',['change_password',['../change__password_8php.html#a888360ab43db15eba1d5cc3623d4100f',1,'change_password.php']]], - ['change_5fpermission',['change_permission',['../classTicket__User.html#a78d4d6de74b1ee26cb9192f36e022416',1,'Ticket_User\change_permission()'],['../change__permission_8php.html#a9ad639fafd67bdc579cf3170cd0d26e7',1,'change_permission(): change_permission.php']]], - ['change_5freceivemail',['change_receivemail',['../change__receivemail_8php.html#a22ae748f60d7b4200dce30c94a52c421',1,'change_receivemail.php']]], - ['check_5fchange_5fpassword',['check_change_password',['../classUsers.html#a9c78408d50465957eeb8068810315a8e',1,'Users']]], - ['check_5fif_5fgame_5fclient',['check_if_game_client',['../classHelpers.html#a4e3e5309a66456d81a1effdabcc9cd79',1,'Helpers']]], - ['check_5flogin_5fingame',['check_login_ingame',['../classHelpers.html#abd01528a1145831a4fc98eae7ffaca36',1,'Helpers']]], - ['check_5fmethods',['check_methods',['../classMyCrypt.html#ad72fefc790b0bb1ac6edc252427b0970',1,'MyCrypt']]], - ['check_5fregister',['check_Register',['../classUsers.html#a740de04dc3aa7cf3bed959540ffab8f8',1,'Users']]], - ['checkemail',['checkEmail',['../classUsers.html#a76646237ab053cdde386c06aa5437d8a',1,'Users']]], - ['checkemailexists',['checkEmailExists',['../classUsers.html#a37275e677004927b6b1a30e16c5b5b38',1,'Users\checkEmailExists()'],['../classWebUsers.html#a37275e677004927b6b1a30e16c5b5b38',1,'WebUsers\checkEmailExists($email)'],['../classWebUsers.html#a37275e677004927b6b1a30e16c5b5b38',1,'WebUsers\checkEmailExists($email)']]], - ['checkloginmatch',['checkLoginMatch',['../classUsers.html#af0b98012abb190cf4617999f008de27e',1,'Users\checkLoginMatch()'],['../classWebUsers.html#a11894eb69bb2f172baf5186e8f92246d',1,'WebUsers\checkLoginMatch($username, $password)'],['../classWebUsers.html#a11894eb69bb2f172baf5186e8f92246d',1,'WebUsers\checkLoginMatch($username, $password)']]], - ['checkpassword',['checkPassword',['../classUsers.html#a4cb5e34b56fb6de0ec318fb59e90838f',1,'Users']]], - ['checkuser',['checkUser',['../classUsers.html#adfffce17947a9f72d68838db250c9ab8',1,'Users']]], - ['checkusernameexists',['checkUserNameExists',['../classUsers.html#ac3a8cb9a038f6aef0bd98be091274122',1,'Users\checkUserNameExists()'],['../classWebUsers.html#ac3a8cb9a038f6aef0bd98be091274122',1,'WebUsers\checkUserNameExists($username)'],['../classWebUsers.html#ac3a8cb9a038f6aef0bd98be091274122',1,'WebUsers\checkUserNameExists($username)']]], - ['confirmpassword',['confirmPassword',['../classUsers.html#a2f5349025bed3874f08d80652cab2fe0',1,'Users']]], - ['constr_5fexternid',['constr_ExternId',['../classTicket__User.html#a4e5c577ed0a9da4b1c56397912f02ba0',1,'Ticket_User']]], - ['constr_5fsgroupid',['constr_SGroupId',['../classSupport__Group.html#a873beb80bd0b5d572704cdb6d2ec34eb',1,'Support_Group']]], - ['constr_5ftcategoryid',['constr_TCategoryId',['../classTicket__Category.html#a332d2dd59b46fc933a3c9a1b2967803a',1,'Ticket_Category']]], - ['constr_5ftcontentid',['constr_TContentId',['../classTicket__Content.html#aa28ad9a063c1914ff75d19afd25c707f',1,'Ticket_Content']]], - ['constr_5ftlogid',['constr_TLogId',['../classTicket__Log.html#a001ec13f64bb026b1c8a3b3bd02ee22b',1,'Ticket_Log']]], - ['constr_5ftreplyid',['constr_TReplyId',['../classTicket__Reply.html#a4b4493d28e8518a87667d285c49e5e24',1,'Ticket_Reply']]], - ['constr_5ftuserid',['constr_TUserId',['../classTicket__User.html#a10939bce9b667f26d3827993b4e3df1d',1,'Ticket_User']]], - ['create',['create',['../classAssigned.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Assigned\create()'],['../classForwarded.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Forwarded\create()'],['../classIn__Support__Group.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'In_Support_Group\create()'],['../classSupport__Group.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Support_Group\create()'],['../classTicket.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket\create()'],['../classTicket__Content.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket_Content\create()'],['../classTicket__Info.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket_Info\create()'],['../classTicket__Reply.html#a435e7d7525d4bcd0ed5e34a469f3adf6',1,'Ticket_Reply\create()']]], - ['create_5ffolders',['create_folders',['../classHelpers.html#add8ef9ce82106c505f6f04c2a8e3b2b4',1,'Helpers']]], - ['create_5fticket',['create_Ticket',['../classTicket.html#a81b3285033bc3c9e89adfa8da34d61de',1,'Ticket\create_Ticket()'],['../create__ticket_8php.html#a65bcbfccf737c72927d15c06783cd9f4',1,'create_ticket(): create_ticket.php']]], - ['create_5fticket_5finfo',['create_Ticket_Info',['../classTicket__Info.html#aaa4e26c92338b70e874135af9c02bba9',1,'Ticket_Info']]], - ['createlogentry',['createLogEntry',['../classTicket__Log.html#a345a2da9c23780c7e6aef7134baa1749',1,'Ticket_Log']]], - ['createpermissions',['createPermissions',['../classUsers.html#aeac9f32fd53c97c92e5c774e154399df',1,'Users']]], - ['createqueue',['createQueue',['../classTicket__Queue.html#af077496b6071af47c19a873bf025c1f3',1,'Ticket_Queue\createQueue()'],['../classTicket__Queue__Handler.html#af077496b6071af47c19a873bf025c1f3',1,'Ticket_Queue_Handler\createQueue()']]], - ['createreply',['createReply',['../classTicket.html#af6568341f5052034440f79c0e74707a3',1,'Ticket\createReply()'],['../classTicket__Reply.html#aa6fa056fff4ddafc3eabf3ed72143e1b',1,'Ticket_Reply\createReply()']]], - ['createsupportgroup',['createSupportGroup',['../classSupport__Group.html#a31ee7c68c0ffb77438bb9ff095962568',1,'Support_Group']]], - ['createticket',['createticket',['../createticket_8php.html#aa8253d883a3ba14c6449a13ed2bb9c8f',1,'createticket.php']]], - ['createticketcategory',['createTicketCategory',['../classTicket__Category.html#a506fc7f32de9547e91a5dbb68c391907',1,'Ticket_Category']]], - ['createticketuser',['createTicketUser',['../classTicket__User.html#a37c416f7d3723874f3ac49c7f9f5a21c',1,'Ticket_User']]], - ['createuser',['createUser',['../classUsers.html#ac93aebf1960fb12975b120a2c394a8af',1,'Users']]], - ['createwebuser',['createWebuser',['../classWebUsers.html#a0cb7168a6b8358106512804ff28cea17',1,'WebUsers\createWebuser($name, $pass, $mail)'],['../classWebUsers.html#a0cb7168a6b8358106512804ff28cea17',1,'WebUsers\createWebuser($name, $pass, $mail)']]], - ['cron',['cron',['../classMail__Handler.html#a1b65890aa4eb8c0c6129c3e787a53405',1,'Mail_Handler']]] -]; diff --git a/code/web/docs/ams/html/search/functions_64.html b/code/web/docs/ams/html/search/functions_64.html deleted file mode 100644 index d8b63943c..000000000 --- a/code/web/docs/ams/html/search/functions_64.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_64.js b/code/web/docs/ams/html/search/functions_64.js deleted file mode 100644 index da5e1ad06..000000000 --- a/code/web/docs/ams/html/search/functions_64.js +++ /dev/null @@ -1,9 +0,0 @@ -var searchData= -[ - ['dashboard',['dashboard',['../dashboard_8php.html#a54d0c80ff20df9df6439bb87608c375a',1,'dashboard.php']]], - ['decode_5futf8',['decode_utf8',['../classMail__Handler.html#a6fc5947eaa45b0724f8720b374481275',1,'Mail_Handler']]], - ['decrypt',['decrypt',['../classMyCrypt.html#aed69cdc691e1155856c905ee1c08d9b7',1,'MyCrypt']]], - ['delete',['delete',['../classAssigned.html#a13bdffdd926f26b825ea57066334ff01',1,'Assigned\delete()'],['../classForwarded.html#a13bdffdd926f26b825ea57066334ff01',1,'Forwarded\delete()'],['../classIn__Support__Group.html#a13bdffdd926f26b825ea57066334ff01',1,'In_Support_Group\delete()'],['../classSupport__Group.html#a13bdffdd926f26b825ea57066334ff01',1,'Support_Group\delete()']]], - ['deletesupportgroup',['deleteSupportGroup',['../classSupport__Group.html#ab4a7d3ba86333a058027c7d58b9137f1',1,'Support_Group']]], - ['deleteuserofsupportgroup',['deleteUserOfSupportGroup',['../classSupport__Group.html#ad2d1a010903640e39545085b93b9a4f1',1,'Support_Group']]] -]; diff --git a/code/web/docs/ams/html/search/functions_65.html b/code/web/docs/ams/html/search/functions_65.html deleted file mode 100644 index a77debae0..000000000 --- a/code/web/docs/ams/html/search/functions_65.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_65.js b/code/web/docs/ams/html/search/functions_65.js deleted file mode 100644 index 348a0bc5f..000000000 --- a/code/web/docs/ams/html/search/functions_65.js +++ /dev/null @@ -1,8 +0,0 @@ -var searchData= -[ - ['encrypt',['encrypt',['../classMyCrypt.html#a07bcc8ef1d23370470ecb5ae8fc07dfa',1,'MyCrypt']]], - ['error',['error',['../error_8php.html#a43b8d30b879d4f09ceb059b02af2bc02',1,'error.php']]], - ['execute',['execute',['../classDBLayer.html#a9a0e3ecb193fecd94263eda79c54bcc4',1,'DBLayer']]], - ['executereturnid',['executeReturnId',['../classDBLayer.html#a9a8137347ec2d551de3ec54cfb3bdb1a',1,'DBLayer']]], - ['executewithoutparams',['executeWithoutParams',['../classDBLayer.html#a33552c5325c469ac1aa0d049d2312468',1,'DBLayer']]] -]; diff --git a/code/web/docs/ams/html/search/functions_66.html b/code/web/docs/ams/html/search/functions_66.html deleted file mode 100644 index 319a5316a..000000000 --- a/code/web/docs/ams/html/search/functions_66.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_66.js b/code/web/docs/ams/html/search/functions_66.js deleted file mode 100644 index 608fb4187..000000000 --- a/code/web/docs/ams/html/search/functions_66.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['forwardticket',['forwardTicket',['../classForwarded.html#aa6f01e425a0f845ce55c2d90aeb11db0',1,'Forwarded\forwardTicket()'],['../classTicket.html#a3fdc6def6a0feaf4c2458811b8c75050',1,'Ticket\forwardTicket()']]] -]; diff --git a/code/web/docs/ams/html/search/functions_67.html b/code/web/docs/ams/html/search/functions_67.html deleted file mode 100644 index d0ab42a3f..000000000 --- a/code/web/docs/ams/html/search/functions_67.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_67.js b/code/web/docs/ams/html/search/functions_67.js deleted file mode 100644 index 6f68d029b..000000000 --- a/code/web/docs/ams/html/search/functions_67.js +++ /dev/null @@ -1,106 +0,0 @@ -var searchData= -[ - ['generatesalt',['generateSALT',['../classUsers.html#afb7603ac9556c1069fbf1c0062251203',1,'Users']]], - ['get_5femail_5fby_5fuser_5fid',['get_email_by_user_id',['../classTicket__User.html#a7274bc305ccce731091c68d1607cb6e9',1,'Ticket_User']]], - ['get_5fid_5ffrom_5femail',['get_id_from_email',['../classTicket__User.html#a7feeb7a909bf6733de21300d0ea0e1bd',1,'Ticket_User']]], - ['get_5fid_5ffrom_5fusername',['get_id_from_username',['../classTicket__User.html#a0bcfa281f41b948eb42dd18992724543',1,'Ticket_User']]], - ['get_5fmime_5ftype',['get_mime_type',['../classMail__Handler.html#a719c5051ef00fbb0d7c7ce2c78e3b4e1',1,'Mail_Handler']]], - ['get_5fpart',['get_part',['../classMail__Handler.html#ab3a5e8f69692826c6dae96f873859642',1,'Mail_Handler']]], - ['get_5fticket_5fid_5ffrom_5fsubject',['get_ticket_id_from_subject',['../classMail__Handler.html#a8604569b1e012ea3b1fe466018f75ce2',1,'Mail_Handler']]], - ['get_5fusername_5ffrom_5fid',['get_username_from_id',['../classTicket__User.html#a266ff1e60e08dcd8c7e70f22f5a33e93',1,'Ticket_User']]], - ['getaction',['getAction',['../classTicket__Log.html#a189a4abe5faf11f4320d5d3f1d3d1715',1,'Ticket_Log']]], - ['getactiontextarray',['getActionTextArray',['../classTicket__Log.html#ac760071c0ce36337c16d8146fcb3bade',1,'Ticket_Log']]], - ['getallcategories',['getAllCategories',['../classTicket__Category.html#a1e4b8ecfd737337e35976126b521499f',1,'Ticket_Category']]], - ['getalllogs',['getAllLogs',['../classTicket__Log.html#aeaf1c995cc807afe241f6e7bdc684921',1,'Ticket_Log']]], - ['getallsupportgroups',['getAllSupportGroups',['../classSupport__Group.html#ad3fc18cb894f789d19a768ea63d9b673',1,'Support_Group']]], - ['getallusersofsupportgroup',['getAllUsersOfSupportGroup',['../classSupport__Group.html#a7f1662394a31e2a05e9863def178df12',1,'Support_Group']]], - ['getallusersquery',['getAllUsersQuery',['../classWebUsers.html#a2f8e928ed02e462b40e909965250fb7d',1,'WebUsers\getAllUsersQuery()'],['../classWebUsers.html#a2f8e928ed02e462b40e909965250fb7d',1,'WebUsers\getAllUsersQuery()']]], - ['getamountofrows',['getAmountOfRows',['../classPagination.html#ae43f78382809e3cd2aaa3c455cb0b2b4',1,'Pagination']]], - ['getargument',['getArgument',['../classTicket__Log.html#a88ec9370bcbdb60301f89e401c9e64e1',1,'Ticket_Log']]], - ['getassigned',['getAssigned',['../classTicket.html#a8234a4e23319778d234b3957f8b5d06c',1,'Ticket']]], - ['getauthor',['getAuthor',['../classTicket.html#a5286e30390ae3e1b274940286493dd24',1,'Ticket\getAuthor()'],['../classTicket__Log.html#a5286e30390ae3e1b274940286493dd24',1,'Ticket_Log\getAuthor()'],['../classTicket__Reply.html#a5286e30390ae3e1b274940286493dd24',1,'Ticket_Reply\getAuthor()']]], - ['getcategoryname',['getCategoryName',['../classTicket.html#a689e9d131777e7f1219ee0d65b088cb3',1,'Ticket']]], - ['getclient_5fversion',['getClient_Version',['../classTicket__Info.html#a5a9884f9f9b63d4a6ed8c6112704277d',1,'Ticket_Info']]], - ['getconnect_5fstate',['getConnect_State',['../classTicket__Info.html#a51a5247b7c82f60479ccdcfa33041c27',1,'Ticket_Info']]], - ['getcontent',['getContent',['../classTicket__Content.html#a58e43f09a06ce4e29b192c4e17ce7915',1,'Ticket_Content\getContent()'],['../classTicket__Reply.html#a58e43f09a06ce4e29b192c4e17ce7915',1,'Ticket_Reply\getContent()']]], - ['getcountryarray',['getCountryArray',['../drupal__module_2ryzommanage_2inc_2settings_8php.html#a9342547984d3c9a5ece41572951f8edf',1,'getCountryArray(): settings.php'],['../www_2html_2inc_2settings_8php.html#a9342547984d3c9a5ece41572951f8edf',1,'getCountryArray(): settings.php']]], - ['getcpu_5fmask',['getCPU_Mask',['../classTicket__Info.html#ae85e54574e6e0b17cd33b8c49255d228',1,'Ticket_Info']]], - ['getcpuid',['getCPUId',['../classTicket__Info.html#aba21caccb000efb673b8b66ca70a36c7',1,'Ticket_Info']]], - ['getcurrent',['getCurrent',['../classPagination.html#ad926899d7cac34a3f1a90e552d8eb27d',1,'Pagination']]], - ['getdb',['getDb',['../classQuerycache.html#aceb656ee5135578ab3a9947252caa772',1,'Querycache']]], - ['getelements',['getElements',['../classPagination.html#a97a3a3e912139aa222a7ca13fdb27d33',1,'Pagination']]], - ['getemail',['getEmail',['../classWebUsers.html#a02a01849f28e2535e888ae4ec87b20f2',1,'WebUsers\getEmail()'],['../classWebUsers.html#a02a01849f28e2535e888ae4ec87b20f2',1,'WebUsers\getEmail()']]], - ['getentireticket',['getEntireTicket',['../classTicket.html#a00572e06f01ae1cadb5949f1b45e8f04',1,'Ticket']]], - ['getexternid',['getExternId',['../classTicket__User.html#ace230deb485c9f115f7fea4ce92442a3',1,'Ticket_User']]], - ['getforwardedgroupid',['getForwardedGroupId',['../classTicket.html#aedbfa4efd5aaa96ac713817d12156f7e',1,'Ticket']]], - ['getforwardedgroupname',['getForwardedGroupName',['../classTicket.html#a34e17d1cc053a7b86ce2b58a3a347c7e',1,'Ticket']]], - ['getgroup',['getGroup',['../classForwarded.html#a4f44e7bc9de772c21b4304d11e87bf16',1,'Forwarded\getGroup()'],['../classIn__Support__Group.html#a4f44e7bc9de772c21b4304d11e87bf16',1,'In_Support_Group\getGroup()'],['../classSupport__Group.html#af6697615443145a2981e62aa741c3afa',1,'Support_Group\getGroup()']]], - ['getgroupemail',['getGroupEmail',['../classSupport__Group.html#a9d0f36a53db49c1f57e3cab8a61a7d90',1,'Support_Group']]], - ['getgroups',['getGroups',['../classSupport__Group.html#a562142b89699a1063ea9769030250365',1,'Support_Group']]], - ['gethidden',['getHidden',['../classTicket__Reply.html#a1d032efbce2b4edb7c269a1e13562f40',1,'Ticket_Reply']]], - ['getht',['getHT',['../classTicket__Info.html#a90d3c0edc1e767875c7fb98880886e73',1,'Ticket_Info']]], - ['getid',['getId',['../classWebUsers.html#a585ef354b38d0fad9d92f45e183b639f',1,'WebUsers\getId($username)'],['../classWebUsers.html#a585ef354b38d0fad9d92f45e183b639f',1,'WebUsers\getId($username)']]], - ['getidfromemail',['getIdFromEmail',['../classWebUsers.html#aee8d6b322defc5dfe8e47f382becca62',1,'WebUsers\getIdFromEmail($email)'],['../classWebUsers.html#aee8d6b322defc5dfe8e47f382becca62',1,'WebUsers\getIdFromEmail($email)']]], - ['getimap_5fmailserver',['getIMAP_MailServer',['../classSupport__Group.html#a30d67354e52f95489b93923440ff0661',1,'Support_Group']]], - ['getimap_5fpassword',['getIMAP_Password',['../classSupport__Group.html#a4983db184794db8f05ce93f5ba11ba7e',1,'Support_Group']]], - ['getimap_5fusername',['getIMAP_Username',['../classSupport__Group.html#a0ace9f66f2541d29e060cb7728030e93',1,'Support_Group']]], - ['getinfo',['getInfo',['../classWebUsers.html#a164026f74736817927e1cacd282a2e28',1,'WebUsers\getInfo()'],['../classWebUsers.html#a164026f74736817927e1cacd282a2e28',1,'WebUsers\getInfo()']]], - ['getlanguage',['getLanguage',['../classWebUsers.html#afcef2403c4111bc44ef0530f1e493909',1,'WebUsers\getLanguage()'],['../classWebUsers.html#afcef2403c4111bc44ef0530f1e493909',1,'WebUsers\getLanguage()']]], - ['getlast',['getLast',['../classPagination.html#a9316ede6960667d832997c8e20223623',1,'Pagination']]], - ['getlatestreply',['getLatestReply',['../classTicket.html#a3a4ce7e9c445dd245b3370304d0afd92',1,'Ticket']]], - ['getlinks',['getLinks',['../classPagination.html#aeecf550e63b55ecd5d737ecc46e07d3a',1,'Pagination']]], - ['getlocal_5faddress',['getLocal_Address',['../classTicket__Info.html#a49b4c851eff2f3d06531a39baa8423f5',1,'Ticket_Info']]], - ['getlogsofticket',['getLogsOfTicket',['../classTicket__Log.html#a37ad4d95b0bb2d5a6dfc2dd7c3744292',1,'Ticket_Log']]], - ['getmemory',['getMemory',['../classTicket__Info.html#a144248575cd034a40315155a9b48ff87',1,'Ticket_Info']]], - ['getmodsandadmins',['getModsAndAdmins',['../classTicket__User.html#a71099747902fb7e064ec1d4128ea4576',1,'Ticket_User']]], - ['getname',['getName',['../classSupport__Group.html#a3d0963e68bb313b163a73f2803c64600',1,'Support_Group\getName()'],['../classTicket__Category.html#a3d0963e68bb313b163a73f2803c64600',1,'Ticket_Category\getName()']]], - ['getnel3d',['getNel3D',['../classTicket__Info.html#abe3ae528bfd5495720c3adeff59fe11e',1,'Ticket_Info']]], - ['getnewestticket',['getNewestTicket',['../classTicket__Queue__Handler.html#ab5a79318a0c771083f03400093b3b2ec',1,'Ticket_Queue_Handler']]], - ['getnroftickets',['getNrOfTickets',['../classTicket__Queue__Handler.html#ada8f87ed8466c5e0477fa20359c3c8ad',1,'Ticket_Queue_Handler']]], - ['getnrofticketsassignedwaiting',['getNrOfTicketsAssignedWaiting',['../classTicket__Queue__Handler.html#a0d3daaaf5c79188eb62bb3adda11fa2a',1,'Ticket_Queue_Handler']]], - ['getnrofticketstodo',['getNrOfTicketsToDo',['../classTicket__Queue__Handler.html#ae8d1a2a66991583c05c173147e8dc657',1,'Ticket_Queue_Handler']]], - ['getos',['getOS',['../classTicket__Info.html#a9a1b88474ad97701d67a752d0c4d65c5',1,'Ticket_Info']]], - ['getpagination',['getPagination',['../classTicket__Queue__Handler.html#ab45a102a508e9727b108e8f24486c464',1,'Ticket_Queue_Handler']]], - ['getparams',['getParams',['../classTicket__Queue.html#ae32cd7c32721b02d676bb63b4b1366db',1,'Ticket_Queue']]], - ['getpatch_5fversion',['getPatch_Version',['../classTicket__Info.html#a6e41e115b03a1f152bd2c28c77d5fbac',1,'Ticket_Info']]], - ['getpermission',['getPermission',['../classTicket__User.html#a478067ecf173884c2ee3e5b94e746200',1,'Ticket_User']]], - ['getpriority',['getPriority',['../classTicket.html#a1e7a3c168dcd0901a0d2669c67575b55',1,'Ticket']]], - ['getpriorityarray',['getPriorityArray',['../classTicket.html#a509625cccc0b41f4ab3a658df705b3dc',1,'Ticket']]], - ['getprioritytext',['getPriorityText',['../classTicket.html#ae07f7808a12f2789593722f3293bd105',1,'Ticket']]], - ['getprocessor',['getProcessor',['../classTicket__Info.html#a3ace868ad456ff61f545cb44ee01c562',1,'Ticket_Info']]], - ['getquery',['getQuery',['../classQuerycache.html#a55f162785567258fe5138af282e588c2',1,'Querycache\getQuery()'],['../classTicket__Log.html#a55f162785567258fe5138af282e588c2',1,'Ticket_Log\getQuery()'],['../classTicket__Queue.html#a55f162785567258fe5138af282e588c2',1,'Ticket_Queue\getQuery()']]], - ['getqueue',['getQueue',['../classTicket.html#aa7a8055e5ee1eb792f29443ddb79c4d3',1,'Ticket']]], - ['getreceivemail',['getReceiveMail',['../classWebUsers.html#ae4680f622bd8d571530615fb616d37e7',1,'WebUsers\getReceiveMail()'],['../classWebUsers.html#ae4680f622bd8d571530615fb616d37e7',1,'WebUsers\getReceiveMail()']]], - ['getrepliesofticket',['getRepliesOfTicket',['../classTicket__Reply.html#a7e80a6437bb6ee90be42a32f3a82fe76',1,'Ticket_Reply']]], - ['getserver_5ftick',['getServer_Tick',['../classTicket__Info.html#a5a5799e4e54d3fa4858716b4464710c0',1,'Ticket_Info']]], - ['getsgroupid',['getSGroupId',['../classSupport__Group.html#a77d0961efe9609ebb268f8672e71bba4',1,'Support_Group']]], - ['getsgroupofticket',['getSGroupOfTicket',['../classForwarded.html#a4de002d45322cf62ce493f49933d33bd',1,'Forwarded']]], - ['getshardid',['getShardId',['../classTicket__Info.html#a36306b5367015050fb516fcaaff8351f',1,'Ticket_Info']]], - ['getsid',['getSID',['../classQuerycache.html#a5bac91964d19751986cccad6fad28dda',1,'Querycache']]], - ['getstatus',['getStatus',['../classTicket.html#a9d21636071f529e2154051d3ea6e5921',1,'Ticket']]], - ['getstatusarray',['getStatusArray',['../classTicket.html#aa728c6a1f8ddd7030acbf5a4ca913b50',1,'Ticket']]], - ['getstatustext',['getStatusText',['../classTicket.html#aab26af198dc3a59295747084b85435ff',1,'Ticket']]], - ['gettag',['getTag',['../classSupport__Group.html#ab86ba36154b20e6bbfa3ba705f12f9d6',1,'Support_Group']]], - ['gettcategoryid',['getTCategoryId',['../classTicket__Category.html#acb530a119e5e52230a92ece95cc7ec82',1,'Ticket_Category']]], - ['gettcontentid',['getTContentId',['../classTicket__Content.html#a9245dceab917ad08e5244c9395b347ae',1,'Ticket_Content']]], - ['getticket',['getTicket',['../classAssigned.html#a42ddf34a72af750b7013fa309b67e46c',1,'Assigned\getTicket()'],['../classForwarded.html#a42ddf34a72af750b7013fa309b67e46c',1,'Forwarded\getTicket()'],['../classTicket__Info.html#a42ddf34a72af750b7013fa309b67e46c',1,'Ticket_Info\getTicket()'],['../classTicket__Log.html#a42ddf34a72af750b7013fa309b67e46c',1,'Ticket_Log\getTicket()'],['../classTicket__Reply.html#a42ddf34a72af750b7013fa309b67e46c',1,'Ticket_Reply\getTicket()']]], - ['getticket_5fcategory',['getTicket_Category',['../classTicket.html#addff2fc457fe07664f4eb39efcea45f9',1,'Ticket']]], - ['gettickets',['getTickets',['../classTicket__Queue__Handler.html#a45e8c11ba9485041fa92c7c470a8f9f9',1,'Ticket_Queue_Handler']]], - ['getticketsof',['getTicketsOf',['../classTicket.html#aa426904463cd0eb50d9b2f4becdd242f',1,'Ticket']]], - ['gettid',['getTId',['../classTicket.html#aa7af74696d9898008992c494cec136dd',1,'Ticket']]], - ['gettimestamp',['getTimestamp',['../classTicket.html#a92aa1d82129ec8cd803d64c28efcb30f',1,'Ticket\getTimestamp()'],['../classTicket__Log.html#a92aa1d82129ec8cd803d64c28efcb30f',1,'Ticket_Log\getTimestamp()'],['../classTicket__Reply.html#a92aa1d82129ec8cd803d64c28efcb30f',1,'Ticket_Reply\getTimestamp()']]], - ['gettinfoid',['getTInfoId',['../classTicket__Info.html#ad7c7ccc1926763c252d32d1fee5a7f69',1,'Ticket_Info']]], - ['gettitle',['getTitle',['../classTicket.html#a95e859a4588a39a1824b717378a84c29',1,'Ticket']]], - ['gettlogid',['getTLogId',['../classTicket__Log.html#ab174d340ee116d8cc3aa377003421fc5',1,'Ticket_Log']]], - ['gettreplyid',['getTReplyId',['../classTicket__Reply.html#ade0c35755c1a1af8fa4c9bae8b4c51f1',1,'Ticket_Reply']]], - ['gettuserid',['getTUserId',['../classTicket__User.html#a4a31c27c61f9794200b647bf810461f5',1,'Ticket_User']]], - ['gettype',['getType',['../classQuerycache.html#a830b5c75df72b32396701bc563fbe3c7',1,'Querycache']]], - ['getuid',['getUId',['../classWebUsers.html#aa36a98da4146d85e7813e99df7d97497',1,'WebUsers\getUId()'],['../classWebUsers.html#aa36a98da4146d85e7813e99df7d97497',1,'WebUsers\getUId()']]], - ['getuser',['getUser',['../classAssigned.html#ae81b7186fb97a7c6457edcc68c9aa2ef',1,'Assigned\getUser()'],['../classIn__Support__Group.html#ae81b7186fb97a7c6457edcc68c9aa2ef',1,'In_Support_Group\getUser()']]], - ['getuser_5fid',['getUser_Id',['../classTicket__Info.html#a9c2fe31c14609e2255773d5a4dd154d8',1,'Ticket_Info']]], - ['getuser_5fposition',['getUser_Position',['../classTicket__Info.html#a3f5a46d846543219d6321d2f8751d1f0',1,'Ticket_Info']]], - ['getuserassignedtoticket',['getUserAssignedToTicket',['../classAssigned.html#afcfb156712a9477a97423a49238d13c5',1,'Assigned']]], - ['getusername',['getUsername',['../classWebUsers.html#a81b37a3c9d639574e394f80c1138c75e',1,'WebUsers\getUsername()'],['../classWebUsers.html#a81b37a3c9d639574e394f80c1138c75e',1,'WebUsers\getUsername()']]], - ['getusers',['getUsers',['../classWebUsers.html#a0fc10b64683021b70c7eb95fb514c119',1,'WebUsers\getUsers()'],['../classWebUsers.html#a0fc10b64683021b70c7eb95fb514c119',1,'WebUsers\getUsers()']]], - ['getview_5fposition',['getView_Position',['../classTicket__Info.html#a525dbd26fc788c7c152f6c686a9a5d11',1,'Ticket_Info']]] -]; diff --git a/code/web/docs/ams/html/search/functions_68.html b/code/web/docs/ams/html/search/functions_68.html deleted file mode 100644 index 66b85be31..000000000 --- a/code/web/docs/ams/html/search/functions_68.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_68.js b/code/web/docs/ams/html/search/functions_68.js deleted file mode 100644 index 68cc67ed7..000000000 --- a/code/web/docs/ams/html/search/functions_68.js +++ /dev/null @@ -1,6 +0,0 @@ -var searchData= -[ - ['handle_5flanguage',['handle_language',['../classHelpers.html#a334920d0652c160c6145d3bd7be31a22',1,'Helpers']]], - ['hashiv',['hashIV',['../classMyCrypt.html#a1bdf94a5906655bf0965338c9d17ab27',1,'MyCrypt']]], - ['hasinfo',['hasInfo',['../classTicket.html#afca07df3cc25a0e1a15d3f69bd6afa62',1,'Ticket']]] -]; diff --git a/code/web/docs/ams/html/search/functions_69.html b/code/web/docs/ams/html/search/functions_69.html deleted file mode 100644 index e2041976c..000000000 --- a/code/web/docs/ams/html/search/functions_69.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_69.js b/code/web/docs/ams/html/search/functions_69.js deleted file mode 100644 index e23cc85fc..000000000 --- a/code/web/docs/ams/html/search/functions_69.js +++ /dev/null @@ -1,9 +0,0 @@ -var searchData= -[ - ['incoming_5fmail_5fhandler',['incoming_mail_handler',['../classMail__Handler.html#a2896dabadb8e435de7ba7bbb258f8a96',1,'Mail_Handler']]], - ['isadmin',['isAdmin',['../classTicket__User.html#ae8a7d91474cde916fced2127fab426d2',1,'Ticket_User']]], - ['isassigned',['isAssigned',['../classAssigned.html#ade127364a5e5635077119b7217b6059c',1,'Assigned']]], - ['isforwarded',['isForwarded',['../classForwarded.html#ac1fa2045188edf04b07c523e1c6f68a0',1,'Forwarded']]], - ['isloggedin',['isLoggedIn',['../classWebUsers.html#a33bdd79e5da367ebddd4cfbdbbfc7cff',1,'WebUsers\isLoggedIn()'],['../classWebUsers.html#a33bdd79e5da367ebddd4cfbdbbfc7cff',1,'WebUsers\isLoggedIn()']]], - ['ismod',['isMod',['../classTicket__User.html#a8d88cdbf205bf7d24be03157d25bb7d8',1,'Ticket_User']]] -]; diff --git a/code/web/docs/ams/html/search/functions_6c.html b/code/web/docs/ams/html/search/functions_6c.html deleted file mode 100644 index da371cfab..000000000 --- a/code/web/docs/ams/html/search/functions_6c.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_6c.js b/code/web/docs/ams/html/search/functions_6c.js deleted file mode 100644 index 51fb577db..000000000 --- a/code/web/docs/ams/html/search/functions_6c.js +++ /dev/null @@ -1,23 +0,0 @@ -var searchData= -[ - ['load',['load',['../classAssigned.html#a689011be59ec3d216ebe6852f07ab37f',1,'Assigned\load()'],['../classForwarded.html#a689011be59ec3d216ebe6852f07ab37f',1,'Forwarded\load()']]], - ['load_5fwith_5fsgroupid',['load_With_SGroupId',['../classSupport__Group.html#a6beae177f45da42a57b100b5481f49bf',1,'Support_Group']]], - ['load_5fwith_5fsid',['load_With_SID',['../classQuerycache.html#ae960510ccb242704233c38d787242f53',1,'Querycache']]], - ['load_5fwith_5ftcategoryid',['load_With_TCategoryId',['../classTicket__Category.html#ab3a70940917530d91a39536a6d45a21d',1,'Ticket_Category']]], - ['load_5fwith_5ftcontentid',['load_With_TContentId',['../classTicket__Content.html#ad8b1226537a055701bcc3fe4af87257b',1,'Ticket_Content']]], - ['load_5fwith_5fticket',['load_With_Ticket',['../classTicket__Info.html#afcf4006cdd19b05919b5df34d3345ad2',1,'Ticket_Info']]], - ['load_5fwith_5ftid',['load_With_TId',['../classTicket.html#ac17d9e1158fb77707da1f6cd3e425d54',1,'Ticket']]], - ['load_5fwith_5ftinfoid',['load_With_TInfoId',['../classTicket__Info.html#a1681685f76483b7944bf6848b29caa4a',1,'Ticket_Info']]], - ['load_5fwith_5ftlogid',['load_With_TLogId',['../classTicket__Log.html#a76e8e991002c7e408f7b182556cdeade',1,'Ticket_Log']]], - ['load_5fwith_5ftreplyid',['load_With_TReplyId',['../classTicket__Reply.html#ac9a387c63aad0b81a8161d2515f697d9',1,'Ticket_Reply']]], - ['load_5fwith_5ftuserid',['load_With_TUserId',['../classTicket__User.html#af43df1ba39e073e4b3a0120e6e4d3140',1,'Ticket_User']]], - ['loadallclosedtickets',['loadAllClosedTickets',['../classTicket__Queue.html#af2a9b20ac9dc0e1992f717abbb418be7',1,'Ticket_Queue']]], - ['loadallnotassignedtickets',['loadAllNotAssignedTickets',['../classTicket__Queue.html#a771627a0bd387cd666474a6ef0d5eaaf',1,'Ticket_Queue']]], - ['loadallopentickets',['loadAllOpenTickets',['../classTicket__Queue.html#a3a1cf8a88a3604e093f7d276050f1c49',1,'Ticket_Queue']]], - ['loadalltickets',['loadAllTickets',['../classTicket__Queue.html#a80542bde30a8a589f1d088422cb7719b',1,'Ticket_Queue']]], - ['loadassignedandwaiting',['loadAssignedandWaiting',['../classTicket__Queue.html#a348c76f7ae32437b7e91b57671d6f33d',1,'Ticket_Queue']]], - ['loadtemplate',['loadTemplate',['../classHelpers.html#a78997ab39ba0237dc7a5441b58601211',1,'Helpers']]], - ['loadtodotickets',['loadToDoTickets',['../classTicket__Queue.html#ad88848edf9a9132eb0cfcac904a8459f',1,'Ticket_Queue']]], - ['login',['login',['../func_2login_8php.html#aa311da27ba5706f5710cea7706c8eae1',1,'login(): login.php'],['../inc_2login_8php.html#aa311da27ba5706f5710cea7706c8eae1',1,'login(): login.php']]], - ['logout',['logout',['../drupal__module_2ryzommanage_2inc_2logout_8php.html#a082405d89acd6835c3a7c7a08a7adbab',1,'logout(): logout.php'],['../www_2html_2inc_2logout_8php.html#a082405d89acd6835c3a7c7a08a7adbab',1,'logout(): logout.php']]] -]; diff --git a/code/web/docs/ams/html/search/functions_6d.html b/code/web/docs/ams/html/search/functions_6d.html deleted file mode 100644 index d01ac5376..000000000 --- a/code/web/docs/ams/html/search/functions_6d.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_6d.js b/code/web/docs/ams/html/search/functions_6d.js deleted file mode 100644 index 2f5fc5e1e..000000000 --- a/code/web/docs/ams/html/search/functions_6d.js +++ /dev/null @@ -1,7 +0,0 @@ -var searchData= -[ - ['mail_5ffork',['mail_fork',['../classMail__Handler.html#ac6f9bcfab65cc93fdd4723284fff6b7a',1,'Mail_Handler']]], - ['make_5ftable',['make_table',['../classGui__Elements.html#a639930203d81ff01840ac90a51cbbfe7',1,'Gui_Elements']]], - ['make_5ftable_5fwith_5fkey_5fis_5fid',['make_table_with_key_is_id',['../classGui__Elements.html#ae3c8c19fce4cdd7d87d4ae759ab06f24',1,'Gui_Elements']]], - ['modify_5femail_5fof_5fsgroup',['modify_email_of_sgroup',['../modify__email__of__sgroup_8php.html#acb8c4a7ad3e36662d1d22ba56a98d0ab',1,'modify_email_of_sgroup.php']]] -]; diff --git a/code/web/docs/ams/html/search/functions_6e.html b/code/web/docs/ams/html/search/functions_6e.html deleted file mode 100644 index d734dd07e..000000000 --- a/code/web/docs/ams/html/search/functions_6e.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_6e.js b/code/web/docs/ams/html/search/functions_6e.js deleted file mode 100644 index 0831ed960..000000000 --- a/code/web/docs/ams/html/search/functions_6e.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['new_5fmessage_5fid',['new_message_id',['../classMail__Handler.html#a667ca75b6c659157d855c3d19978a436',1,'Mail_Handler']]] -]; diff --git a/code/web/docs/ams/html/search/functions_6f.html b/code/web/docs/ams/html/search/functions_6f.html deleted file mode 100644 index 222f0f836..000000000 --- a/code/web/docs/ams/html/search/functions_6f.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_6f.js b/code/web/docs/ams/html/search/functions_6f.js deleted file mode 100644 index f8a8b3016..000000000 --- a/code/web/docs/ams/html/search/functions_6f.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['outputtime',['outputTime',['../classHelpers.html#a4370c805a72fe32c03b178b03ad2e393',1,'Helpers']]] -]; diff --git a/code/web/docs/ams/html/search/functions_72.html b/code/web/docs/ams/html/search/functions_72.html deleted file mode 100644 index a4336f7c4..000000000 --- a/code/web/docs/ams/html/search/functions_72.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_72.js b/code/web/docs/ams/html/search/functions_72.js deleted file mode 100644 index 857dcd26f..000000000 --- a/code/web/docs/ams/html/search/functions_72.js +++ /dev/null @@ -1,5 +0,0 @@ -var searchData= -[ - ['register',['register',['../register_8php.html#acc294a6cc8e69743746820e3d15e3f78',1,'register.php']]], - ['reply_5fon_5fticket',['reply_on_ticket',['../reply__on__ticket_8php.html#a79f0a445c77e8e1e59eb9e72cbf39dba',1,'reply_on_ticket.php']]] -]; diff --git a/code/web/docs/ams/html/search/functions_73.html b/code/web/docs/ams/html/search/functions_73.html deleted file mode 100644 index 774d577f5..000000000 --- a/code/web/docs/ams/html/search/functions_73.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_73.js b/code/web/docs/ams/html/search/functions_73.js deleted file mode 100644 index 50284d9b1..000000000 --- a/code/web/docs/ams/html/search/functions_73.js +++ /dev/null @@ -1,73 +0,0 @@ -var searchData= -[ - ['send_5fmail',['send_mail',['../classMail__Handler.html#a50308ad0711aee080dacef7e3f574699',1,'Mail_Handler']]], - ['send_5fticketing_5fmail',['send_ticketing_mail',['../classMail__Handler.html#abe649044c8b8bd8eb05787a401865e6d',1,'Mail_Handler']]], - ['set',['set',['../classAssigned.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Assigned\set()'],['../classForwarded.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Forwarded\set()'],['../classIn__Support__Group.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'In_Support_Group\set()'],['../classQuerycache.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Querycache\set()'],['../classSupport__Group.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Support_Group\set()'],['../classTicket.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket\set()'],['../classTicket__Info.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_Info\set()'],['../classTicket__Log.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_Log\set()'],['../classTicket__Reply.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_Reply\set()'],['../classTicket__User.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'Ticket_User\set()'],['../classWebUsers.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'WebUsers\set($values)'],['../classWebUsers.html#a8bdfe0a5256e35367225bcd6d278ef21',1,'WebUsers\set($values)']]], - ['setamsemail',['setAmsEmail',['../classUsers.html#ad1cbb1fe6ee72f46dc385bec6e274363',1,'Users']]], - ['setamspassword',['setAmsPassword',['../classUsers.html#ab89812058b0a71baf492af4652d67501',1,'Users']]], - ['setauthor',['setAuthor',['../classTicket.html#a0c8f116992af7c8737c70119dae00d45',1,'Ticket\setAuthor()'],['../classTicket__Log.html#a0c8f116992af7c8737c70119dae00d45',1,'Ticket_Log\setAuthor()'],['../classTicket__Reply.html#a0c8f116992af7c8737c70119dae00d45',1,'Ticket_Reply\setAuthor()']]], - ['setclient_5fversion',['setClient_Version',['../classTicket__Info.html#af06e75f73ae40120cc371f6ddd9ab49c',1,'Ticket_Info']]], - ['setconnect_5fstate',['setConnect_State',['../classTicket__Info.html#a4de823fc3a051d3aac3d526badef313c',1,'Ticket_Info']]], - ['setcontent',['setContent',['../classTicket__Content.html#a76e94f05c5cc0044993a35492097df4d',1,'Ticket_Content\setContent()'],['../classTicket__Reply.html#a76e94f05c5cc0044993a35492097df4d',1,'Ticket_Reply\setContent()']]], - ['setcpu_5fmask',['setCPU_Mask',['../classTicket__Info.html#a5f19999ab39a2ac0b7d6f2ced9223ae6',1,'Ticket_Info']]], - ['setcpuid',['setCPUId',['../classTicket__Info.html#af1f04d3bdcbaf28b246eb94a484f397c',1,'Ticket_Info']]], - ['setdb',['setDb',['../classQuerycache.html#afa9c249972ca269a2b1a399ed2faf9b4',1,'Querycache']]], - ['setemail',['setEmail',['../classWebUsers.html#a0cd214763f395718db166fbd598689f4',1,'WebUsers\setEmail($user, $mail)'],['../classWebUsers.html#a0cd214763f395718db166fbd598689f4',1,'WebUsers\setEmail($user, $mail)']]], - ['setexternid',['setExternId',['../classTicket__User.html#ad38846bb954052a5293ae2d26cf810d2',1,'Ticket_User']]], - ['setgroup',['setGroup',['../classForwarded.html#a3116db27c2e2f33cbb10a9488db34da3',1,'Forwarded\setGroup()'],['../classIn__Support__Group.html#a3116db27c2e2f33cbb10a9488db34da3',1,'In_Support_Group\setGroup()']]], - ['setgroupemail',['setGroupEmail',['../classSupport__Group.html#abbb0e975fd21a42439970ebb3eba5fea',1,'Support_Group']]], - ['sethidden',['setHidden',['../classTicket__Reply.html#a0b67f1016974c7b153b8944a94c88045',1,'Ticket_Reply']]], - ['setht',['setHT',['../classTicket__Info.html#a9ef93ff2fede4bd9b1cb8da2129dee20',1,'Ticket_Info']]], - ['setimap_5fmailserver',['setIMAP_MailServer',['../classSupport__Group.html#a71f266f2bba1fc4fb6df4cf083988938',1,'Support_Group']]], - ['setimap_5fpassword',['setIMAP_Password',['../classSupport__Group.html#ad6fcb63d4ae129567e8bea8786a75d87',1,'Support_Group']]], - ['setimap_5fusername',['setIMAP_Username',['../classSupport__Group.html#a6856519261b543f27bc001616c2881eb',1,'Support_Group']]], - ['setlanguage',['setLanguage',['../classWebUsers.html#a5ab1bd5f0959a3c33a46c176d9412c80',1,'WebUsers\setLanguage($user, $language)'],['../classWebUsers.html#a5ab1bd5f0959a3c33a46c176d9412c80',1,'WebUsers\setLanguage($user, $language)']]], - ['setlocal_5faddress',['setLocal_Address',['../classTicket__Info.html#a144b42f39cea6b24624c6c547df6aeeb',1,'Ticket_Info']]], - ['setmemory',['setMemory',['../classTicket__Info.html#a6f6f6925a18d24d2ecd5166a325be609',1,'Ticket_Info']]], - ['setname',['setName',['../classSupport__Group.html#aa3dcc220094e19fef1f918a3a917dba7',1,'Support_Group\setName()'],['../classTicket__Category.html#aa3dcc220094e19fef1f918a3a917dba7',1,'Ticket_Category\setName()']]], - ['setnel3d',['setNel3D',['../classTicket__Info.html#a77fbf6da57aa02e075be0905dc6cdd48',1,'Ticket_Info']]], - ['setos',['setOS',['../classTicket__Info.html#aacb7cbb0f04959ae64ba1c3aac36df54',1,'Ticket_Info']]], - ['setpassword',['setPassword',['../classWebUsers.html#a91506e5f74c9884045e865ef7c314fed',1,'WebUsers\setPassword($user, $pass)'],['../classWebUsers.html#a91506e5f74c9884045e865ef7c314fed',1,'WebUsers\setPassword($user, $pass)']]], - ['setpatch_5fversion',['setPatch_Version',['../classTicket__Info.html#a1d0f55ed3b50a72bf882591474d2ff72',1,'Ticket_Info']]], - ['setpermission',['setPermission',['../classTicket__User.html#adf7c497fb026ee6e05f6ece91f541839',1,'Ticket_User']]], - ['setpriority',['setPriority',['../classTicket.html#a3080d0b46978a8f82022bbb6e5fc0c1c',1,'Ticket']]], - ['setprocessor',['setProcessor',['../classTicket__Info.html#a8b66f72ec1928b89058cd0a9b4dd8c11',1,'Ticket_Info']]], - ['setquery',['setQuery',['../classQuerycache.html#adbd6075ec5d3bd84122e52b0134ed8e7',1,'Querycache\setQuery()'],['../classTicket__Log.html#adbd6075ec5d3bd84122e52b0134ed8e7',1,'Ticket_Log\setQuery()']]], - ['setqueue',['setQueue',['../classTicket.html#a1595d3fe708fe4f453922054407a1c03',1,'Ticket']]], - ['setreceivemail',['setReceiveMail',['../classWebUsers.html#aa0f439ff7a5cd6377a557f545fbeb45c',1,'WebUsers\setReceiveMail($user, $receivemail)'],['../classWebUsers.html#aa0f439ff7a5cd6377a557f545fbeb45c',1,'WebUsers\setReceiveMail($user, $receivemail)']]], - ['setserver_5ftick',['setServer_Tick',['../classTicket__Info.html#ab6ff52082590b43d90f8f37fd5b31086',1,'Ticket_Info']]], - ['setsgroupid',['setSGroupId',['../classSupport__Group.html#aa49cb914be98fc354a45584c6f2b8be1',1,'Support_Group']]], - ['setshardid',['setShardId',['../classTicket__Info.html#a4026e593012113e253b80e3bbd5f6c13',1,'Ticket_Info']]], - ['setsid',['setSID',['../classQuerycache.html#a2f536a1f8c8e463eb0346ac375f2a24d',1,'Querycache']]], - ['setstatus',['setStatus',['../classTicket.html#a66605893c4afc9855f1e0cf8ccccac09',1,'Ticket']]], - ['settag',['setTag',['../classSupport__Group.html#a4de944a53debc51843530fe96296f220',1,'Support_Group']]], - ['settcategoryid',['setTCategoryId',['../classTicket__Category.html#a39a64c3f7ab33ba3f5a67c31647e889f',1,'Ticket_Category']]], - ['settcontentid',['setTContentId',['../classTicket__Content.html#ae07366727208e060372063e96591c5d4',1,'Ticket_Content']]], - ['setticket',['setTicket',['../classAssigned.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Assigned\setTicket()'],['../classForwarded.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Forwarded\setTicket()'],['../classTicket__Info.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Ticket_Info\setTicket()'],['../classTicket__Log.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Ticket_Log\setTicket()'],['../classTicket__Reply.html#a47c6ae5b3cd713fdbf0a7f4d568b7c27',1,'Ticket_Reply\setTicket()']]], - ['setticket_5fcategory',['setTicket_Category',['../classTicket.html#a4e38b2a263b5a934b76cd77f026308c3',1,'Ticket']]], - ['settid',['setTId',['../classTicket.html#a8c72dc7b09645b390043f5a4664e7c7f',1,'Ticket']]], - ['settimestamp',['setTimestamp',['../classTicket.html#a4e05995d5cc78cdc9ffe72d864811ac6',1,'Ticket\setTimestamp()'],['../classTicket__Log.html#aa8903a0020a17d745524806f4e751f4c',1,'Ticket_Log\setTimestamp()'],['../classTicket__Reply.html#aa8903a0020a17d745524806f4e751f4c',1,'Ticket_Reply\setTimestamp()']]], - ['settinfoid',['setTInfoId',['../classTicket__Info.html#a5e98fba0b50f74645a2fdaa8f4d0c1ea',1,'Ticket_Info']]], - ['settings',['settings',['../drupal__module_2ryzommanage_2inc_2settings_8php.html#ad7354383714c6ae99d6ee1bfb95ab49f',1,'settings(): settings.php'],['../www_2html_2inc_2settings_8php.html#ad7354383714c6ae99d6ee1bfb95ab49f',1,'settings(): settings.php']]], - ['settitle',['setTitle',['../classTicket.html#ac765da6fa83b06ea39c0edc9b3e6c6c0',1,'Ticket']]], - ['settlogid',['setTLogId',['../classTicket__Log.html#aca708aae8c7320e11d9e08936ec74dec',1,'Ticket_Log']]], - ['settreplyid',['setTReplyId',['../classTicket__Reply.html#a7b91b481de87eb1515212d62b298cb94',1,'Ticket_Reply']]], - ['settuserid',['setTUserId',['../classTicket__User.html#a0faf8954e86346e7b566870b1a3c0a4a',1,'Ticket_User']]], - ['settype',['setType',['../classQuerycache.html#a0f29af8d4b9fdd8959739727a33acee5',1,'Querycache']]], - ['setuser',['setUser',['../classAssigned.html#af560ca7f201e2f871384a150e8ffd9aa',1,'Assigned\setUser()'],['../classIn__Support__Group.html#af560ca7f201e2f871384a150e8ffd9aa',1,'In_Support_Group\setUser()']]], - ['setuser_5fid',['setUser_Id',['../classTicket__Info.html#aec77405f6e096f2c0493383724f33034',1,'Ticket_Info']]], - ['setuser_5fposition',['setUser_Position',['../classTicket__Info.html#a41cfb7786d3252b2ec7aec42d77add9f',1,'Ticket_Info']]], - ['setview_5fposition',['setView_Position',['../classTicket__Info.html#a58912ec04451ab232d88bd78b6a8c2ea',1,'Ticket_Info']]], - ['sgroup_5flist',['sgroup_list',['../sgroup__list_8php.html#ab3af46486585b0ddced2de27a5d7a000',1,'sgroup_list.php']]], - ['show_5fqueue',['show_queue',['../show__queue_8php.html#a48695b07fef725dbf0b4f261b1fe1547',1,'show_queue.php']]], - ['show_5freply',['show_reply',['../show__reply_8php.html#ad8e51d3b3a4bf996fb07199a08ca9a3e',1,'show_reply.php']]], - ['show_5fsgroup',['show_sgroup',['../show__sgroup_8php.html#a118719426cb30ed43e39c2af24cfea2d',1,'show_sgroup.php']]], - ['show_5fticket',['show_ticket',['../show__ticket_8php.html#a1249d6cae97f6949ce3a7754fa1b7016',1,'show_ticket.php']]], - ['show_5fticket_5finfo',['show_ticket_info',['../show__ticket__info_8php.html#a579a5c89b55189455a8237369a78f0d8',1,'show_ticket_info.php']]], - ['show_5fticket_5flog',['show_ticket_log',['../show__ticket__log_8php.html#ab37298a659581e85338601f2259ead49',1,'show_ticket_log.php']]], - ['show_5fuser',['show_user',['../drupal__module_2ryzommanage_2inc_2show__user_8php.html#ac755ca62882d4caca41c7822793b8812',1,'show_user(): show_user.php'],['../www_2html_2inc_2show__user_8php.html#ac755ca62882d4caca41c7822793b8812',1,'show_user(): show_user.php']]], - ['supportgroup_5fentrynotexists',['supportGroup_EntryNotExists',['../classSupport__Group.html#aa557f337f57a3bb530f1f04df78c0f1e',1,'Support_Group']]], - ['supportgroup_5fexists',['supportGroup_Exists',['../classSupport__Group.html#ac235662693dcc9c2be51e6f1a2c426b6',1,'Support_Group']]], - ['syncdata',['syncdata',['../classSync.html#ad1211cc677b7aafcc4ebcc25f3cacdda',1,'Sync']]], - ['syncing',['syncing',['../syncing_8php.html#a8d4df31796dab54a8d0c9c9ec32cf7f9',1,'syncing.php']]] -]; diff --git a/code/web/docs/ams/html/search/functions_74.html b/code/web/docs/ams/html/search/functions_74.html deleted file mode 100644 index e3c96c339..000000000 --- a/code/web/docs/ams/html/search/functions_74.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_74.js b/code/web/docs/ams/html/search/functions_74.js deleted file mode 100644 index 62c7f6f79..000000000 --- a/code/web/docs/ams/html/search/functions_74.js +++ /dev/null @@ -1,6 +0,0 @@ -var searchData= -[ - ['ticketexists',['ticketExists',['../classTicket.html#a091d7ec56d4dc4bf980b81e8069b76d0',1,'Ticket']]], - ['tickethasinfo',['TicketHasInfo',['../classTicket__Info.html#a361217eb1d85e13aa534dabfbbd64a86',1,'Ticket_Info']]], - ['time_5felapsed_5fstring',['time_elapsed_string',['../classGui__Elements.html#a04d9bc70e65231a470426f0a94b7583d',1,'Gui_Elements']]] -]; diff --git a/code/web/docs/ams/html/search/functions_75.html b/code/web/docs/ams/html/search/functions_75.html deleted file mode 100644 index 2d61754d1..000000000 --- a/code/web/docs/ams/html/search/functions_75.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_75.js b/code/web/docs/ams/html/search/functions_75.js deleted file mode 100644 index 08d9856d5..000000000 --- a/code/web/docs/ams/html/search/functions_75.js +++ /dev/null @@ -1,9 +0,0 @@ -var searchData= -[ - ['unassignticket',['unAssignTicket',['../classAssigned.html#a8263a9c223957bb558a2c16d4431ca29',1,'Assigned\unAssignTicket()'],['../classTicket.html#a8263a9c223957bb558a2c16d4431ca29',1,'Ticket\unAssignTicket()']]], - ['update',['update',['../classQuerycache.html#a842e4774e3b3601a005b995c02f7e883',1,'Querycache\update()'],['../classSupport__Group.html#a842e4774e3b3601a005b995c02f7e883',1,'Support_Group\update()'],['../classTicket.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket\update()'],['../classTicket__Category.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Category\update()'],['../classTicket__Content.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Content\update()'],['../classTicket__Log.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Log\update()'],['../classTicket__Reply.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_Reply\update()'],['../classTicket__User.html#a842e4774e3b3601a005b995c02f7e883',1,'Ticket_User\update()']]], - ['updateticketstatus',['updateTicketStatus',['../classTicket.html#a6da2625040e9f06c583e9303082c556f',1,'Ticket']]], - ['updateticketstatusandpriority',['updateTicketStatusAndPriority',['../classTicket.html#a64f08c8987c9eb00d4bfc9ef94e45326',1,'Ticket']]], - ['userexistsinsgroup',['userExistsInSGroup',['../classIn__Support__Group.html#a1a25afa24efc6c01ffd236f735281543',1,'In_Support_Group']]], - ['userlist',['userlist',['../userlist_8php.html#a55709a05f18e09358e2b02531eb859ad',1,'userlist.php']]] -]; diff --git a/code/web/docs/ams/html/search/functions_76.html b/code/web/docs/ams/html/search/functions_76.html deleted file mode 100644 index 2ec05695c..000000000 --- a/code/web/docs/ams/html/search/functions_76.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_76.js b/code/web/docs/ams/html/search/functions_76.js deleted file mode 100644 index 1566125d3..000000000 --- a/code/web/docs/ams/html/search/functions_76.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['validemail',['validEmail',['../classUsers.html#a73637e760498c5cea55074896ec982ac',1,'Users']]] -]; diff --git a/code/web/docs/ams/html/search/functions_77.html b/code/web/docs/ams/html/search/functions_77.html deleted file mode 100644 index 8fe97554f..000000000 --- a/code/web/docs/ams/html/search/functions_77.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/functions_77.js b/code/web/docs/ams/html/search/functions_77.js deleted file mode 100644 index ed7a85370..000000000 --- a/code/web/docs/ams/html/search/functions_77.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchData= -[ - ['write_5fuser',['write_user',['../add__user_8php.html#a09df49f177966f5b08af71ec43760e0c',1,'add_user.php']]] -]; diff --git a/code/web/docs/ams/html/search/mag_sel.png b/code/web/docs/ams/html/search/mag_sel.png deleted file mode 100644 index 81f6040a2092402b4d98f9ffa8855d12a0d4ca17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 563 zcmV-30?hr1P)zxx&tqG15pu7)IiiXFflOc2k;dXd>%13GZAy? zRz!q0=|E6a6vV)&ZBS~G9oe0kbqyw1*gvY`{Pop2oKq#FlzgXt@Xh-7fxh>}`Fxg> z$%N%{$!4=5nM{(;=c!aG1Ofr^Do{u%Ih{^&Fc@H2)+a-?TBXrw5DW&z%Nb6mQ!L9O zl}b@6mB?f=tX3;#vl)}ggh(Vpyh(IK z(Mb0D{l{U$FsRjP;!{($+bsaaVi8T#1c0V#qEIOCYa9@UVLV`f__E81L;?WEaRA;Y zUH;rZ;vb;mk7JX|$=i3O~&If0O@oZfLg8gfIjW=dcBsz;gI=!{-r4# z4%6v$&~;q^j7Fo67yJ(NJWuX+I~I!tj^nW3?}^9bq|<3^+vapS5sgM^x7!cs(+mMT z&y%j};&~po+YO)3hoUH4E*E;e9>?R6SS&`X)p`njycAVcg{rEb41T{~Hk(bl-7eSb zmFxA2uIqo#@R?lKm50ND`~6Nfn|-b1|L6O98vt3Tx@gKz#isxO002ovPDHLkV1kyW B_l^Jn diff --git a/code/web/docs/ams/html/search/nomatches.html b/code/web/docs/ams/html/search/nomatches.html deleted file mode 100644 index b1ded27e9..000000000 --- a/code/web/docs/ams/html/search/nomatches.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - -
    -
    No Matches
    -
    - - diff --git a/code/web/docs/ams/html/search/search.css b/code/web/docs/ams/html/search/search.css deleted file mode 100644 index d18c1da8c..000000000 --- a/code/web/docs/ams/html/search/search.css +++ /dev/null @@ -1,238 +0,0 @@ -/*---------------- Search Box */ - -#FSearchBox { - float: left; -} - -#MSearchBox { - white-space : nowrap; - position: absolute; - float: none; - display: inline; - margin-top: 8px; - right: 0px; - width: 170px; - z-index: 102; - background-color: white; -} - -#MSearchBox .left -{ - display:block; - position:absolute; - left:10px; - width:20px; - height:19px; - background:url('search_l.png') no-repeat; - background-position:right; -} - -#MSearchSelect { - display:block; - position:absolute; - width:20px; - height:19px; -} - -.left #MSearchSelect { - left:4px; -} - -.right #MSearchSelect { - right:5px; -} - -#MSearchField { - display:block; - position:absolute; - height:19px; - background:url('search_m.png') repeat-x; - border:none; - width:116px; - margin-left:20px; - padding-left:4px; - color: #909090; - outline: none; - font: 9pt Arial, Verdana, sans-serif; -} - -#FSearchBox #MSearchField { - margin-left:15px; -} - -#MSearchBox .right { - display:block; - position:absolute; - right:10px; - top:0px; - width:20px; - height:19px; - background:url('search_r.png') no-repeat; - background-position:left; -} - -#MSearchClose { - display: none; - position: absolute; - top: 4px; - background : none; - border: none; - margin: 0px 4px 0px 0px; - padding: 0px 0px; - outline: none; -} - -.left #MSearchClose { - left: 6px; -} - -.right #MSearchClose { - right: 2px; -} - -.MSearchBoxActive #MSearchField { - color: #000000; -} - -/*---------------- Search filter selection */ - -#MSearchSelectWindow { - display: none; - position: absolute; - left: 0; top: 0; - border: 1px solid #90A5CE; - background-color: #F9FAFC; - z-index: 1; - padding-top: 4px; - padding-bottom: 4px; - -moz-border-radius: 4px; - -webkit-border-top-left-radius: 4px; - -webkit-border-top-right-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -} - -.SelectItem { - font: 8pt Arial, Verdana, sans-serif; - padding-left: 2px; - padding-right: 12px; - border: 0px; -} - -span.SelectionMark { - margin-right: 4px; - font-family: monospace; - outline-style: none; - text-decoration: none; -} - -a.SelectItem { - display: block; - outline-style: none; - color: #000000; - text-decoration: none; - padding-left: 6px; - padding-right: 12px; -} - -a.SelectItem:focus, -a.SelectItem:active { - color: #000000; - outline-style: none; - text-decoration: none; -} - -a.SelectItem:hover { - color: #FFFFFF; - background-color: #3D578C; - outline-style: none; - text-decoration: none; - cursor: pointer; - display: block; -} - -/*---------------- Search results window */ - -iframe#MSearchResults { - width: 60ex; - height: 15em; -} - -#MSearchResultsWindow { - display: none; - position: absolute; - left: 0; top: 0; - border: 1px solid #000; - background-color: #EEF1F7; -} - -/* ----------------------------------- */ - - -#SRIndex { - clear:both; - padding-bottom: 15px; -} - -.SREntry { - font-size: 10pt; - padding-left: 1ex; -} - -.SRPage .SREntry { - font-size: 8pt; - padding: 1px 5px; -} - -body.SRPage { - margin: 5px 2px; -} - -.SRChildren { - padding-left: 3ex; padding-bottom: .5em -} - -.SRPage .SRChildren { - display: none; -} - -.SRSymbol { - font-weight: bold; - color: #425E97; - font-family: Arial, Verdana, sans-serif; - text-decoration: none; - outline: none; -} - -a.SRScope { - display: block; - color: #425E97; - font-family: Arial, Verdana, sans-serif; - text-decoration: none; - outline: none; -} - -a.SRSymbol:focus, a.SRSymbol:active, -a.SRScope:focus, a.SRScope:active { - text-decoration: underline; -} - -span.SRScope { - padding-left: 4px; -} - -.SRPage .SRStatus { - padding: 2px 5px; - font-size: 8pt; - font-style: italic; -} - -.SRResult { - display: none; -} - -DIV.searchresults { - margin-left: 10px; - margin-right: 10px; -} diff --git a/code/web/docs/ams/html/search/search.js b/code/web/docs/ams/html/search/search.js deleted file mode 100644 index 9746f607f..000000000 --- a/code/web/docs/ams/html/search/search.js +++ /dev/null @@ -1,803 +0,0 @@ -// Search script generated by doxygen -// Copyright (C) 2009 by Dimitri van Heesch. - -// The code in this file is loosly based on main.js, part of Natural Docs, -// which is Copyright (C) 2003-2008 Greg Valure -// Natural Docs is licensed under the GPL. - -var indexSectionsWithContent = -{ - 0: "0000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000010101111111001111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 1: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100101111000100110111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 2: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101111111001100111111010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 3: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010101111111001111001111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - 4: "0000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -}; - -var indexSectionNames = -{ - 0: "all", - 1: "classes", - 2: "files", - 3: "functions", - 4: "variables" -}; - -function convertToId(search) -{ - var result = ''; - for (i=0;i do a search - { - this.Search(); - } - } - - this.OnSearchSelectKey = function(evt) - { - var e = (evt) ? evt : window.event; // for IE - if (e.keyCode==40 && this.searchIndex0) // Up - { - this.searchIndex--; - this.OnSelectItem(this.searchIndex); - } - else if (e.keyCode==13 || e.keyCode==27) - { - this.OnSelectItem(this.searchIndex); - this.CloseSelectionWindow(); - this.DOMSearchField().focus(); - } - return false; - } - - // --------- Actions - - // Closes the results window. - this.CloseResultsWindow = function() - { - this.DOMPopupSearchResultsWindow().style.display = 'none'; - this.DOMSearchClose().style.display = 'none'; - this.Activate(false); - } - - this.CloseSelectionWindow = function() - { - this.DOMSearchSelectWindow().style.display = 'none'; - } - - // Performs a search. - this.Search = function() - { - this.keyTimeout = 0; - - // strip leading whitespace - var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); - - var code = searchValue.toLowerCase().charCodeAt(0); - var hexCode; - if (code<16) - { - hexCode="0"+code.toString(16); - } - else - { - hexCode=code.toString(16); - } - - var resultsPage; - var resultsPageWithSearch; - var hasResultsPage; - - if (indexSectionsWithContent[this.searchIndex].charAt(code) == '1') - { - resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; - resultsPageWithSearch = resultsPage+'?'+escape(searchValue); - hasResultsPage = true; - } - else // nothing available for this search term - { - resultsPage = this.resultsPath + '/nomatches.html'; - resultsPageWithSearch = resultsPage; - hasResultsPage = false; - } - - window.frames.MSearchResults.location = resultsPageWithSearch; - var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); - - if (domPopupSearchResultsWindow.style.display!='block') - { - var domSearchBox = this.DOMSearchBox(); - this.DOMSearchClose().style.display = 'inline'; - if (this.insideFrame) - { - var domPopupSearchResults = this.DOMPopupSearchResults(); - domPopupSearchResultsWindow.style.position = 'relative'; - domPopupSearchResultsWindow.style.display = 'block'; - var width = document.body.clientWidth - 8; // the -8 is for IE :-( - domPopupSearchResultsWindow.style.width = width + 'px'; - domPopupSearchResults.style.width = width + 'px'; - } - else - { - var domPopupSearchResults = this.DOMPopupSearchResults(); - var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth; - var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1; - domPopupSearchResultsWindow.style.display = 'block'; - left -= domPopupSearchResults.offsetWidth; - domPopupSearchResultsWindow.style.top = top + 'px'; - domPopupSearchResultsWindow.style.left = left + 'px'; - } - } - - this.lastSearchValue = searchValue; - this.lastResultsPage = resultsPage; - } - - // -------- Activation Functions - - // Activates or deactivates the search panel, resetting things to - // their default values if necessary. - this.Activate = function(isActive) - { - if (isActive || // open it - this.DOMPopupSearchResultsWindow().style.display == 'block' - ) - { - this.DOMSearchBox().className = 'MSearchBoxActive'; - - var searchField = this.DOMSearchField(); - - if (searchField.value == this.searchLabel) // clear "Search" term upon entry - { - searchField.value = ''; - this.searchActive = true; - } - } - else if (!isActive) // directly remove the panel - { - this.DOMSearchBox().className = 'MSearchBoxInactive'; - this.DOMSearchField().value = this.searchLabel; - this.searchActive = false; - this.lastSearchValue = '' - this.lastResultsPage = ''; - } - } -} - -// ----------------------------------------------------------------------- - -// The class that handles everything on the search results page. -function SearchResults(name) -{ - // The number of matches from the last run of . - this.lastMatchCount = 0; - this.lastKey = 0; - this.repeatOn = false; - - // Toggles the visibility of the passed element ID. - this.FindChildElement = function(id) - { - var parentElement = document.getElementById(id); - var element = parentElement.firstChild; - - while (element && element!=parentElement) - { - if (element.nodeName == 'DIV' && element.className == 'SRChildren') - { - return element; - } - - if (element.nodeName == 'DIV' && element.hasChildNodes()) - { - element = element.firstChild; - } - else if (element.nextSibling) - { - element = element.nextSibling; - } - else - { - do - { - element = element.parentNode; - } - while (element && element!=parentElement && !element.nextSibling); - - if (element && element!=parentElement) - { - element = element.nextSibling; - } - } - } - } - - this.Toggle = function(id) - { - var element = this.FindChildElement(id); - if (element) - { - if (element.style.display == 'block') - { - element.style.display = 'none'; - } - else - { - element.style.display = 'block'; - } - } - } - - // Searches for the passed string. If there is no parameter, - // it takes it from the URL query. - // - // Always returns true, since other documents may try to call it - // and that may or may not be possible. - this.Search = function(search) - { - if (!search) // get search word from URL - { - search = window.location.search; - search = search.substring(1); // Remove the leading '?' - search = unescape(search); - } - - search = search.replace(/^ +/, ""); // strip leading spaces - search = search.replace(/ +$/, ""); // strip trailing spaces - search = search.toLowerCase(); - search = convertToId(search); - - var resultRows = document.getElementsByTagName("div"); - var matches = 0; - - var i = 0; - while (i < resultRows.length) - { - var row = resultRows.item(i); - if (row.className == "SRResult") - { - var rowMatchName = row.id.toLowerCase(); - rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' - - if (search.length<=rowMatchName.length && - rowMatchName.substr(0, search.length)==search) - { - row.style.display = 'block'; - matches++; - } - else - { - row.style.display = 'none'; - } - } - i++; - } - document.getElementById("Searching").style.display='none'; - if (matches == 0) // no results - { - document.getElementById("NoMatches").style.display='block'; - } - else // at least one result - { - document.getElementById("NoMatches").style.display='none'; - } - this.lastMatchCount = matches; - return true; - } - - // return the first item with index index or higher that is visible - this.NavNext = function(index) - { - var focusItem; - while (1) - { - var focusName = 'Item'+index; - focusItem = document.getElementById(focusName); - if (focusItem && focusItem.parentNode.parentNode.style.display=='block') - { - break; - } - else if (!focusItem) // last element - { - break; - } - focusItem=null; - index++; - } - return focusItem; - } - - this.NavPrev = function(index) - { - var focusItem; - while (1) - { - var focusName = 'Item'+index; - focusItem = document.getElementById(focusName); - if (focusItem && focusItem.parentNode.parentNode.style.display=='block') - { - break; - } - else if (!focusItem) // last element - { - break; - } - focusItem=null; - index--; - } - return focusItem; - } - - this.ProcessKeys = function(e) - { - if (e.type == "keydown") - { - this.repeatOn = false; - this.lastKey = e.keyCode; - } - else if (e.type == "keypress") - { - if (!this.repeatOn) - { - if (this.lastKey) this.repeatOn = true; - return false; // ignore first keypress after keydown - } - } - else if (e.type == "keyup") - { - this.lastKey = 0; - this.repeatOn = false; - } - return this.lastKey!=0; - } - - this.Nav = function(evt,itemIndex) - { - var e = (evt) ? evt : window.event; // for IE - if (e.keyCode==13) return true; - if (!this.ProcessKeys(e)) return false; - - if (this.lastKey==38) // Up - { - var newIndex = itemIndex-1; - var focusItem = this.NavPrev(newIndex); - if (focusItem) - { - var child = this.FindChildElement(focusItem.parentNode.parentNode.id); - if (child && child.style.display == 'block') // children visible - { - var n=0; - var tmpElem; - while (1) // search for last child - { - tmpElem = document.getElementById('Item'+newIndex+'_c'+n); - if (tmpElem) - { - focusItem = tmpElem; - } - else // found it! - { - break; - } - n++; - } - } - } - if (focusItem) - { - focusItem.focus(); - } - else // return focus to search field - { - parent.document.getElementById("MSearchField").focus(); - } - } - else if (this.lastKey==40) // Down - { - var newIndex = itemIndex+1; - var focusItem; - var item = document.getElementById('Item'+itemIndex); - var elem = this.FindChildElement(item.parentNode.parentNode.id); - if (elem && elem.style.display == 'block') // children visible - { - focusItem = document.getElementById('Item'+itemIndex+'_c0'); - } - if (!focusItem) focusItem = this.NavNext(newIndex); - if (focusItem) focusItem.focus(); - } - else if (this.lastKey==39) // Right - { - var item = document.getElementById('Item'+itemIndex); - var elem = this.FindChildElement(item.parentNode.parentNode.id); - if (elem) elem.style.display = 'block'; - } - else if (this.lastKey==37) // Left - { - var item = document.getElementById('Item'+itemIndex); - var elem = this.FindChildElement(item.parentNode.parentNode.id); - if (elem) elem.style.display = 'none'; - } - else if (this.lastKey==27) // Escape - { - parent.searchBox.CloseResultsWindow(); - parent.document.getElementById("MSearchField").focus(); - } - else if (this.lastKey==13) // Enter - { - return true; - } - return false; - } - - this.NavChild = function(evt,itemIndex,childIndex) - { - var e = (evt) ? evt : window.event; // for IE - if (e.keyCode==13) return true; - if (!this.ProcessKeys(e)) return false; - - if (this.lastKey==38) // Up - { - if (childIndex>0) - { - var newIndex = childIndex-1; - document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); - } - else // already at first child, jump to parent - { - document.getElementById('Item'+itemIndex).focus(); - } - } - else if (this.lastKey==40) // Down - { - var newIndex = childIndex+1; - var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); - if (!elem) // last child, jump to parent next parent - { - elem = this.NavNext(itemIndex+1); - } - if (elem) - { - elem.focus(); - } - } - else if (this.lastKey==27) // Escape - { - parent.searchBox.CloseResultsWindow(); - parent.document.getElementById("MSearchField").focus(); - } - else if (this.lastKey==13) // Enter - { - return true; - } - return false; - } -} - -function setKeyActions(elem,action) -{ - elem.setAttribute('onkeydown',action); - elem.setAttribute('onkeypress',action); - elem.setAttribute('onkeyup',action); -} - -function setClassAttr(elem,attr) -{ - elem.setAttribute('class',attr); - elem.setAttribute('className',attr); -} - -function createResults() -{ - var results = document.getElementById("SRResults"); - for (var e=0; ek7RCwB~R6VQOP#AvB$vH7i{6H{96zot$7cZT<7246EF5Np6N}+$IbiG6W zg#87A+NFaX+=_^xM1#gCtshC=E{%9^uQX_%?YwXvo{#q&MnpJ8uh(O?ZRc&~_1%^SsPxG@rfElJg-?U zm!Cz-IOn(qJP3kDp-^~qt+FGbl=5jNli^Wj_xIBG{Rc0en{!oFvyoNC7{V~T8}b>| z=jL2WIReZzX(YN(_9fV;BBD$VXQIxNasAL8ATvEu822WQ%mvv4FO#qs` BFGc_W diff --git a/code/web/docs/ams/html/search/search_r.png b/code/web/docs/ams/html/search/search_r.png deleted file mode 100644 index 97ee8b439687084201b79c6f776a41f495c6392a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 612 zcmV-q0-ODbP)PbXFRCwB?)W514K@j&X?z2*SxFI6-@HT2E2K=9X9%Pb zEK*!TBw&g(DMC;|A)uGlRkOS9vd-?zNs%bR4d$w+ox_iFnE8fvIvv7^5<(>Te12Li z7C)9srCzmK{ZcNM{YIl9j{DePFgOWiS%xG@5CnnnJa4nvY<^glbz7^|-ZY!dUkAwd z{gaTC@_>b5h~;ug#R0wRL0>o5!hxm*s0VW?8dr}O#zXTRTnrQm_Z7z1Mrnx>&p zD4qifUjzLvbVVWi?l?rUzwt^sdb~d!f_LEhsRVIXZtQ=qSxuxqm zEX#tf>$?M_Y1-LSDT)HqG?`%-%ZpY!#{N!rcNIiL;G7F0`l?)mNGTD9;f9F5Up3Kg zw}a<-JylhG&;=!>B+fZaCX+?C+kHYrP%c?X2!Zu_olK|GcS4A70HEy;vn)I0>0kLH z`jc(WIaaHc7!HS@f*^R^Znx8W=_jIl2oWJoQ*h1^$FX!>*PqR1J8k|fw}w_y}TpE>7m8DqDO<3z`OzXt$ccSejbEZCg@0000 - - - - - - - -
    -
    Loading...
    -
    - -
    Searching...
    -
    No Matches
    - -
    - - diff --git a/code/web/docs/ams/html/search/variables_24.js b/code/web/docs/ams/html/search/variables_24.js deleted file mode 100644 index 8e8a493e9..000000000 --- a/code/web/docs/ams/html/search/variables_24.js +++ /dev/null @@ -1,91 +0,0 @@ -var searchData= -[ - ['_24allow_5funknown',['$ALLOW_UNKNOWN',['../drupal__module_2ryzommanage_2config_8php.html#a384355265e4331097d55252f901eddff',1,'$ALLOW_UNKNOWN(): config.php'],['../www_2config_8php.html#a384355265e4331097d55252f901eddff',1,'$ALLOW_UNKNOWN(): config.php']]], - ['_24amountofrows',['$amountOfRows',['../classPagination.html#a6b5c716eec440d8dc5b9754c53c545ec',1,'Pagination']]], - ['_24ams_5fcachedir',['$AMS_CACHEDIR',['../drupal__module_2ryzommanage_2config_8php.html#a92879a931e7a7d0ae6919e70a1529747',1,'$AMS_CACHEDIR(): config.php'],['../www_2config_8php.html#a92879a931e7a7d0ae6919e70a1529747',1,'$AMS_CACHEDIR(): config.php']]], - ['_24ams_5flib',['$AMS_LIB',['../drupal__module_2ryzommanage_2config_8php.html#a75086b9c8602bf3417773bae7ef0cdc8',1,'$AMS_LIB(): config.php'],['../www_2config_8php.html#a75086b9c8602bf3417773bae7ef0cdc8',1,'$AMS_LIB(): config.php']]], - ['_24ams_5ftrans',['$AMS_TRANS',['../drupal__module_2ryzommanage_2config_8php.html#acc96a0076127356b4f9f00f4bdfa9b65',1,'$AMS_TRANS(): config.php'],['../www_2config_8php.html#acc96a0076127356b4f9f00f4bdfa9b65',1,'$AMS_TRANS(): config.php']]], - ['_24author',['$author',['../classTicket.html#ac35b828f7d4064a7c9f849c255468ee3',1,'Ticket\$author()'],['../classTicket__Log.html#ac35b828f7d4064a7c9f849c255468ee3',1,'Ticket_Log\$author()'],['../classTicket__Reply.html#ac35b828f7d4064a7c9f849c255468ee3',1,'Ticket_Reply\$author()']]], - ['_24base_5fwebpath',['$BASE_WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#a2e954ee09fb5f52b9d05caf9dfc3d5ad',1,'$BASE_WEBPATH(): config.php'],['../www_2config_8php.html#a2e954ee09fb5f52b9d05caf9dfc3d5ad',1,'$BASE_WEBPATH(): config.php']]], - ['_24cfg',['$cfg',['../drupal__module_2ryzommanage_2config_8php.html#a32f90fc68bcb40de0bae38354fd0a5fe',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a6b776651fa7defe140c03ed3bd86aa96',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a68f172c430a17022c9f74ae1acd24a00',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1805c74760836f682459a12a17d50589',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a94213b6df61b8a6b62abbe7c956493a4',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a4b555022064138fee1d7edea873c5e9e',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1b49c1f0de42e603443bea2c93276c13',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7c5f3fd8aea7ae8363c6cdc9addd9b62',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7b5bbf5b3c541b46d06deaffeeb76424',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1dca44c652dd54f6879957cf8d4a039c',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a56e7e53dac48b99f62d41d387c8624e6',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#adc2648938b5135f1f2aab1d92d33418e',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1324eeda6b288c0a26d7071db555090c',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a63d97fffb2ff86525bb6cacb74113a73',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7147f422b8150cd3f3c8a68325208607',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a53f42728714b4e86b885c12f7846cd06',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#aa68c438d0b6b38d756d8724bac554f1b',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#ae4ae1095a3543d5607464a88e6330a07',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a7cf20f61de759c233272150b12e866d8',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#aed7bed5da2b934c742cb60d23c06f752',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a1606e0620d5a628b865e0df5c217ce7e',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a41e3a386ec52e0f05bdcad04acecf619',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#ac2c263a1e16ebd69dbf247e8d82c9f63',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a9996bf49f150442cf9d564725d0dea24',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#aa7eb09eb019c344553a61b54606cb650',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a79b711e7ee81b7435a8dba7cb132b34a',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a8578ffa00c2dbcf5d34a97bcff79058b',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a50d80d35dbd37739f844a93a36fce557',1,'$cfg(): config.php'],['../drupal__module_2ryzommanage_2config_8php.html#a55031a1c3c2b9d87e37558811b311ff8',1,'$cfg(): config.php'],['../www_2config_8php.html#a32f90fc68bcb40de0bae38354fd0a5fe',1,'$cfg(): config.php'],['../www_2config_8php.html#a6b776651fa7defe140c03ed3bd86aa96',1,'$cfg(): config.php'],['../www_2config_8php.html#a68f172c430a17022c9f74ae1acd24a00',1,'$cfg(): config.php'],['../www_2config_8php.html#a1805c74760836f682459a12a17d50589',1,'$cfg(): config.php'],['../www_2config_8php.html#a94213b6df61b8a6b62abbe7c956493a4',1,'$cfg(): config.php'],['../www_2config_8php.html#a4b555022064138fee1d7edea873c5e9e',1,'$cfg(): config.php'],['../www_2config_8php.html#a1b49c1f0de42e603443bea2c93276c13',1,'$cfg(): config.php'],['../www_2config_8php.html#a7c5f3fd8aea7ae8363c6cdc9addd9b62',1,'$cfg(): config.php'],['../www_2config_8php.html#a7b5bbf5b3c541b46d06deaffeeb76424',1,'$cfg(): config.php'],['../www_2config_8php.html#a1dca44c652dd54f6879957cf8d4a039c',1,'$cfg(): config.php'],['../www_2config_8php.html#a56e7e53dac48b99f62d41d387c8624e6',1,'$cfg(): config.php'],['../www_2config_8php.html#adc2648938b5135f1f2aab1d92d33418e',1,'$cfg(): config.php'],['../www_2config_8php.html#a1324eeda6b288c0a26d7071db555090c',1,'$cfg(): config.php'],['../www_2config_8php.html#a63d97fffb2ff86525bb6cacb74113a73',1,'$cfg(): config.php'],['../www_2config_8php.html#a7147f422b8150cd3f3c8a68325208607',1,'$cfg(): config.php'],['../www_2config_8php.html#a53f42728714b4e86b885c12f7846cd06',1,'$cfg(): config.php'],['../www_2config_8php.html#aa68c438d0b6b38d756d8724bac554f1b',1,'$cfg(): config.php'],['../www_2config_8php.html#ae4ae1095a3543d5607464a88e6330a07',1,'$cfg(): config.php'],['../www_2config_8php.html#a7cf20f61de759c233272150b12e866d8',1,'$cfg(): config.php'],['../www_2config_8php.html#aed7bed5da2b934c742cb60d23c06f752',1,'$cfg(): config.php'],['../www_2config_8php.html#a1606e0620d5a628b865e0df5c217ce7e',1,'$cfg(): config.php'],['../www_2config_8php.html#a41e3a386ec52e0f05bdcad04acecf619',1,'$cfg(): config.php'],['../www_2config_8php.html#ac2c263a1e16ebd69dbf247e8d82c9f63',1,'$cfg(): config.php'],['../www_2config_8php.html#a9996bf49f150442cf9d564725d0dea24',1,'$cfg(): config.php'],['../www_2config_8php.html#aa7eb09eb019c344553a61b54606cb650',1,'$cfg(): config.php'],['../www_2config_8php.html#a79b711e7ee81b7435a8dba7cb132b34a',1,'$cfg(): config.php'],['../www_2config_8php.html#a8578ffa00c2dbcf5d34a97bcff79058b',1,'$cfg(): config.php'],['../www_2config_8php.html#a50d80d35dbd37739f844a93a36fce557',1,'$cfg(): config.php'],['../www_2config_8php.html#a55031a1c3c2b9d87e37558811b311ff8',1,'$cfg(): config.php'],['../install_8php.html#a449cc4bf6cfd310810993b3ef5251aa5',1,'$cfg(): install.php']]], - ['_24client_5fversion',['$client_version',['../classTicket__Info.html#ac43fbb88dcd0696ad49d5f805f369a61',1,'Ticket_Info']]], - ['_24config',['$config',['../classMyCrypt.html#a49c7011be9c979d9174c52a8b83e5d8e',1,'MyCrypt']]], - ['_24config_5fpath',['$CONFIG_PATH',['../drupal__module_2ryzommanage_2config_8php.html#ae15921e2ebd5885ecf37d31a2cf6ab7a',1,'$CONFIG_PATH(): config.php'],['../www_2config_8php.html#ae15921e2ebd5885ecf37d31a2cf6ab7a',1,'$CONFIG_PATH(): config.php']]], - ['_24connect_5fstate',['$connect_state',['../classTicket__Info.html#a33f4c9badf7f0c5c6728bba0ffacd66e',1,'Ticket_Info']]], - ['_24content',['$content',['../classTicket__Content.html#a57b284fe00866494b33afa80ba729bed',1,'Ticket_Content\$content()'],['../classTicket__Reply.html#a57b284fe00866494b33afa80ba729bed',1,'Ticket_Reply\$content()']]], - ['_24country',['$country',['../classWebUsers.html#a1437a5f6eb157f0eb267a26e0ad4f1ba',1,'WebUsers']]], - ['_24cpu_5fid',['$cpu_id',['../classTicket__Info.html#abea88d0d04f0d548115a0e85eef42e42',1,'Ticket_Info']]], - ['_24cpu_5fmask',['$cpu_mask',['../classTicket__Info.html#a9b0c63551b567630d1aa82f33c328ab0',1,'Ticket_Info']]], - ['_24create_5fring',['$CREATE_RING',['../drupal__module_2ryzommanage_2config_8php.html#a16031d9d4e5065229bc3b00dfd4202fa',1,'$CREATE_RING(): config.php'],['../www_2config_8php.html#a16031d9d4e5065229bc3b00dfd4202fa',1,'$CREATE_RING(): config.php']]], - ['_24current',['$current',['../classPagination.html#a2c4c58e377f6c66ca38c8ea97666fc5e',1,'Pagination']]], - ['_24db',['$db',['../classMail__Handler.html#a1fa3127fc82f96b1436d871ef02be319',1,'Mail_Handler\$db()'],['../classQuerycache.html#a1fa3127fc82f96b1436d871ef02be319',1,'Querycache\$db()']]], - ['_24default_5flanguage',['$DEFAULT_LANGUAGE',['../drupal__module_2ryzommanage_2config_8php.html#a7b56c2ed5a82ceb21fc73cef77beb150',1,'$DEFAULT_LANGUAGE(): config.php'],['../www_2config_8php.html#a7b56c2ed5a82ceb21fc73cef77beb150',1,'$DEFAULT_LANGUAGE(): config.php']]], - ['_24element_5farray',['$element_array',['../classPagination.html#a8fa0f6a15481ba69e7be913eaa15594c',1,'Pagination']]], - ['_24email',['$email',['../classWebUsers.html#ad634f418b20382e2802f80532d76d3cd',1,'WebUsers']]], - ['_24externid',['$externId',['../classTicket__User.html#af51400fe5820e964cb38fcc60b3afd84',1,'Ticket_User']]], - ['_24firstname',['$firstname',['../classWebUsers.html#a55793c72c535d153ffd3f0e43377898b',1,'WebUsers']]], - ['_24force_5fingame',['$FORCE_INGAME',['../drupal__module_2ryzommanage_2config_8php.html#aabd939b29ed900f5fc489f1a957fc6ce',1,'$FORCE_INGAME(): config.php'],['../www_2config_8php.html#aabd939b29ed900f5fc489f1a957fc6ce',1,'$FORCE_INGAME(): config.php']]], - ['_24gender',['$gender',['../classWebUsers.html#a0f1d7cfb9dc6f494b9014885205fc47e',1,'WebUsers']]], - ['_24group',['$group',['../classForwarded.html#ad530a85733b0ec1dc321859fd8faa0dc',1,'Forwarded\$group()'],['../classIn__Support__Group.html#ad530a85733b0ec1dc321859fd8faa0dc',1,'In_Support_Group\$group()']]], - ['_24groupemail',['$groupEmail',['../classSupport__Group.html#ab7ad611af238b28f1f65a32cb152acd1',1,'Support_Group']]], - ['_24hidden',['$hidden',['../classTicket__Reply.html#a4a374564d2858d8ae869a8fb890aad56',1,'Ticket_Reply']]], - ['_24ht',['$ht',['../classTicket__Info.html#a969583a6605ed731abf5849a5202db1e',1,'Ticket_Info']]], - ['_24imageloc_5fwebpath',['$IMAGELOC_WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#a16820074dcd11e4881ca6461377db000',1,'$IMAGELOC_WEBPATH(): config.php'],['../www_2config_8php.html#a16820074dcd11e4881ca6461377db000',1,'$IMAGELOC_WEBPATH(): config.php']]], - ['_24imap_5fmailserver',['$iMAP_MailServer',['../classSupport__Group.html#ad9f2ef2089fe446a9ac49a19a450d636',1,'Support_Group']]], - ['_24imap_5fpassword',['$iMAP_Password',['../classSupport__Group.html#a4166a2fc4b594ee425d7f40870e16455',1,'Support_Group']]], - ['_24imap_5fusername',['$iMAP_Username',['../classSupport__Group.html#a2b549eb4d5773efd741a2990817af0ea',1,'Support_Group']]], - ['_24ingame_5flayout',['$INGAME_LAYOUT',['../drupal__module_2ryzommanage_2config_8php.html#a0deedf69fea8c97030373e15a68c4cc5',1,'$INGAME_LAYOUT(): config.php'],['../www_2config_8php.html#a0deedf69fea8c97030373e15a68c4cc5',1,'$INGAME_LAYOUT(): config.php']]], - ['_24ingame_5fwebpath',['$INGAME_WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#ae9f6aa9c61501bca7b8851925c636d87',1,'$INGAME_WEBPATH(): config.php'],['../www_2config_8php.html#ae9f6aa9c61501bca7b8851925c636d87',1,'$INGAME_WEBPATH(): config.php']]], - ['_24language',['$language',['../classWebUsers.html#a83170d318260a5a2e2a79dccdd371b10',1,'WebUsers']]], - ['_24last',['$last',['../classPagination.html#acf48db609a946d13953d8060363fd1d3',1,'Pagination']]], - ['_24lastname',['$lastname',['../classWebUsers.html#a1d2ddb6354180329b59e8b90ed94dc7f',1,'WebUsers']]], - ['_24local_5faddress',['$local_address',['../classTicket__Info.html#a467dca5673d4c9f737dac972ab05720c',1,'Ticket_Info']]], - ['_24login',['$login',['../classWebUsers.html#afc31993e855f9631572adfedcfe6f34b',1,'WebUsers']]], - ['_24mail_5fdir',['$MAIL_DIR',['../drupal__module_2ryzommanage_2config_8php.html#a9f8fc644554910de5434f78a5f23044e',1,'$MAIL_DIR(): config.php'],['../www_2config_8php.html#a9f8fc644554910de5434f78a5f23044e',1,'$MAIL_DIR(): config.php']]], - ['_24mail_5fhandler',['$mail_handler',['../mail__cron_8php.html#a160a75d95407d877e9c2542e3ddd8c43',1,'mail_cron.php']]], - ['_24mail_5flog_5fpath',['$MAIL_LOG_PATH',['../drupal__module_2ryzommanage_2config_8php.html#afe6e9ed40480c14cb7a119fb84cb557a',1,'$MAIL_LOG_PATH(): config.php'],['../www_2config_8php.html#afe6e9ed40480c14cb7a119fb84cb557a',1,'$MAIL_LOG_PATH(): config.php']]], - ['_24memory',['$memory',['../classTicket__Info.html#a5e20a9a3e12271b3b8d685805590c9e0',1,'Ticket_Info']]], - ['_24name',['$name',['../classSupport__Group.html#ab2fc40d43824ea3e1ce5d86dee0d763b',1,'Support_Group\$name()'],['../classTicket__Category.html#ab2fc40d43824ea3e1ce5d86dee0d763b',1,'Ticket_Category\$name()']]], - ['_24nel3d',['$nel3d',['../classTicket__Info.html#a9b616e5fbafadc93aa4bdf3ccbf31498',1,'Ticket_Info']]], - ['_24os',['$os',['../classTicket__Info.html#a292791d5d8e3ded85cb2e8ec80dea0d9',1,'Ticket_Info']]], - ['_24pagination',['$pagination',['../classTicket__Queue__Handler.html#a388a4a950e936f746d3b9c1b56450ce7',1,'Ticket_Queue_Handler']]], - ['_24params',['$params',['../classTicket__Queue.html#afe68e6fbe7acfbffc0af0c84a1996466',1,'Ticket_Queue']]], - ['_24patch_5fversion',['$patch_version',['../classTicket__Info.html#a55fc0854f90ed36ab9774ba7bd2af53f',1,'Ticket_Info']]], - ['_24pdo',['$PDO',['../classDBLayer.html#acdb2149c05a21fe144fb05ec524a51f3',1,'DBLayer']]], - ['_24permission',['$permission',['../classTicket__User.html#aad04b6f3304fe6a13d5be37f7cd28938',1,'Ticket_User']]], - ['_24priority',['$priority',['../classTicket.html#a2677e505e860db863720ac4e216fd3f2',1,'Ticket']]], - ['_24processor',['$processor',['../classTicket__Info.html#a11fe8ad69d64b596f8b712b0b7e7e1e3',1,'Ticket_Info']]], - ['_24query',['$query',['../classQuerycache.html#af59a5f7cd609e592c41dc3643efd3c98',1,'Querycache\$query()'],['../classTicket__Log.html#af59a5f7cd609e592c41dc3643efd3c98',1,'Ticket_Log\$query()'],['../classTicket__Queue.html#af59a5f7cd609e592c41dc3643efd3c98',1,'Ticket_Queue\$query()']]], - ['_24queue',['$queue',['../classTicket.html#a4a0b48f6ae2fcb248a4f0288c7c344a6',1,'Ticket\$queue()'],['../classTicket__Queue__Handler.html#a4a0b48f6ae2fcb248a4f0288c7c344a6',1,'Ticket_Queue_Handler\$queue()']]], - ['_24receivemail',['$receiveMail',['../classWebUsers.html#a3c74ba660e348124f36d978b137f691d',1,'WebUsers']]], - ['_24server_5ftick',['$server_tick',['../classTicket__Info.html#aeac33ccad750e9ee81a22414db1224ab',1,'Ticket_Info']]], - ['_24sgroupid',['$sGroupId',['../classSupport__Group.html#a23265908fce0f131e03ba1ede7f42647',1,'Support_Group']]], - ['_24shardid',['$shardid',['../classTicket__Info.html#ac73283a0a8308fb7594543e4a049942c',1,'Ticket_Info']]], - ['_24sid',['$SID',['../classQuerycache.html#a69c31f890638fa4930097cf55ae27995',1,'Querycache']]], - ['_24sitebase',['$SITEBASE',['../drupal__module_2ryzommanage_2config_8php.html#a9eb41824afc2b8150c27648859f07357',1,'$SITEBASE(): config.php'],['../www_2config_8php.html#a9eb41824afc2b8150c27648859f07357',1,'$SITEBASE(): config.php']]], - ['_24status',['$status',['../classTicket.html#a58391ea75f2d29d5d708d7050b641c33',1,'Ticket']]], - ['_24support_5fgroup_5fimap_5fcryptkey',['$SUPPORT_GROUP_IMAP_CRYPTKEY',['../drupal__module_2ryzommanage_2config_8php.html#a3ed2ac4433023af3e95f8912f00125ea',1,'$SUPPORT_GROUP_IMAP_CRYPTKEY(): config.php'],['../www_2config_8php.html#a3ed2ac4433023af3e95f8912f00125ea',1,'$SUPPORT_GROUP_IMAP_CRYPTKEY(): config.php']]], - ['_24tag',['$tag',['../classSupport__Group.html#a81d5015d41ed8ec66e9db8cdc5db9555',1,'Support_Group']]], - ['_24tcategoryid',['$tCategoryId',['../classTicket__Category.html#a0111df4559c9f524272d94df0b7f9d6b',1,'Ticket_Category']]], - ['_24tcontentid',['$tContentId',['../classTicket__Content.html#a2249787a24edd706ae7a54609a601d6f',1,'Ticket_Content']]], - ['_24ticket',['$ticket',['../classAssigned.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Assigned\$ticket()'],['../classForwarded.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Forwarded\$ticket()'],['../classTicket__Info.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Ticket_Info\$ticket()'],['../classTicket__Log.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Ticket_Log\$ticket()'],['../classTicket__Reply.html#abf7832c7c53a3be2ca8a8fc305006bb0',1,'Ticket_Reply\$ticket()']]], - ['_24ticket_5fcategory',['$ticket_category',['../classTicket.html#a86e470072892575063c478122fb65184',1,'Ticket']]], - ['_24ticket_5flogging',['$TICKET_LOGGING',['../drupal__module_2ryzommanage_2config_8php.html#aa59491d29009336d89423cccd3adc5de',1,'$TICKET_LOGGING(): config.php'],['../www_2config_8php.html#aa59491d29009336d89423cccd3adc5de',1,'$TICKET_LOGGING(): config.php']]], - ['_24ticket_5fmailing_5fsupport',['$TICKET_MAILING_SUPPORT',['../drupal__module_2ryzommanage_2config_8php.html#a23c3d413e56a57bc04d69627a4ed2b14',1,'$TICKET_MAILING_SUPPORT(): config.php'],['../www_2config_8php.html#a23c3d413e56a57bc04d69627a4ed2b14',1,'$TICKET_MAILING_SUPPORT(): config.php']]], - ['_24tid',['$tId',['../classTicket.html#a3eda2fecc2433b6b6b3b957110e937ca',1,'Ticket']]], - ['_24time_5fformat',['$TIME_FORMAT',['../drupal__module_2ryzommanage_2config_8php.html#a613b2c043c06772e7119587b26eb9989',1,'$TIME_FORMAT(): config.php'],['../www_2config_8php.html#a613b2c043c06772e7119587b26eb9989',1,'$TIME_FORMAT(): config.php']]], - ['_24timestamp',['$timestamp',['../classTicket.html#a2b69de9676dd97c675cd4d9bcceb684c',1,'Ticket\$timestamp()'],['../classTicket__Log.html#a2b69de9676dd97c675cd4d9bcceb684c',1,'Ticket_Log\$timestamp()'],['../classTicket__Reply.html#a2b69de9676dd97c675cd4d9bcceb684c',1,'Ticket_Reply\$timestamp()']]], - ['_24tinfoid',['$tInfoId',['../classTicket__Info.html#a4c2ae13b7827d13b9629e3fc57335f8f',1,'Ticket_Info']]], - ['_24title',['$title',['../classTicket.html#ada57e7bb7c152edad18fe2f166188691',1,'Ticket']]], - ['_24tlogid',['$tLogId',['../classTicket__Log.html#a734657bd8aac85b5a33e03646c17eb65',1,'Ticket_Log']]], - ['_24tos_5furl',['$TOS_URL',['../drupal__module_2ryzommanage_2config_8php.html#aef688ce4c627fa2fbd8037fd2cceef78',1,'$TOS_URL(): config.php'],['../www_2config_8php.html#aef688ce4c627fa2fbd8037fd2cceef78',1,'$TOS_URL(): config.php']]], - ['_24treplyid',['$tReplyId',['../classTicket__Reply.html#a29f22c2783e510d4764a99a648a0cc36',1,'Ticket_Reply']]], - ['_24tuserid',['$tUserId',['../classTicket__User.html#a2f1828693b198682ae3e926e63a4c110',1,'Ticket_User']]], - ['_24type',['$type',['../classQuerycache.html#a9a4a6fba2208984cabb3afacadf33919',1,'Querycache']]], - ['_24uid',['$uId',['../classWebUsers.html#a8f11c60ae8f70a5059b97bc0ea9d0de5',1,'WebUsers']]], - ['_24user',['$user',['../classAssigned.html#a598ca4e71b15a1313ec95f0df1027ca5',1,'Assigned\$user()'],['../classIn__Support__Group.html#a598ca4e71b15a1313ec95f0df1027ca5',1,'In_Support_Group\$user()']]], - ['_24user_5fid',['$user_id',['../classTicket__Info.html#af0fcd925f00973e32f7214859dfb3c6b',1,'Ticket_Info']]], - ['_24user_5fposition',['$user_position',['../classTicket__Info.html#afc9fcd144a71e56898632daf43854aa7',1,'Ticket_Info']]], - ['_24view_5fposition',['$view_position',['../classTicket__Info.html#ae325cbe2a7e27757b90b12d595c4dfe9',1,'Ticket_Info']]], - ['_24webpath',['$WEBPATH',['../drupal__module_2ryzommanage_2config_8php.html#a562d30b98806af1e001a3ff855e8890a',1,'$WEBPATH(): config.php'],['../www_2config_8php.html#a562d30b98806af1e001a3ff855e8890a',1,'$WEBPATH(): config.php']]] -]; diff --git a/code/web/docs/ams/html/sgroup__list_8php.html b/code/web/docs/ams/html/sgroup__list_8php.html deleted file mode 100644 index ec06aedcf..000000000 --- a/code/web/docs/ams/html/sgroup__list_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/sgroup_list.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/sgroup_list.php File Reference
    -
    -
    - - - - -

    -Functions

     sgroup_list ()
     This function is beign used to load info that's needed for the sgroup_list page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    sgroup_list ()
    -
    -
    - -

    This function is beign used to load info that's needed for the sgroup_list page.

    -

    check if the person who wants to view this page is a mod/admin, if this is not the case, he will be redirected to an error page. It will return all suppport groups information. Also if the $_GET['delete'] var is set and the user is an admin, he will delete a specific entry.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/show__queue_8php.html b/code/web/docs/ams/html/show__queue_8php.html deleted file mode 100644 index 0ee887073..000000000 --- a/code/web/docs/ams/html/show__queue_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_queue.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_queue.php File Reference
    -
    -
    - - - - -

    -Functions

     show_queue ()
     This function is beign used to load info that's needed for the show_queue page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_queue ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_queue page.

    -

    check if the person who wants to view this page is a mod/admin, if this is not the case, he will be redirected to an error page. if an action is set (this is done by $_GET['action']) it will try to execute it first, actions are: assign a ticket, unassign a ticket an create a queue. There are a few predefined queues which is the 'all tickets' queue, 'archive' queue, 'todo' queue, .. these are passed by $_GET['get']. if $_GET['get'] = create; then it's a custom made queue, this will call the createQueue function which builds the query that we will later use to get the tickets. The tickets fetched will be returned and used in the template. Now why use POST and GET params here and have a createQueue function twice? Well the first time someone creates a queue the POST variables will be used, however after going to the next page it will use the GET params.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/show__reply_8php.html b/code/web/docs/ams/html/show__reply_8php.html deleted file mode 100644 index 0be3d45f5..000000000 --- a/code/web/docs/ams/html/show__reply_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_reply.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_reply.php File Reference
    -
    -
    - - - - -

    -Functions

     show_reply ()
     This function is beign used to load info that's needed for the show_reply page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_reply ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_reply page.

    -

    check if the person is allowed to see the reply, if not he'll be redirected to an error page. data regarding to the reply will be returned by this function that will be used by the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/show__sgroup_8php.html b/code/web/docs/ams/html/show__sgroup_8php.html deleted file mode 100644 index fdffe05d6..000000000 --- a/code/web/docs/ams/html/show__sgroup_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_sgroup.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_sgroup.php File Reference
    -
    -
    - - - - -

    -Functions

     show_sgroup ()
     This function is beign used to load info that's needed for the show_sgroup page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_sgroup ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_sgroup page.

    -

    check if the person browsing this page is a mod/admin, if not he'll be redirected to an error page. if the $_GET['delete'] var is set and the user executing is an admin, an entry will be deleted out of the support group. A list of users that are member of the group will be returned, which can be used by the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/show__ticket_8php.html b/code/web/docs/ams/html/show__ticket_8php.html deleted file mode 100644 index 4d8746ec5..000000000 --- a/code/web/docs/ams/html/show__ticket_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket.php File Reference
    -
    -
    - - - - -

    -Functions

     show_ticket ()
     This function is beign used to load info that's needed for the show_ticket page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_ticket ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_ticket page.

    -

    check if the person browsing this page is a mod/admin or the ticket creator himself, if not he'll be redirected to an error page. if the $_GET['action'] var is set and the user executing is a mod/admin, it will try to execute the action. The actions here are: forwarding of a ticket, assigning a ticket and unassigning a ticket. This function returns a lot of information that will be used by the template to show the ticket. Mods/admins will be able to also see hidden replies to a ticket.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/show__ticket__info_8php.html b/code/web/docs/ams/html/show__ticket__info_8php.html deleted file mode 100644 index 91ee2707a..000000000 --- a/code/web/docs/ams/html/show__ticket__info_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket_info.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket_info.php File Reference
    -
    -
    - - - - -

    -Functions

     show_ticket_info ()
     This function is beign used to load info that's needed for the show_ticket_info page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_ticket_info ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_ticket_info page.

    -

    check if the person browsing this page is a mod/admin or the ticket creator himself, if not he'll be redirected to an error page. not all tickets have this page related to it, only tickets created ingame will have additional information. The returned info will be used by the template to show the show_ticket_info page.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/show__ticket__log_8php.html b/code/web/docs/ams/html/show__ticket__log_8php.html deleted file mode 100644 index 603f3dbdc..000000000 --- a/code/web/docs/ams/html/show__ticket__log_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket_log.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_ticket_log.php File Reference
    -
    -
    - - - - -

    -Functions

     show_ticket_log ()
     This function is beign used to load info that's needed for the show_ticket_log page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_ticket_log ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_ticket_log page.

    -

    This page shows the logs related to a ticket: who created the ticket, who replied on it, who viewed it, assigned or forwarded it. Only mods/admins are able to browse the log though. The found information is returned so it can be used by the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/support__group_8php.html b/code/web/docs/ams/html/support__group_8php.html deleted file mode 100644 index d2692f073..000000000 --- a/code/web/docs/ams/html/support__group_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/support_group.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Support_Group
     groups moderators & admins together. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/sync_8php.html b/code/web/docs/ams/html/sync_8php.html deleted file mode 100644 index b7b7907da..000000000 --- a/code/web/docs/ams/html/sync_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/sync.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Sync
     handler for performing changes when shard is back online after being offline. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/sync__cron_8php.html b/code/web/docs/ams/html/sync__cron_8php.html deleted file mode 100644 index ede9924a7..000000000 --- a/code/web/docs/ams/html/sync__cron_8php.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/cron/sync_cron.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/cron/sync_cron.php File Reference
    -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/syncing_8php.html b/code/web/docs/ams/html/syncing_8php.html deleted file mode 100644 index 5b4838a79..000000000 --- a/code/web/docs/ams/html/syncing_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/syncing.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/syncing.php File Reference
    -
    -
    - - - - -

    -Functions

     syncing ()
     This function is beign used to load info that's needed for the syncing page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    syncing ()
    -
    -
    - -

    This function is beign used to load info that's needed for the syncing page.

    -

    this function is used for notifying admins that there are unsynced changes, a brief overview of the non syned changes will be shown. The entries are being loaded here so that they can be passed to the template itself. Only admins can browse this page, others will be redirected to an error page.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/tab_a.png b/code/web/docs/ams/html/tab_a.png deleted file mode 100644 index 2d99ef23fed78c7683f0b5aa803d937060d288c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!Qo)`sjv*C{Z|CmjY;X`^DSv)) z;hc^cTF;t%XWXdwWP5+kt?jQ5uhqKtjd^EY`^^-S;M%tFAj_l)EwVTK)E@1LSD0{e q?a6($SGQTzz1#QBzr0NMKf^0WCX-0bi?u-G89ZJ6T-G@yGywp8?ljB* diff --git a/code/web/docs/ams/html/tab_b.png b/code/web/docs/ams/html/tab_b.png deleted file mode 100644 index b2c3d2be3c7e518fbca6bb30f571882e72fc506d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!Qk9-Ajv*C{Z|~mbJ)|JfaM8Xd zIP7xAmLwau9@iXhZTrl-TjWj9jM#?{xt`6uU{<)jb9Suc^QnbhJ(o{ib8=j9u0_mE8M7kgF7f<7W7IEf=8(L_qx|g0H;V7iPxm&Q@G7p8W2Kx&iT|YUM=ITC zY<0Qbr;u&AtXD{o@41wH=7&d8=2Z_{M9Tsa=g*t*@A3H$UOlxZk7?f6RUWpx>Fc_L s#LQ{edY3MpIXkMeV^&YV=9fR%8Jv|Kya=#u06K}m)78&qol`;+0RKEt)&Kwi diff --git a/code/web/docs/ams/html/tab_s.png b/code/web/docs/ams/html/tab_s.png deleted file mode 100644 index 978943ac807718de0e69e5a585a8f0a1e5999285..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^j6kfy!2~3aiye;!QZ1e?jv*C{Z|}b5Yzkm-c<7z3 zq^cq0=~}Z;b(!Zvb5Z%sTRFKGlz1=qOFg;myyu?$r`wZb^irPsN1a)6)TwB0r+)wb zPL25;=adu89?fTK`qDR>$D*)b_WOmdKI;Vst02j(hg8%>k diff --git a/code/web/docs/ams/html/tabs.css b/code/web/docs/ams/html/tabs.css deleted file mode 100644 index 21920562a..000000000 --- a/code/web/docs/ams/html/tabs.css +++ /dev/null @@ -1,59 +0,0 @@ -.tabs, .tabs2, .tabs3 { - background-image: url('tab_b.png'); - width: 100%; - z-index: 101; - font-size: 13px; -} - -.tabs2 { - font-size: 10px; -} -.tabs3 { - font-size: 9px; -} - -.tablist { - margin: 0; - padding: 0; - display: table; -} - -.tablist li { - float: left; - display: table-cell; - background-image: url('tab_b.png'); - line-height: 36px; - list-style: none; -} - -.tablist a { - display: block; - padding: 0 20px; - font-weight: bold; - background-image:url('tab_s.png'); - background-repeat:no-repeat; - background-position:right; - color: #283A5D; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; - outline: none; -} - -.tabs3 .tablist a { - padding: 0 10px; -} - -.tablist a:hover { - background-image: url('tab_h.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); - text-decoration: none; -} - -.tablist li.current a { - background-image: url('tab_a.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); -} diff --git a/code/web/docs/ams/html/ticket_8php.html b/code/web/docs/ams/html/ticket_8php.html deleted file mode 100644 index 09e6d6329..000000000 --- a/code/web/docs/ams/html/ticket_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket
     class that handles most ticket related functions. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__category_8php.html b/code/web/docs/ams/html/ticket__category_8php.html deleted file mode 100644 index e84fafcf0..000000000 --- a/code/web/docs/ams/html/ticket__category_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_category.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Category
     Class related to the ticket categories. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__content_8php.html b/code/web/docs/ams/html/ticket__content_8php.html deleted file mode 100644 index 69dbd3954..000000000 --- a/code/web/docs/ams/html/ticket__content_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_content.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Content
     Class that handles the content of a reply. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__info_8php.html b/code/web/docs/ams/html/ticket__info_8php.html deleted file mode 100644 index e8e1d079f..000000000 --- a/code/web/docs/ams/html/ticket__info_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_info.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Info
     Class that handles additional info sent by ticket creation ingame. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__log_8php.html b/code/web/docs/ams/html/ticket__log_8php.html deleted file mode 100644 index 645bb27d3..000000000 --- a/code/web/docs/ams/html/ticket__log_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_log.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Log
     Class that handles the logging. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__queue_8php.html b/code/web/docs/ams/html/ticket__queue_8php.html deleted file mode 100644 index 6b78f9c7a..000000000 --- a/code/web/docs/ams/html/ticket__queue_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Queue
     Data class that holds a lot of queries that load specific tickets. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__queue__handler_8php.html b/code/web/docs/ams/html/ticket__queue__handler_8php.html deleted file mode 100644 index fa7720f16..000000000 --- a/code/web/docs/ams/html/ticket__queue__handler_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue_handler.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_queue_handler.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Queue_Handler
     returns tickets (queues) that are related in some way. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__reply_8php.html b/code/web/docs/ams/html/ticket__reply_8php.html deleted file mode 100644 index 9594115b5..000000000 --- a/code/web/docs/ams/html/ticket__reply_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_reply.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_Reply
     handles functions related to replies on tickets. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/ticket__user_8php.html b/code/web/docs/ams/html/ticket__user_8php.html deleted file mode 100644 index e106212f4..000000000 --- a/code/web/docs/ams/html/ticket__user_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/ticket_user.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Ticket_User
     user entry point in the ticket system. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/todo.html b/code/web/docs/ams/html/todo.html deleted file mode 100644 index e630d4465..000000000 --- a/code/web/docs/ams/html/todo.html +++ /dev/null @@ -1,115 +0,0 @@ - - - - - -Ryzom Account Management System: Todo List - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - -
    -
    -
    -
    Todo List
    -
    -
    -
    -
    Global Helpers ()
    -
    for the drupal module it might be possible that drupal_mkdir needs to be used instead of mkdir, also this should be in the install.php instead.
    -
    Global Mail_Handler (&$structure)
    -
    take care of the HTML part of incoming emails.
    -
    Class Querycache
    -
    make sure that the querycache class is being used by the sync class and also for inserting the queries themselfs into it. Atm this class isn't used yet if I remember correctly
    -
    Global Ticket ($ticket_id, $newStatus, $newPriority, $author)
    -
    break this function up into a updateStatus (already exists) and updatePriority function and perhaps write a wrapper function for the combo.
    -
    Global Ticket_Log ($ticket_id)
    -
    only use one of the 2 comparable functions in the future and make the other depricated.
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/userlist_8php.html b/code/web/docs/ams/html/userlist_8php.html deleted file mode 100644 index 149a7973c..000000000 --- a/code/web/docs/ams/html/userlist_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/userlist.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/userlist.php File Reference
    -
    -
    - - - - -

    -Functions

     userlist ()
     This function is beign used to load info that's needed for the userlist page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    userlist ()
    -
    -
    - -

    This function is beign used to load info that's needed for the userlist page.

    -

    this function will return all users by using he pagination class, so that it can be used in the template. Only Mods and Admins can browse this page though.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/users_8php.html b/code/web/docs/ams/html/users_8php.html deleted file mode 100644 index baefc8a11..000000000 --- a/code/web/docs/ams/html/users_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/ams_lib/autoload/users.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  Users
     handles basic user registration & management functions (shard related). More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/www_2config_8php.html b/code/web/docs/ams/html/www_2config_8php.html deleted file mode 100644 index 2e598c248..000000000 --- a/code/web/docs/ams/html/www_2config_8php.html +++ /dev/null @@ -1,820 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/config.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/config.php File Reference
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    -Variables

     $cfg ['db']['web']['host'] = 'localhost'
     This file contains all variables needed by other php scripts.
     $cfg ['db']['web']['port'] = '3306'
     $cfg ['db']['web']['name'] = 'ryzom_ams'
     $cfg ['db']['web']['user'] = 'shard'
     $cfg ['db']['web']['pass'] = ''
     $cfg ['db']['lib']['host'] = 'localhost'
     $cfg ['db']['lib']['port'] = '3306'
     $cfg ['db']['lib']['name'] = 'ryzom_ams_lib'
     $cfg ['db']['lib']['user'] = 'shard'
     $cfg ['db']['lib']['pass'] = ''
     $cfg ['db']['shard']['host'] = 'localhost'
     $cfg ['db']['shard']['port'] = '3306'
     $cfg ['db']['shard']['name'] = 'nel'
     $cfg ['db']['shard']['user'] = 'shard'
     $cfg ['db']['shard']['pass'] = ''
     $cfg ['db']['ring']['host'] = 'localhost'
     $cfg ['db']['ring']['port'] = '3306'
     $cfg ['db']['ring']['name'] = 'ring_open'
     $cfg ['db']['ring']['user'] = 'shard'
     $cfg ['db']['ring']['pass'] = ''
     $cfg ['mail']['default_mailserver'] = '{imap.gmail.com:993/imap/ssl}INBOX'
     $cfg ['mail']['default_groupemail'] = 'amsryzom@gmail.com'
     $cfg ['mail']['default_groupname'] = 'Ryzomcore Support'
     $cfg ['mail']['default_username'] = 'amsryzom@gmail.com'
     $cfg ['mail']['default_password'] = 'lol123bol'
     $cfg ['mail']['host'] = "ryzomcore.com"
     $SUPPORT_GROUP_IMAP_CRYPTKEY = "azerty"
     $TICKET_MAILING_SUPPORT = true
     $MAIL_DIR = "/tmp/mail"
     $MAIL_LOG_PATH = "/tmp/mail/cron_mail.log"
     $TOS_URL = "http://createyourtos.com"
     $cfg ['crypt']['key'] = 'Sup3rS3cr3tStuff'
     $cfg ['crypt']['enc_method'] = 'AES-256-CBC'
     $cfg ['crypt']['hash_method'] = "SHA512"
     $ALLOW_UNKNOWN = true
     $CREATE_RING = true
     $AMS_LIB = dirname( dirname( __FILE__ ) ) . '/ams_lib'
     $AMS_TRANS = $AMS_LIB . '/translations'
     $AMS_CACHEDIR = $AMS_LIB . '/cache'
     $SITEBASE = dirname( __FILE__ ) . '/html/'
     $BASE_WEBPATH = 'http://localhost:40917/www/html'
     $IMAGELOC_WEBPATH = 'http://localhost:40917/ams_lib/img'
     $WEBPATH = $BASE_WEBPATH . '/index.php'
     $INGAME_WEBPATH = $BASE_WEBPATH . '/index.php'
     $CONFIG_PATH = dirname( __FILE__ )
     $DEFAULT_LANGUAGE = 'en'
     $TICKET_LOGGING = true
     $TIME_FORMAT = "m-d-Y H:i:s"
     $INGAME_LAYOUT = "basic"
     $FORCE_INGAME = false
    -

    Variable Documentation

    - -
    -
    - - - - -
    $ALLOW_UNKNOWN = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $AMS_CACHEDIR = $AMS_LIB . '/cache'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $AMS_LIB = dirname( dirname( __FILE__ ) ) . '/ams_lib'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $AMS_TRANS = $AMS_LIB . '/translations'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $BASE_WEBPATH = 'http://localhost:40917/www/html'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['host'] = 'localhost'
    -
    -
    - -

    This file contains all variables needed by other php scripts.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['port'] = '3306'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['name'] = 'ryzom_ams'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['user'] = 'shard'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['web']['pass'] = ''
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['host'] = 'localhost'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['port'] = '3306'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['name'] = 'ryzom_ams_lib'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['user'] = 'shard'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['lib']['pass'] = ''
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['host'] = 'localhost'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['port'] = '3306'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['name'] = 'nel'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['user'] = 'shard'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['shard']['pass'] = ''
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['host'] = 'localhost'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['port'] = '3306'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['name'] = 'ring_open'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['user'] = 'shard'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['db']['ring']['pass'] = ''
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_mailserver'] = '{imap.gmail.com:993/imap/ssl}INBOX'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_groupemail'] = 'amsryzom@gmail.com'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_groupname'] = 'Ryzomcore Support'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_username'] = 'amsryzom@gmail.com'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['default_password'] = 'lol123bol'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['mail']['host'] = "ryzomcore.com"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['crypt']['key'] = 'Sup3rS3cr3tStuff'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['crypt']['enc_method'] = 'AES-256-CBC'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $cfg['crypt']['hash_method'] = "SHA512"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $CONFIG_PATH = dirname( __FILE__ )
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $CREATE_RING = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $DEFAULT_LANGUAGE = 'en'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $FORCE_INGAME = false
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $IMAGELOC_WEBPATH = 'http://localhost:40917/ams_lib/img'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $INGAME_LAYOUT = "basic"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $INGAME_WEBPATH = $BASE_WEBPATH . '/index.php'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $MAIL_DIR = "/tmp/mail"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $MAIL_LOG_PATH = "/tmp/mail/cron_mail.log"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $SITEBASE = dirname( __FILE__ ) . '/html/'
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $SUPPORT_GROUP_IMAP_CRYPTKEY = "azerty"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TICKET_LOGGING = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TICKET_MAILING_SUPPORT = true
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TIME_FORMAT = "m-d-Y H:i:s"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $TOS_URL = "http://createyourtos.com"
    -
    -
    - -
    -
    - -
    -
    - - - - -
    $WEBPATH = $BASE_WEBPATH . '/index.php'
    -
    -
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/www_2html_2autoload_2webusers_8php.html b/code/web/docs/ams/html/www_2html_2autoload_2webusers_8php.html deleted file mode 100644 index 9bf55da85..000000000 --- a/code/web/docs/ams/html/www_2html_2autoload_2webusers_8php.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/autoload/webusers.php File Reference
    -
    -
    - - - - -

    -Data Structures

    class  WebUsers
     handles CMS/WWW related functions regarding user management & registration. More...
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/www_2html_2inc_2logout_8php.html b/code/web/docs/ams/html/www_2html_2inc_2logout_8php.html deleted file mode 100644 index d6c860de7..000000000 --- a/code/web/docs/ams/html/www_2html_2inc_2logout_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/logout.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/logout.php File Reference
    -
    -
    - - - - -

    -Functions

     logout ()
     This function is beign used to load info that's needed for the logout page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    logout ()
    -
    -
    - -

    This function is beign used to load info that's needed for the logout page.

    -

    it will just unset & destroy the session

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/www_2html_2inc_2settings_8php.html b/code/web/docs/ams/html/www_2html_2inc_2settings_8php.html deleted file mode 100644 index d49c641ac..000000000 --- a/code/web/docs/ams/html/www_2html_2inc_2settings_8php.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/settings.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/settings.php File Reference
    -
    -
    - - - - - -

    -Functions

     settings ()
     This function is beign used to load info that's needed for the settings page.
     getCountryArray ()
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    getCountryArray ()
    -
    -
    - -
    -
    - -
    -
    - - - - - - - -
    settings ()
    -
    -
    - -

    This function is beign used to load info that's needed for the settings page.

    -

    check if the person who wants to view this page is a mod/admin or the user to whom te settings belong himself, if this is not the case, he will be redirected to an error page. it will return a lot of information of that user, that's being used for loading the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - diff --git a/code/web/docs/ams/html/www_2html_2inc_2show__user_8php.html b/code/web/docs/ams/html/www_2html_2inc_2show__user_8php.html deleted file mode 100644 index 48f54f06d..000000000 --- a/code/web/docs/ams/html/www_2html_2inc_2show__user_8php.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - -Ryzom Account Management System: /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_user.php File Reference - - - - - - - - - - - -
    - - -
    - - - - - - - - - - - - - -
    -
    Ryzom Account Management System -  1.0 -
    - -
    -
    - - - - - -
    -
    - -
    -
    /home/daan/ryzom/ryzomcore/code/ryzom/tools/server/ryzom_ams/www/html/inc/show_user.php File Reference
    -
    -
    - - - - -

    -Functions

     show_user ()
     This function is beign used to load info that's needed for the show_user page.
    -

    Function Documentation

    - -
    -
    - - - - - - - -
    show_user ()
    -
    -
    - -

    This function is beign used to load info that's needed for the show_user page.

    -

    Users can only browse their own user page, while mods/admins can browse all user pages. The current settings of the user being browsed will be loaded, as also their created tickets and this info will be returned so it can be used by the template.

    -
    Author:
    Daan Janssens, mentored by Matthew Lagoe
    - -
    -
    -
    - - - - -
    - -
    - - - - - - - From 64fafda9bc7d2a710b3623cc16f65e346ef1c8ba Mon Sep 17 00:00:00 2001 From: botanic Date: Fri, 15 Aug 2014 03:55:49 -0700 Subject: [PATCH 256/282] updated hgignore --- .hgignore | 29 +++-- .../tools/server/ryzom_ams/www/config.php | 118 ++++++++++++++++++ .../tools/server/ryzom_ams/www/is_installed | 0 3 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 code/ryzom/tools/server/ryzom_ams/www/config.php create mode 100644 code/ryzom/tools/server/ryzom_ams/www/is_installed diff --git a/.hgignore b/.hgignore index 829f8812b..1f8453d8a 100644 --- a/.hgignore +++ b/.hgignore @@ -204,16 +204,7 @@ code/nel/tools/pacs/build_rbank/build_rbank code/ryzom/common/data_leveldesign/leveldesign/game_element/xp_table/skills.skill_tree code/ryzom/common/data_leveldesign/leveldesign/game_element/xp_table/xptable.xp_table code/ryzom/tools/server/sql/ryzom_admin_default_data.sql -code/ryzom/tools/server/ryzom_ams/drupal -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/autoload -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/configs -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/cron -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/img -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/plugins -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/smarty -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/translations -code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/libinclude.php -code/ryzom/tools/server/ryzom_ams/www/html/templates_c + # Linux server compile code/ryzom/server/src/entities_game_service/entities_game_service @@ -227,11 +218,23 @@ code/ryzom/server/src/ryzom_welcome_service/ryzom_welcome_service code/ryzom/server/src/tick_service/tick_service # WebTT temp dir code/ryzom/tools/server/www/webtt/app/tmp -code\ryzom\tools\server\ryzom_ams\old # AMS ignore -code/ryzom/tools/server/ryzom_ams/www/config.php -code/ryzom/tools/server/ryzom_ams/www/is_installed +code/web/public_php/ams/is_installed +code/web/docs/ams/html +code/web/public_php/ams/templates_c +code/ryzom/tools/server/ryzom_ams/drupal +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/autoload +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/configs +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/cron +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/img +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/plugins +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/smarty +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/translations +code/ryzom/tools/server/ryzom_ams/drupal_module/ryzommanage/ams_lib/libinclude.php +code/ryzom/tools/server/ryzom_ams/old + + #tools and external dir's external diff --git a/code/ryzom/tools/server/ryzom_ams/www/config.php b/code/ryzom/tools/server/ryzom_ams/www/config.php new file mode 100644 index 000000000..7ade3efb6 --- /dev/null +++ b/code/ryzom/tools/server/ryzom_ams/www/config.php @@ -0,0 +1,118 @@ + Date: Fri, 15 Aug 2014 23:49:12 +0200 Subject: [PATCH 257/282] Fixed a crash. Setting a value into a valueless Georges node doesn't assign a type, which leads to a crash when trying to poll the value directly from the node. However if the value is polled indirectly using the node's name the value can be retrieved without a crash. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/georges_editor/browser_ctrl.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 207c665a9..5499854a9 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -35,6 +35,7 @@ public: mgr = new QtVariantPropertyManager(); factory = new QtVariantEditorFactory(); m_currentNode = NULL; + m_rootNode = NULL; } ~BrowserCtrlPvt() @@ -56,9 +57,11 @@ public: { t = getValueType( elm.Element->getType() ); - NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); + std::string formName; + elm.Element->getFormName( formName, NULL ); + std::string v; - atom->getValue( v, NLGEORGES::UFormElm::NoEval ); + m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); value = v.c_str(); } @@ -98,17 +101,21 @@ public: std::string k = p->propertyName().toUtf8().constData(); std::string v = value.toString().toUtf8().constData(); - m_currentNode->setValueByName( v.c_str(), k.c_str() ); + bool created = false; + m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); } QtVariantPropertyManager* manager() const{ return mgr; } + void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } + private: QtVariantPropertyManager *mgr; QtVariantEditorFactory *factory; QtTreePropertyBrowser *m_browser; NLGEORGES::UFormElm *m_currentNode; + NLGEORGES::CFormElm *m_rootNode; }; BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : @@ -131,6 +138,8 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); NLGEORGES::UFormElm &root = m_form->getRootNode(); + NLGEORGES::CFormElm *rootNode = dynamic_cast< NLGEORGES::CFormElm* >( &root ); + m_pvt->setRootNode( rootNode ); NLGEORGES::UFormElm *node = NULL; bool b = false; From 5812058ea650234f12e49e00f8c849f2403e8adc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:01:07 +0200 Subject: [PATCH 258/282] Only add atoms to the property browser. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/georges_editor/browser_ctrl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 5499854a9..eb2ef7508 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -47,7 +47,7 @@ public: m_browser = NULL; } - void setupElement( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) + void setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) { QString key = elm.Name.c_str(); QString value = ""; @@ -70,12 +70,15 @@ public: m_browser->addProperty( p ); } - void setupForm( NLGEORGES::CFormElmStruct *st ) + void setupStruct( NLGEORGES::CFormElmStruct *st ) { for( int i = 0; i < st->Elements.size(); i++ ) { NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - setupElement( elm ); + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + + setupAtom( elm ); } m_currentNode = st; @@ -152,7 +155,7 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) return; NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - m_pvt->setupForm( st ); + m_pvt->setupStruct( st ); enableMgrConnections(); From 99502a1bfc7057fd294ba27a6acae4995ed4390c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:47:29 +0200 Subject: [PATCH 259/282] Handle selected arrays too ( show size, changing it isn't implemented yet ). --HG-- branch : gsoc2014-dfighter --- .../plugins/georges_editor/browser_ctrl.cpp | 67 ++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index eb2ef7508..ded5737ce 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -70,18 +70,45 @@ public: m_browser->addProperty( p ); } - void setupStruct( NLGEORGES::CFormElmStruct *st ) + void setupArray( NLGEORGES::UFormElm *node ) { + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); + uint size = 0; + arr->getArraySize( size ); + + std::string name; + arr->getFormName( name, NULL ); + QString key = name.c_str(); + key = key.mid( 1 ); + + QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); + p->setValue( size ); + m_browser->addProperty( p ); + + } + + void setupStruct( NLGEORGES::UFormElm *node ) + { + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + for( int i = 0; i < st->Elements.size(); i++ ) { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) - continue; - + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; setupAtom( elm ); } + } - m_currentNode = st; + void setupNode( NLGEORGES::UFormElm *node ) + { + if( node->isStruct() ) + setupStruct( node ); + else + if( node->isArray() ) + setupArray( node ); + else + return; + + m_currentNode = node; m_browser->setFactoryForManager( mgr, factory ); } @@ -96,11 +123,8 @@ public: m_browser = browser; } - void onValueChanged( QtProperty *p, const QVariant &value ) + void onStructValueChanged( QtProperty *p, const QVariant &value ) { - if( m_currentNode == NULL ) - return; - std::string k = p->propertyName().toUtf8().constData(); std::string v = value.toString().toUtf8().constData(); @@ -108,6 +132,23 @@ public: m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); } + void onArrayValueChanged( QtProperty *p, const QVariant &value ) + { + + } + + void onValueChanged( QtProperty *p, const QVariant &value ) + { + if( m_currentNode == NULL ) + return; + + if( m_currentNode->isStruct() ) + onStructValueChanged( p, value ); + else + if( m_currentNode->isArray() ) + onArrayValueChanged( p, value ); + } + QtVariantPropertyManager* manager() const{ return mgr; } void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } @@ -151,11 +192,7 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) if( !b || ( node == NULL ) ) return; - if( !node->isStruct() ) - return; - - NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - m_pvt->setupStruct( st ); + m_pvt->setupNode( node ); enableMgrConnections(); From 2a0af6cabf1810208145cc9f2a84c5a4b0fafd61 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:51:30 +0200 Subject: [PATCH 260/282] Only add atoms to the property browser.. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/georges_editor/browser_ctrl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index ded5737ce..1a71b57c6 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -94,6 +94,9 @@ public: for( int i = 0; i < st->Elements.size(); i++ ) { NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + setupAtom( elm ); } } From 6d074bc618376a150757aaf1bf2754ca79040837 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 03:10:50 +0200 Subject: [PATCH 261/282] Only add atoms to the property browser.. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/georges_editor/browser_ctrl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 1a71b57c6..a6dd288d8 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -97,6 +97,13 @@ public: if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) continue; + if( elm.Element == NULL ) + { + NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); + if( entry.getArrayFlag() ) + continue; + } + setupAtom( elm ); } } From fb5ce7baacb77b75427f3df8015587fa09efae41 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 03:46:52 +0200 Subject: [PATCH 262/282] Use the string 'array size' as the name for the property holding the array size. --HG-- branch : gsoc2014-dfighter --- code/studio/src/plugins/georges_editor/browser_ctrl.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index a6dd288d8..f430ff675 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -76,11 +76,7 @@ public: uint size = 0; arr->getArraySize( size ); - std::string name; - arr->getFormName( name, NULL ); - QString key = name.c_str(); - key = key.mid( 1 ); - + QString key = QObject::tr( "Array size" ); QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); p->setValue( size ); m_browser->addProperty( p ); @@ -144,6 +140,9 @@ public: void onArrayValueChanged( QtProperty *p, const QVariant &value ) { + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); + std::string formName; + arr->getFormName( formName, NULL ); } From f718380f5272d128c5fb4cfd46b4a6901d311ec4 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sat, 16 Aug 2014 14:51:29 +0200 Subject: [PATCH 263/282] Zone light exporter adjust --- code/nel/tools/build_gamedata/all_install_dev.bat | 9 +++++++++ .../build_gamedata/processes/zone_light/1_export.py | 1 + 2 files changed, 10 insertions(+) create mode 100644 code/nel/tools/build_gamedata/all_install_dev.bat diff --git a/code/nel/tools/build_gamedata/all_install_dev.bat b/code/nel/tools/build_gamedata/all_install_dev.bat new file mode 100644 index 000000000..6791bbea0 --- /dev/null +++ b/code/nel/tools/build_gamedata/all_install_dev.bat @@ -0,0 +1,9 @@ +title Ryzom Core: 3_install.py +3_install.py +title Ryzom Core: a1_worldedit_data.py +a1_worldedit_data.py +title Ryzom Core: b1_client_dev.py +b1_client_dev.py +title Ryzom Core: b2_shard_data.py +b2_shard_data.py +title Ryzom Core: Ready diff --git a/code/nel/tools/build_gamedata/processes/zone_light/1_export.py b/code/nel/tools/build_gamedata/processes/zone_light/1_export.py index cede7d658..615a4dffa 100755 --- a/code/nel/tools/build_gamedata/processes/zone_light/1_export.py +++ b/code/nel/tools/build_gamedata/processes/zone_light/1_export.py @@ -55,6 +55,7 @@ for dir in WaterMapSourceDirectories: destDir = DatabaseDirectory + "/" + dir mkPath(log, destDir) copyFilesExtNoTreeIfNeeded(log, srcDir, destDir, ".tga") + copyFilesExtNoTreeIfNeeded(log, srcDir, destDir, ".png") printLog(log, "") log.close() From 5bc60987be583e2dce2cdf6b43d5b44af353ee67 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sat, 16 Aug 2014 14:51:29 +0200 Subject: [PATCH 264/282] Maxscript selection clear fix --- .../build_gamedata/generators/max_exporter_scripts/clod.ms | 1 + .../build_gamedata/generators/max_exporter_scripts/cmb.ms | 1 + .../tools/build_gamedata/generators/max_exporter_scripts/ig.ms | 2 ++ .../generators/max_exporter_scripts/pacs_prim.ms | 1 + .../build_gamedata/generators/max_exporter_scripts/shape.ms | 1 + .../build_gamedata/generators/max_exporter_scripts/veget.ms | 1 + .../build_gamedata/generators/max_exporter_scripts/zone.ms | 1 + .../build_gamedata/processes/clodbank/maxscript/clod_export.ms | 1 + .../tools/build_gamedata/processes/ig/maxscript/ig_export.ms | 2 ++ .../build_gamedata/processes/ligo/maxscript/nel_ligo_export.ms | 3 +++ .../processes/pacs_prim/maxscript/pacs_prim_export.ms | 1 + .../build_gamedata/processes/rbank/maxscript/cmb_export.ms | 1 + .../build_gamedata/processes/shape/maxscript/shape_export.ms | 1 + .../build_gamedata/processes/veget/maxscript/veget_export.ms | 1 + .../build_gamedata/processes/zone/maxscript/zone_export.ms | 1 + 15 files changed, 19 insertions(+) diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/clod.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/clod.ms index 29744c7d1..68c8455d6 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/clod.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/clod.ms @@ -56,6 +56,7 @@ fn runNelMaxExport inputMaxFile = -- unselect max select none + clearSelection() -- Exported object count exported = 0 diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/cmb.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/cmb.ms index 2a7492c29..40feab761 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/cmb.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/cmb.ms @@ -36,6 +36,7 @@ fn runNelMaxExport inputMaxFile = -- Select all collision mesh max select none + clearSelection() for m in geometry do ( if (isToBeExported m) == true then diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/ig.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/ig.ms index 7c9563088..df0ecf7fc 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/ig.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/ig.ms @@ -61,6 +61,7 @@ fn runNelMaxExport inputMaxFile = -- unselect max select none + clearSelection() -- Exported object count exported = 0 @@ -109,6 +110,7 @@ fn runNelMaxExport inputMaxFile = ( -- Select none max select none + clearSelection() -- Select all node in this ig for node in geometry do diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/pacs_prim.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/pacs_prim.ms index 93e94de19..ea730c0b4 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/pacs_prim.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/pacs_prim.ms @@ -10,6 +10,7 @@ fn runNelMaxExport inputMaxFile = -- Select none max select none + clearSelection() -- Select all PACS primitives for i in geometry do diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/shape.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/shape.ms index c1f4761ff..d8d6c8d9d 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/shape.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/shape.ms @@ -199,6 +199,7 @@ fn runNelMaxExportSub inputMaxFile retryCount = -- unselect max select none + clearSelection() -- Exported object count exported = 0 diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/veget.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/veget.ms index f0d5cd584..22c49013a 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/veget.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/veget.ms @@ -46,6 +46,7 @@ fn runNelMaxExport inputMaxFile = -- unselect max select none + clearSelection() -- Exported object count exported = 0 diff --git a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/zone.ms b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/zone.ms index d4ecbe275..338d48733 100755 --- a/code/nel/tools/build_gamedata/generators/max_exporter_scripts/zone.ms +++ b/code/nel/tools/build_gamedata/generators/max_exporter_scripts/zone.ms @@ -40,6 +40,7 @@ fn runNelMaxExport inputMaxFile = -- Select none max select none + clearSelection() -- Found it ? find = false diff --git a/code/nel/tools/build_gamedata/processes/clodbank/maxscript/clod_export.ms b/code/nel/tools/build_gamedata/processes/clodbank/maxscript/clod_export.ms index f01a973e4..a8693dc8a 100755 --- a/code/nel/tools/build_gamedata/processes/clodbank/maxscript/clod_export.ms +++ b/code/nel/tools/build_gamedata/processes/clodbank/maxscript/clod_export.ms @@ -122,6 +122,7 @@ fn runNelMaxExport inputMaxFile = -- unselect max select none + clearSelection() -- Exported object count exported = 0 diff --git a/code/nel/tools/build_gamedata/processes/ig/maxscript/ig_export.ms b/code/nel/tools/build_gamedata/processes/ig/maxscript/ig_export.ms index 526d06dc8..65cb38c4a 100755 --- a/code/nel/tools/build_gamedata/processes/ig/maxscript/ig_export.ms +++ b/code/nel/tools/build_gamedata/processes/ig/maxscript/ig_export.ms @@ -127,6 +127,7 @@ fn runNelMaxExport inputMaxFile = -- unselect max select none + clearSelection() -- Exported object count exported = 0 @@ -175,6 +176,7 @@ fn runNelMaxExport inputMaxFile = ( -- Select none max select none + clearSelection() -- Select all node in this ig for node in geometry do diff --git a/code/nel/tools/build_gamedata/processes/ligo/maxscript/nel_ligo_export.ms b/code/nel/tools/build_gamedata/processes/ligo/maxscript/nel_ligo_export.ms index 4b25c1427..933468459 100755 --- a/code/nel/tools/build_gamedata/processes/ligo/maxscript/nel_ligo_export.ms +++ b/code/nel/tools/build_gamedata/processes/ligo/maxscript/nel_ligo_export.ms @@ -228,6 +228,7 @@ fn exportCollisionsFromZone outputNelDir filename = ( -- Select all collision mesh max select none + clearSelection() for m in geometry do ( if (isToBeExportedCollision m) == true then @@ -311,6 +312,7 @@ fn exportInstanceGroupFromZone inputFile outputPath igName transitionZone cellSi -- unselect max select none + clearSelection() -- Exported object count exported = 0 @@ -372,6 +374,7 @@ fn exportInstanceGroupFromZone inputFile outputPath igName transitionZone cellSi ( -- Select none max select none + clearSelection() for node in objects where classOf node == XRefObject do ( diff --git a/code/nel/tools/build_gamedata/processes/pacs_prim/maxscript/pacs_prim_export.ms b/code/nel/tools/build_gamedata/processes/pacs_prim/maxscript/pacs_prim_export.ms index ddfc0014a..750af80d9 100755 --- a/code/nel/tools/build_gamedata/processes/pacs_prim/maxscript/pacs_prim_export.ms +++ b/code/nel/tools/build_gamedata/processes/pacs_prim/maxscript/pacs_prim_export.ms @@ -76,6 +76,7 @@ fn runNelMaxExport inputMaxFile = -- Select none max select none + clearSelection() -- Select all PACS primitives for i in geometry do diff --git a/code/nel/tools/build_gamedata/processes/rbank/maxscript/cmb_export.ms b/code/nel/tools/build_gamedata/processes/rbank/maxscript/cmb_export.ms index 74cf3a8dd..59b444db3 100755 --- a/code/nel/tools/build_gamedata/processes/rbank/maxscript/cmb_export.ms +++ b/code/nel/tools/build_gamedata/processes/rbank/maxscript/cmb_export.ms @@ -102,6 +102,7 @@ fn runNelMaxExport inputMaxFile = -- Select all collision mesh max select none + clearSelection() for m in geometry do ( if (isToBeExported m) == true then diff --git a/code/nel/tools/build_gamedata/processes/shape/maxscript/shape_export.ms b/code/nel/tools/build_gamedata/processes/shape/maxscript/shape_export.ms index e979f6b0d..16c6dcec9 100755 --- a/code/nel/tools/build_gamedata/processes/shape/maxscript/shape_export.ms +++ b/code/nel/tools/build_gamedata/processes/shape/maxscript/shape_export.ms @@ -265,6 +265,7 @@ fn runNelMaxExportSub inputMaxFile retryCount = -- unselect max select none + clearSelection() -- Exported object count exported = 0 diff --git a/code/nel/tools/build_gamedata/processes/veget/maxscript/veget_export.ms b/code/nel/tools/build_gamedata/processes/veget/maxscript/veget_export.ms index 828a78d42..cbc2f2177 100755 --- a/code/nel/tools/build_gamedata/processes/veget/maxscript/veget_export.ms +++ b/code/nel/tools/build_gamedata/processes/veget/maxscript/veget_export.ms @@ -112,6 +112,7 @@ fn runNelMaxExport inputMaxFile = -- unselect max select none + clearSelection() -- Exported object count exported = 0 diff --git a/code/nel/tools/build_gamedata/processes/zone/maxscript/zone_export.ms b/code/nel/tools/build_gamedata/processes/zone/maxscript/zone_export.ms index 71f63e45b..3a0ebf8fe 100755 --- a/code/nel/tools/build_gamedata/processes/zone/maxscript/zone_export.ms +++ b/code/nel/tools/build_gamedata/processes/zone/maxscript/zone_export.ms @@ -103,6 +103,7 @@ fn runNelMaxExport inputMaxFile = -- Select none max select none + clearSelection() -- Found it ? find = false From 41f6e70dc93f6e7a894c0c8ed022f4c7fbd646c3 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 17 Aug 2014 15:39:30 +0200 Subject: [PATCH 265/282] Fixed #172 XML floating point serialization not using neutral culture --- code/nel/include/nel/misc/i_xml.h | 3 +++ code/nel/src/misc/i_xml.cpp | 43 +++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/misc/i_xml.h b/code/nel/include/nel/misc/i_xml.h index a9452e341..cf2527e21 100644 --- a/code/nel/include/nel/misc/i_xml.h +++ b/code/nel/include/nel/misc/i_xml.h @@ -232,6 +232,9 @@ private: // If not NULL, binary mode detected, use this stream in serials IStream *_BinaryStream; + + // System dependant structure for locale + void* _Locale; }; diff --git a/code/nel/src/misc/i_xml.cpp b/code/nel/src/misc/i_xml.cpp index d8925ddef..3b7f0f9e2 100644 --- a/code/nel/src/misc/i_xml.cpp +++ b/code/nel/src/misc/i_xml.cpp @@ -24,6 +24,11 @@ // Include from libxml2 #include +#if defined(NL_OS_WINDOWS) && defined(NL_COMP_VC_VERSION) && NL_COMP_VC_VERSION >= 80 +#define USE_LOCALE_ATOF +#include +#endif + using namespace std; #define NLMISC_READ_BUFFER_SIZE 1024 @@ -46,6 +51,22 @@ const char SEPARATOR = ' '; serialSeparatedBufferIn( number_as_string ); \ dest = (thetype)convfunc( number_as_string.c_str() ); +#ifdef USE_LOCALE_ATOF + +#define readnumberlocale(dest,thetype,digits,convfunc) \ + string number_as_string; \ + serialSeparatedBufferIn( number_as_string ); \ + dest = (thetype)convfunc( number_as_string.c_str(), (_locale_t)_Locale ); + +#define nl_atof _atof_l + +#else + +#define readnumberlocale(dest,thetype,digits,convfunc) readnumber(dest,thetype,digits,convfunc) +#define nl_atof atof + +#endif + // *************************************************************************** inline void CIXml::flushContentString () @@ -70,6 +91,13 @@ CIXml::CIXml () : IStream (true /* Input mode */) _ErrorString = ""; _TryBinaryMode = false; _BinaryStream = NULL; + +#ifdef USE_LOCALE_ATOF + // create C numeric locale + _Locale = _create_locale(LC_NUMERIC, "C"); +#else + _Locale = NULL; +#endif } // *************************************************************************** @@ -85,6 +113,13 @@ CIXml::CIXml (bool tryBinaryMode) : IStream (true /* Input mode */) _ErrorString = ""; _TryBinaryMode = tryBinaryMode; _BinaryStream = NULL; + +#ifdef USE_LOCALE_ATOF + // create C numeric locale + _Locale = _create_locale(LC_NUMERIC, "C"); +#else + _Locale = NULL; +#endif } // *************************************************************************** @@ -119,6 +154,10 @@ void CIXml::release () _ErrorString = ""; resetPtrTable(); + +#ifdef USE_LOCALE_ATOF + if (_Locale) _free_locale((_locale_t)_Locale); +#endif } // *************************************************************************** @@ -546,7 +585,7 @@ void CIXml::serial(float &b) } else { - readnumber( b, float, 128, atof ); + readnumberlocale( b, float, 128, nl_atof ); } } @@ -560,7 +599,7 @@ void CIXml::serial(double &b) } else { - readnumber( b, double, 128, atof ); + readnumberlocale( b, double, 128, nl_atof ); } } From 75e28415193e7923a18f5bc813107d42f40acbdb Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 15:58:42 +0200 Subject: [PATCH 266/282] Fix continent path bug --- code/nel/tools/3d/zone_lighter/zone_lighter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp index 9b6df0900..1add65a9d 100644 --- a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp +++ b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp @@ -202,7 +202,7 @@ static void loadIGFromContinent(NLMISC::CConfigFile ¶meter, std::list Date: Sun, 17 Aug 2014 16:02:51 +0200 Subject: [PATCH 267/282] Additional fix #172 set _Locale to NULL after release --- code/nel/src/misc/i_xml.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/nel/src/misc/i_xml.cpp b/code/nel/src/misc/i_xml.cpp index 3b7f0f9e2..8a624dd5f 100644 --- a/code/nel/src/misc/i_xml.cpp +++ b/code/nel/src/misc/i_xml.cpp @@ -157,6 +157,7 @@ void CIXml::release () #ifdef USE_LOCALE_ATOF if (_Locale) _free_locale((_locale_t)_Locale); + _Locale = NULL; #endif } From 31e9934ba7a23d865f1c27c4d02bb3d71b945d01 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 17 Aug 2014 16:05:51 +0200 Subject: [PATCH 268/282] Changed #172 XML floating point serialization not using neutral culture --- code/nel/src/misc/i_xml.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/nel/src/misc/i_xml.cpp b/code/nel/src/misc/i_xml.cpp index 3b7f0f9e2..ee3f39a89 100644 --- a/code/nel/src/misc/i_xml.cpp +++ b/code/nel/src/misc/i_xml.cpp @@ -128,6 +128,10 @@ CIXml::~CIXml () { // Release release (); + +#ifdef USE_LOCALE_ATOF + if (_Locale) _free_locale((_locale_t)_Locale); +#endif } // *************************************************************************** @@ -154,10 +158,6 @@ void CIXml::release () _ErrorString = ""; resetPtrTable(); - -#ifdef USE_LOCALE_ATOF - if (_Locale) _free_locale((_locale_t)_Locale); -#endif } // *************************************************************************** From e0e1953f4144d8b26cb811f6b259159db0328076 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 16:22:56 +0200 Subject: [PATCH 269/282] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/zone_lighter/zone_lighter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp index 1add65a9d..b3c6807c1 100644 --- a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp +++ b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp @@ -699,6 +699,12 @@ int main(int argc, char* argv[]) if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior) continue; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // PS ? if (toLower (CFile::getExtension (name)) == "ps") continue; From 8f7931d6a833acd290ce52548c2b11db6a242fe4 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 16:41:09 +0200 Subject: [PATCH 270/282] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp b/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp index 0010d5179..a6636730f 100644 --- a/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp +++ b/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp @@ -410,6 +410,12 @@ int main(int argc, char* argv[]) if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior) continue; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // Add a .shape at the end ? if (!name.empty()) { From d4b7a3cf8acdff5e756196f563cc13ad9002abfb Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 16:48:51 +0200 Subject: [PATCH 271/282] Crashfix in case pacs_prim are exported into .ig --- code/nel/src/3d/instance_lighter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/src/3d/instance_lighter.cpp b/code/nel/src/3d/instance_lighter.cpp index f754ebb8b..d21f80e4e 100644 --- a/code/nel/src/3d/instance_lighter.cpp +++ b/code/nel/src/3d/instance_lighter.cpp @@ -408,6 +408,12 @@ void CInstanceLighter::light (const CInstanceGroup &igIn, CInstanceGroup &igOut, string name= _Instances[i].Name; bool shapeFound= true; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // Try to find the shape in the UseShapeMap. std::map::const_iterator iteMap= lightDesc.UserShapeMap.find (name); From 9a19f2041b4d5e83a855374a26ff2ff7481a62b6 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 19:37:20 +0200 Subject: [PATCH 272/282] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp b/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp index 4365eab9b..8286a10e6 100644 --- a/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp +++ b/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp @@ -167,6 +167,12 @@ void CIgLighterLib::lightIg(CInstanceLighter &instanceLighter, string name= igIn.getShapeName(i); bool shapeFound= true; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // Try to find the shape in the UseShapeMap. std::map::const_iterator iteMap= lightDesc.UserShapeMap.find (name); From 0e0de8ec52698c7aae3bf829bfb88058e596ae5e Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 19:40:43 +0200 Subject: [PATCH 273/282] Fix shape lightmap optimize --- code/nel/tools/build_gamedata/processes/shape/0_setup.py | 1 + code/nel/tools/build_gamedata/processes/shape/2_build.py | 7 +++++-- code/nel/tools/build_gamedata/processes/shape/3_install.py | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/build_gamedata/processes/shape/0_setup.py b/code/nel/tools/build_gamedata/processes/shape/0_setup.py index 71dfd097e..941d07531 100755 --- a/code/nel/tools/build_gamedata/processes/shape/0_setup.py +++ b/code/nel/tools/build_gamedata/processes/shape/0_setup.py @@ -69,6 +69,7 @@ if BuildShadowSkinEnabled: printLog(log, ">>> Setup build directories <<<") mkPath(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory) mkPath(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory) +mkPath(log, ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory) mkPath(log, ExportBuildDirectory + "/" + ShapeLightmapBuildDirectory) mkPath(log, ExportBuildDirectory + "/" + ShapeLightmap16BitsBuildDirectory) diff --git a/code/nel/tools/build_gamedata/processes/shape/2_build.py b/code/nel/tools/build_gamedata/processes/shape/2_build.py index 48a658378..1a9f668f8 100755 --- a/code/nel/tools/build_gamedata/processes/shape/2_build.py +++ b/code/nel/tools/build_gamedata/processes/shape/2_build.py @@ -77,16 +77,19 @@ else: # copy lightmap_not_optimized to lightmap printLog(log, ">>> Optimize lightmaps <<<") loPathLightmapsOriginal = ExportBuildDirectory + "/" + ShapeLightmapNotOptimizedExportDirectory +loPathShapesOriginal = ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory mkPath(log, loPathLightmapsOriginal) loPathLightmaps = ExportBuildDirectory + "/" + ShapeLightmapBuildDirectory -loPathShapes = ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory +loPathShapes = ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory loPathTags = ExportBuildDirectory + "/" + ShapeTagExportDirectory mkPath(log, loPathLightmaps) mkPath(log, loPathShapes) mkPath(log, loPathTags) -if needUpdateDirByTagLog(log, loPathLightmapsOriginal, ".txt", loPathLightmaps, ".txt") or needUpdateDirNoSubdir(log, loPathLightmapsOriginal, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathShapes, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathTags, loPathLightmaps): +if needUpdateDirByTagLog(log, loPathLightmapsOriginal, ".txt", loPathLightmaps, ".txt") or needUpdateDirNoSubdir(log, loPathLightmapsOriginal, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathShapesOriginal, loPathShapes) or needUpdateDirNoSubdir(log, loPathShapes, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathTags, loPathLightmaps): removeFilesRecursive(log, loPathLightmaps) copyFiles(log, loPathLightmapsOriginal, loPathLightmaps) + removeFilesRecursive(log, loPathShapes) + copyFiles(log, loPathShapesOriginal, loPathShapes) # Optimize lightmaps if any. Additionnaly, output a file indicating which lightmaps are 8 bits # lightmap_optimizer [path_tags] [path_flag8bit] subprocess.call([ LightmapOptimizer, loPathLightmaps, loPathShapes, loPathTags, ExportBuildDirectory + "/" + ShapeLightmapBuildDirectory + "/list_lm_8bit.txt" ]) diff --git a/code/nel/tools/build_gamedata/processes/shape/3_install.py b/code/nel/tools/build_gamedata/processes/shape/3_install.py index cb93a443b..f6265a1a6 100755 --- a/code/nel/tools/build_gamedata/processes/shape/3_install.py +++ b/code/nel/tools/build_gamedata/processes/shape/3_install.py @@ -46,8 +46,8 @@ printLog(log, "") printLog(log, ">>> Install shape <<<") installPath = InstallDirectory + "/" + ShapeInstallDirectory mkPath(log, installPath) -mkPath(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory) -copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory, installPath, ".shape") +mkPath(log, ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory) +copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory, installPath, ".shape") mkPath(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory) copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory, installPath, ".shape") copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory, installPath, ".dds") From 6000fe187f15932076b7c67a73dbfa5126856ce1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 01:50:07 +0200 Subject: [PATCH 274/282] Moved BrowserCtrlPvt to it's own files. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/georges_editor/CMakeLists.txt | 4 +- .../plugins/georges_editor/browser_ctrl.cpp | 164 +----------------- .../georges_editor/browser_ctrl_pvt.cpp | 156 +++++++++++++++++ .../plugins/georges_editor/browser_ctrl_pvt.h | 50 ++++++ 4 files changed, 210 insertions(+), 164 deletions(-) create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index 679af334e..c2d3c1da7 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -16,7 +16,9 @@ SET(OVQT_PLUG_GEORGES_EDITOR_HDR georges_editor_plugin.h georges_filesystem_model.h georges_treeview_dialog.h expandable_headerview.h - browser_ctrl.h) + browser_ctrl.h + browser_ctrl_pvt.h + ) SET(OVQT_PLUG_GEORGES_EDITOR_UIS georges_editor_form.ui georges_dirtree_form.ui diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index f430ff675..8801894e2 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -7,169 +7,7 @@ #include "formitem.h" -QVariant::Type getValueType( const NLGEORGES::UType *typ ) -{ - QVariant::Type t = QVariant::String; - - NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; - if( typ != NULL ) - ttyp = typ->getType(); - - switch( ttyp ) - { - case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; - case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; - case NLGEORGES::UType::Double: t = QVariant::Double; break; - case NLGEORGES::UType::Color: t = QVariant::Color; break; - case NLGEORGES::UType::String: t = QVariant::String; break; - } - - return t; -} - -class BrowserCtrlPvt -{ -public: - BrowserCtrlPvt() - { - mgr = new QtVariantPropertyManager(); - factory = new QtVariantEditorFactory(); - m_currentNode = NULL; - m_rootNode = NULL; - } - - ~BrowserCtrlPvt() - { - delete mgr; - mgr = NULL; - delete factory; - factory = NULL; - m_browser = NULL; - } - - void setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) - { - QString key = elm.Name.c_str(); - QString value = ""; - QVariant::Type t = QVariant::String; - - if( elm.Element != NULL ) - { - t = getValueType( elm.Element->getType() ); - - std::string formName; - elm.Element->getFormName( formName, NULL ); - - std::string v; - m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); - value = v.c_str(); - } - - QtVariantProperty *p = mgr->addProperty( t, key ); - p->setValue( value ); - m_browser->addProperty( p ); - } - - void setupArray( NLGEORGES::UFormElm *node ) - { - NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); - uint size = 0; - arr->getArraySize( size ); - - QString key = QObject::tr( "Array size" ); - QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); - p->setValue( size ); - m_browser->addProperty( p ); - - } - - void setupStruct( NLGEORGES::UFormElm *node ) - { - NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - - for( int i = 0; i < st->Elements.size(); i++ ) - { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) - continue; - - if( elm.Element == NULL ) - { - NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); - if( entry.getArrayFlag() ) - continue; - } - - setupAtom( elm ); - } - } - - void setupNode( NLGEORGES::UFormElm *node ) - { - if( node->isStruct() ) - setupStruct( node ); - else - if( node->isArray() ) - setupArray( node ); - else - return; - - m_currentNode = node; - m_browser->setFactoryForManager( mgr, factory ); - } - - void clear() - { - m_browser->clear(); - m_currentNode = NULL; - } - - void setBrowser( QtTreePropertyBrowser *browser ) - { - m_browser = browser; - } - - void onStructValueChanged( QtProperty *p, const QVariant &value ) - { - std::string k = p->propertyName().toUtf8().constData(); - std::string v = value.toString().toUtf8().constData(); - - bool created = false; - m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); - } - - void onArrayValueChanged( QtProperty *p, const QVariant &value ) - { - NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); - std::string formName; - arr->getFormName( formName, NULL ); - - } - - void onValueChanged( QtProperty *p, const QVariant &value ) - { - if( m_currentNode == NULL ) - return; - - if( m_currentNode->isStruct() ) - onStructValueChanged( p, value ); - else - if( m_currentNode->isArray() ) - onArrayValueChanged( p, value ); - } - - QtVariantPropertyManager* manager() const{ return mgr; } - - void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } - -private: - QtVariantPropertyManager *mgr; - QtVariantEditorFactory *factory; - QtTreePropertyBrowser *m_browser; - - NLGEORGES::UFormElm *m_currentNode; - NLGEORGES::CFormElm *m_rootNode; -}; +#include "browser_ctrl_pvt.h" BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : QObject( browser ) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp new file mode 100644 index 000000000..f49ebc1ba --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -0,0 +1,156 @@ +#include "browser_ctrl_pvt.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +namespace +{ + + QVariant::Type getValueType( const NLGEORGES::UType *typ ) + { + QVariant::Type t = QVariant::String; + + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + switch( ttyp ) + { + case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; + case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; + case NLGEORGES::UType::Double: t = QVariant::Double; break; + case NLGEORGES::UType::Color: t = QVariant::Color; break; + case NLGEORGES::UType::String: t = QVariant::String; break; + } + + return t; + } + +} + + +BrowserCtrlPvt::BrowserCtrlPvt( QObject *parent ) : +QObject( parent ) +{ + mgr = new QtVariantPropertyManager(); + factory = new QtVariantEditorFactory(); + m_currentNode = NULL; + m_rootNode = NULL; +} + +BrowserCtrlPvt::~BrowserCtrlPvt() +{ + delete mgr; + mgr = NULL; + delete factory; + factory = NULL; + m_browser = NULL; +} + +void BrowserCtrlPvt::setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) +{ + QString key = elm.Name.c_str(); + QString value = ""; + QVariant::Type t = QVariant::String; + + if( elm.Element != NULL ) + { + t = getValueType( elm.Element->getType() ); + + std::string formName; + elm.Element->getFormName( formName, NULL ); + + std::string v; + m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); + value = v.c_str(); + } + + QtVariantProperty *p = mgr->addProperty( t, key ); + p->setValue( value ); + m_browser->addProperty( p ); +} + +void BrowserCtrlPvt::setupArray( NLGEORGES::UFormElm *node ) +{ + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); + uint size = 0; + arr->getArraySize( size ); + + QString key = QObject::tr( "Array size" ); + QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); + p->setValue( size ); + m_browser->addProperty( p ); + +} + +void BrowserCtrlPvt::setupStruct( NLGEORGES::UFormElm *node ) +{ + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + + for( int i = 0; i < st->Elements.size(); i++ ) + { + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + + if( elm.Element == NULL ) + { + NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); + if( entry.getArrayFlag() ) + continue; + } + + setupAtom( elm ); + } +} + +void BrowserCtrlPvt::setupNode( NLGEORGES::UFormElm *node ) +{ + if( node->isStruct() ) + setupStruct( node ); + else + if( node->isArray() ) + setupArray( node ); + else + return; + + m_currentNode = node; + m_browser->setFactoryForManager( mgr, factory ); +} + +void BrowserCtrlPvt::clear() +{ + m_browser->clear(); + m_currentNode = NULL; +} + + +void BrowserCtrlPvt::onStructValueChanged( QtProperty *p, const QVariant &value ) +{ + std::string k = p->propertyName().toUtf8().constData(); + std::string v = value.toString().toUtf8().constData(); + + bool created = false; + m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); +} + +void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) +{ + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); + std::string formName; + arr->getFormName( formName, NULL ); +} + +void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) +{ + if( m_currentNode == NULL ) + return; + + if( m_currentNode->isStruct() ) + onStructValueChanged( p, value ); + else + if( m_currentNode->isArray() ) + onArrayValueChanged( p, value ); +} + + diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h new file mode 100644 index 000000000..51d756cfa --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h @@ -0,0 +1,50 @@ +#ifndef BROWSER_CTRL_PVT_H +#define BROWSER_CTRL_PVT_H + +#include + +namespace NLGEORGES +{ + class CFormElm; + class UFormElm; + class CFormElmStruct; +} + +class QtVariantPropertyManager; +class QtVariantEditorFactory; +class QtTreePropertyBrowser; +class QVariant; +class QtProperty; + +class BrowserCtrlPvt : public QObject +{ + Q_OBJECT +public: + BrowserCtrlPvt( QObject *parent = NULL ); + ~BrowserCtrlPvt(); + + void clear(); + void setupNode( NLGEORGES::UFormElm *node ); + void onValueChanged( QtProperty *p, const QVariant &value ); + + QtVariantPropertyManager* manager() const{ return mgr; } + void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } + void setBrowser( QtTreePropertyBrowser *browser ){ m_browser = browser; } + +private: + void setupStruct( NLGEORGES::UFormElm *node ); + void setupArray( NLGEORGES::UFormElm *node ); + void setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ); + + void onStructValueChanged( QtProperty *p, const QVariant &value ); + void onArrayValueChanged( QtProperty *p, const QVariant &value ); + + QtVariantPropertyManager *mgr; + QtVariantEditorFactory *factory; + QtTreePropertyBrowser *m_browser; + + NLGEORGES::UFormElm *m_currentNode; + NLGEORGES::CFormElm *m_rootNode; +}; + +#endif From c9f54c38061a6b2a5b0c4679c58387b1c11805b9 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 18 Aug 2014 07:13:15 +0530 Subject: [PATCH 275/282] Improved documentation with doxygen generated doc --- code/web/private_php/ams/autoload/dblayer.php | 97 ++++++++++++------- .../private_php/ams/autoload/plugincache.php | 26 +++-- .../web/private_php/ams/autoload/rest_api.php | 8 +- .../private_php/ams/autoload/ticket_log.php | 2 +- .../ams/plugins/API_key_management/.info | 2 +- .../public_php/ams/func/activate_plugin.php | 8 +- .../public_php/ams/func/deactivate_plugin.php | 10 +- .../web/public_php/ams/func/delete_plugin.php | 8 +- .../public_php/ams/func/install_plugin.php | 41 ++++++-- .../web/public_php/ams/func/update_plugin.php | 6 +- .../web/public_php/ams/inc/plugins_update.php | 2 +- 11 files changed, 146 insertions(+), 64 deletions(-) diff --git a/code/web/private_php/ams/autoload/dblayer.php b/code/web/private_php/ams/autoload/dblayer.php index 43282789e..7c4c5435c 100644 --- a/code/web/private_php/ams/autoload/dblayer.php +++ b/code/web/private_php/ams/autoload/dblayer.php @@ -3,13 +3,36 @@ * Handles the database connections. It uses PDO to connect to the different databases. It will use the argument of the constructor to setup a connection to the database * with the matching entry in the $cfg global variable. * + * --> First create an object of dblayer --> $db = new DBLayer('short database name used in config') + * + * --> Insert --> $db->insert( $tb_name, $data ) + * $tb_name = table name in which we want to insert data + * $data = array of data that needs to be inserted in format('fieldname' => $value) where fieldname must be a field in that table. + * + * --> select --> $db->select( $tb_name, $data, $where ) + * $tb_name = table name which we want to select + * $data = array of data which is then required in WHERE clause in format array('fieldname'=>$value) fieldname must be a field in that table. + * $where = string in format ('fieldname=:fieldname') where :fieldname takes it's value from $data array. + * + * --> update --> $db->update( $tb_name, $data, $where ) + * $tb_name = table name which we want to update + * $data = array of data which contains the filelds that need to be updated with their values in the format('fieldname' => $value,...) where fieldname must be a field in that table. + * $where = string contains the filename with a value at that field in the format ('fieldname = $value') where fieldname must be a field in that table and $value is value respect to that field. + * + * --> delete --> $db->delete( $tb_name, $data, $where ) + * $tb_name = table name where we want to delete. + * $data = array of data which is then required in WHERE clause in format array('fieldname'=> $value) where fieldname must be a field in that table. + * $where = string in format ('fieldname=:fieldname') where :fieldname takes it's value from $data array. + * + * * @author Daan Janssens, mentored by Matthew Lagoe + * */ class DBLayer { private $PDO; /** - * *< The PDO object, instantiated by the constructor + * The PDO object, instantiated by the constructor */ /** @@ -17,6 +40,7 @@ class DBLayer { * Instantiates the PDO object attribute by connecting to the arguments matching database(the db info is stored in the $cfg global var) * * @param $db String, the name of the databases entry in the $cfg global var. + * @param $dbn String, the name of the databases entry in the $cfg global var if $db referenced to an action(install etc). */ function __construct( $db, $dbn = null ) { @@ -49,10 +73,10 @@ class DBLayer { } /** - * execute a query that doesn't have any parameters + * Execute a query that doesn't have any parameters. * - * @param $query the mysql query - * @return returns a PDOStatement object + * @param $query the mysql query. + * @return returns a PDOStatement object. */ public function executeWithoutParams( $query ) { $statement = $this -> PDO -> prepare( $query ); @@ -61,11 +85,11 @@ class DBLayer { } /** - * execute a query that has parameters + * Execute a query that has parameters. * - * @param $query the mysql query - * @param $params the parameters that are being used by the query - * @return returns a PDOStatement object + * @param $query the mysql query. + * @param $params the parameters that are being used by the query. + * @return returns a PDOStatement object. */ public function execute( $query, $params ) { $statement = $this -> PDO -> prepare( $query ); @@ -74,10 +98,10 @@ class DBLayer { } /** - * execute a query (an insertion query) that has parameters and return the id of it's insertion + * Insert function which returns id of the inserting field. * - * @param $query the mysql query - * @param $params the parameters that are being used by the query + * @param $tb_name table name where we want to insert data. + * @param $data the parameters that are being inserted into table. * @return returns the id of the last inserted element. */ public function executeReturnId( $tb_name, $data ) { @@ -104,12 +128,14 @@ class DBLayer { } /** - * Select function using prepared statement + * Select function using prepared statement. + * For selecting particular fields. * - * @param string $tb_name Table Name to Select - * @param array $data Associative array - * @param string $where where to select - * @return statement object + * @param string $param field to select, can be multiple fields. + * @param string $tb_name Table Name to Select. + * @param array $data array of data to be used in WHERE clause in format('fieldname'=>$value). 'fieldname' must be a field in that table. + * @param string $where where to select. + * @return statement object. */ public function selectWithParameter( $param, $tb_name, $data, $where ) { @@ -129,12 +155,13 @@ class DBLayer { } /** - * Select function using prepared statement + * Select function using prepared statement. + * For selecting all fields in a table. * - * @param string $tb_name Table Name to Select - * @param array $data Associative array - * @param string $where where to select - * @return statement object + * @param string $tb_name Table Name to Select. + * @param array $data array of data to be used with WHERE part in format('fieldname'=>$value,...). 'fieldname' must be a field in that table. + * @param string $where where to select in format('fieldname=:fieldname' AND ...). + * @return statement object. */ public function select( $tb_name, $data , $where ) { @@ -154,12 +181,12 @@ class DBLayer { } /** - * Update function with prepared statement + * Update function with prepared statement. * - * @param string $tb_name name of the table - * @param array $data associative array with values - * @param string $where where part - * @throws Exception error in updating + * @param string $tb_name name of the table on which operation to be performed. + * @param array $data array of data in format('fieldname' => $value,...).Here, only those fields must be stored which needs to be updated. + * @param string $where where part in format ('fieldname'= $value AND ...). 'fieldname' must be a field in that table. + * @throws Exception error in updating. */ public function update( $tb_name, $data, $where ) { @@ -190,10 +217,11 @@ class DBLayer { } /** - * insert function using prepared statements + * insert function using prepared statements. * - * @param string $tb_name Name of the table to insert in - * @param array $data Associative array of data to insert + * @param string $tb_name Name of the table on which operation to be performed. + * @param array $data array of data to insert in format('fieldname' => $value,....). 'fieldname' must be a field in that table. + * @throws error in inserting. */ public function insert( $tb_name, $data ) { @@ -216,16 +244,17 @@ class DBLayer { { // for rolling back the changes during transaction $this -> PDO -> rollBack(); - throw new Exception( "error in inseting" ); + throw new Exception( "error in inserting" ); } } /** - * Delete database entery using prepared statement + * Delete database entery using prepared statement. * - * @param string $tb_name - * @param string $where - * @throws error in deleting + * @param string $tb_name table name on which operations to be performed. + * @param $data array with values in the format('fieldname'=> $value,...). 'fieldname' must be a field in that table. + * @param string $where condition based on $data array in the format('fieldname=:fieldname' AND ...). + * @throws error in deleting. */ public function delete( $tb_name, $data, $where ) { diff --git a/code/web/private_php/ams/autoload/plugincache.php b/code/web/private_php/ams/autoload/plugincache.php index c90665bc1..8ff258513 100644 --- a/code/web/private_php/ams/autoload/plugincache.php +++ b/code/web/private_php/ams/autoload/plugincache.php @@ -2,7 +2,7 @@ /** * API for loading and interacting with plugins - * contains getters and setters + * contains getters and setters. * * @author shubham meena mentored by Matthew Lagoe */ @@ -14,11 +14,11 @@ class Plugincache { private $plugin_status; private $plugin_info = array(); private $update_info = array(); + /** * A constructor. * Empty constructor */ - public function __construct() { } @@ -207,10 +207,12 @@ class Plugincache { } /** - * returns plugin information with respect to the id + * Returns plugin information with respect to the id. * - * @param id $ plugin id - * @return field info for the plugin + * @param $id plugin id. + * @param $fieldName string plugin field to return + * + * @return info field from the db. */ public static function pluginInfoUsingId( $id, $fieldName ) { @@ -221,9 +223,9 @@ class Plugincache { } /** - * function provides list of active plugins + * Function provides list of active plugins * - * @return $ac_plugins list of active plugins + * @return list of active plugins */ public static function activePlugins() { @@ -235,9 +237,15 @@ class Plugincache { /** * function to load hooks for the active plugins - * and return the contents in the hooks in an array + * and return the contents get from them. + * + * -->Get the list of active plugins then call the global + * hooks exists in the plugins hook file ($pluginName.php). + * -->Collect the contents from the hooks and associate within + * array with key referenced plugin name. + * -->return the content to use with smarty template loader * - * @return $content content available in hooks + * @return $content content get from hooks */ public static function loadHooks() { diff --git a/code/web/private_php/ams/autoload/rest_api.php b/code/web/private_php/ams/autoload/rest_api.php index 74281c6f6..e35586042 100644 --- a/code/web/private_php/ams/autoload/rest_api.php +++ b/code/web/private_php/ams/autoload/rest_api.php @@ -5,7 +5,7 @@ * * Request for the given url using cURL * and send the AccessToken for authentication - * to make public access for the user + * to make public access for the user. * * @author Shubham Meena, mentored by Matthew Lagoe */ @@ -13,12 +13,14 @@ class Rest_Api { /** - * Makes a request using cURL with authentication headers and returns the response. + * Makes a request using cURL with authentication headers , data to post and returns the response. * * @param $url where request is to be sent * @param $applicationKey user generated key * @param $host host for the website - * @return URL response. + * @param $data data to send using POST request + * + * @return $response URL response. */ public function request( $url , $applicationKey, $host , $data ) { diff --git a/code/web/private_php/ams/autoload/ticket_log.php b/code/web/private_php/ams/autoload/ticket_log.php index 6693fe3ce..f83d4b29e 100644 --- a/code/web/private_php/ams/autoload/ticket_log.php +++ b/code/web/private_php/ams/autoload/ticket_log.php @@ -143,7 +143,7 @@ class Ticket_Log{ /** * loads the object's attributes. * loads the object's attributes by giving a ticket_log entries ID (TLogId). - * @param id the id of the ticket_log entry that should be loaded + * @param $id the id of the ticket_log entry that should be loaded */ public function load_With_TLogId( $id) { $dbl = new DBLayer("lib"); diff --git a/code/web/private_php/ams/plugins/API_key_management/.info b/code/web/private_php/ams/plugins/API_key_management/.info index b185a31db..1da25516e 100644 --- a/code/web/private_php/ams/plugins/API_key_management/.info +++ b/code/web/private_php/ams/plugins/API_key_management/.info @@ -1,7 +1,7 @@ PluginName = API Key Management Description = Provides public access to the API's by generating access tokens. Version = 1.0.0 -Type = automatic +Type = Manual TemplatePath = ../../../ams_lib/plugins/API_key_management/templates/index.tpl diff --git a/code/web/public_php/ams/func/activate_plugin.php b/code/web/public_php/ams/func/activate_plugin.php index 930ed15f1..0a331f284 100644 --- a/code/web/public_php/ams/func/activate_plugin.php +++ b/code/web/public_php/ams/func/activate_plugin.php @@ -1,6 +1,9 @@ update( "plugins", array( 'Status' => '1' ), "Id = $id" ); if ( $result ) { + // if result is successfull it redirects and shows success message header( "Location: index.php?page=plugins&result=3" ); exit; } else { + //if result is unsuccessfull it redirects and throws error header( "Location: index.php?page=plugins&result=4" ); exit; } } else { + //if $_GET variable is not set it redirects and shows error header( "Location: index.php?page=plugins&result=4" ); exit; } diff --git a/code/web/public_php/ams/func/deactivate_plugin.php b/code/web/public_php/ams/func/deactivate_plugin.php index a4b6120b1..91986bb50 100644 --- a/code/web/public_php/ams/func/deactivate_plugin.php +++ b/code/web/public_php/ams/func/deactivate_plugin.php @@ -1,6 +1,9 @@ update( "plugins", array( 'Status' => '0' ), "Id = $id" ); if ( $result ) - { + { + // if result is successfull it redirects and shows success message header( "Location: index.php?page=plugins&result=5" ); exit; } else { + // if result is unsuccessfull it redirects and shows success message header( "Location: index.php?page=plugins&result=6" ); exit; @@ -30,6 +35,7 @@ function deactivate_plugin() { } else { + //if $_GET variable is not set it redirects and shows error header( "Location: index.php?page=plugins&result=6" ); exit; } diff --git a/code/web/public_php/ams/func/delete_plugin.php b/code/web/public_php/ams/func/delete_plugin.php index f3dc0311a..d85ed34b9 100644 --- a/code/web/public_php/ams/func/delete_plugin.php +++ b/code/web/public_php/ams/func/delete_plugin.php @@ -1,8 +1,9 @@ delete( 'plugins', array( 'id' => $id ), "Id=:id" ); + //if result successfull redirect and show success message header( "Location: index.php?page=plugins&result=2" ); exit; } else { + // if result unsuccessfull redirect and show error message header( "Location: index.php?page=plugins&result=0" ); exit; } @@ -40,6 +43,7 @@ function delete_plugin() { } else { + // if result unsuccessfull redirect and show error message header( "Location: index.php?page=plugins&result=0" ); exit; } diff --git a/code/web/public_php/ams/func/install_plugin.php b/code/web/public_php/ams/func/install_plugin.php index 052d4f14b..1ad7154d2 100644 --- a/code/web/public_php/ams/func/install_plugin.php +++ b/code/web/public_php/ams/func/install_plugin.php @@ -1,10 +1,32 @@ Check if the file type is .zip. + * --> Extract it to a temp folder. + * --> Check for the .info file. If not exists throw error + * --> Extract the information from the .info file. + * --> Check for the plugin name already exists or not. + * --> if Plugin Name exists it compare the version of .info and version of plugin stored in db. + * --> if same throw error and if different it checks for UpdateInfo field in .info file. + * --> if UpdateInfo not found throw error. + * --> if UpdateInfo found add the update to the ryzom_ams_lib.updates table. + * --> if it's not an update and plugin with same name already exists throw error. + * --> if plugin with same name not present provide option to install plugin + * + * @author Shubham Meena, mentored by Matthew Lagoe + * + */ + + /** - * This function is used in installing plugins - * It performs validation check for the compressed plugin - * then extract in plugin folder to get the info + * This function is used in installing plugins or adding updates + * for previously installed plugins. * - * @author Shubham Meena, mentored by Matthew Lagoe */ function install_plugin() { @@ -165,13 +187,14 @@ function zipExtraction( $target_path, $destination ) * PluginName = Name of the plugin * Version = version of the plugin * Type = type of the plugin + * TemplatePath = path to the template * Description = Description of the plugin ,it's functionality * ----------------------------------------------------------- * * reads only files with name .info * * @param $fileName file to read - * @param $targetPath path to the folder containing .info file + * @param $target_path path to the folder containing .info file * @return array containing above information in array(value => key) */ function readPluginFile( $fileName, $target_path ) @@ -190,8 +213,8 @@ function readPluginFile( $fileName, $target_path ) /** * function to check for updates or * if the same plugin already exists - * also, if the update founds ,check for the update info in the .info file. - * Update is saved in the temp direcotry with pluginName_version.zip + * also, if the update founds ,check for the UpdateInfo in the .info file. + * Update is saved in the temp directory with pluginName_version.zip * * @param $fileName file which is uploaded in .zip extension * @param $findPath where we have to look for the installed plugins @@ -286,8 +309,8 @@ function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) * * @param $pluginId id of the plugin for which update is available * @param $updatePath path of the new update - * @return boolean if update for a plugin already exists or - * if update of same version is uploading + * @return boolean True if update already exists else False + * */ function PluginUpdateExists( $pluginId, $updatePath ) { diff --git a/code/web/public_php/ams/func/update_plugin.php b/code/web/public_php/ams/func/update_plugin.php index 1420572b1..cacc5f119 100644 --- a/code/web/public_php/ams/func/update_plugin.php +++ b/code/web/public_php/ams/func/update_plugin.php @@ -1,6 +1,9 @@ executeWithoutParams( "SELECT * FROM plugins INNER JOIN updates ON plugins.Id=updates.PluginId Where plugins.Id=$id" ); @@ -26,6 +29,7 @@ function update_plugin() { // deleting the previous update $db -> delete( "updates", array( 'id' => $row['s.no'] ), "s.no=:id" ); + // if update is installed succesffully redirect to show success message header( "Location: index.php?page=plugins&result=8" ); exit; diff --git a/code/web/public_php/ams/inc/plugins_update.php b/code/web/public_php/ams/inc/plugins_update.php index 89d547860..e08869f98 100644 --- a/code/web/public_php/ams/inc/plugins_update.php +++ b/code/web/public_php/ams/inc/plugins_update.php @@ -1,7 +1,7 @@ Date: Mon, 18 Aug 2014 18:03:48 +0200 Subject: [PATCH 276/282] Array resize. --HG-- branch : gsoc2014-dfighter --- .../plugins/georges_editor/browser_ctrl.cpp | 7 +++ .../src/plugins/georges_editor/browser_ctrl.h | 4 ++ .../georges_editor/browser_ctrl_pvt.cpp | 46 +++++++++++++++++++ .../plugins/georges_editor/browser_ctrl_pvt.h | 3 ++ .../src/plugins/georges_editor/formitem.cpp | 25 +++++++++- .../src/plugins/georges_editor/formitem.h | 4 ++ .../georges_treeview_dialog.cpp | 22 +++++++++ .../georges_editor/georges_treeview_dialog.h | 4 ++ .../georges_editor/georgesform_model.cpp | 40 ++++++++++++++++ .../georges_editor/georgesform_model.h | 3 ++ 10 files changed, 157 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 8801894e2..d881f42a2 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -14,6 +14,8 @@ QObject( browser ) { m_pvt = new BrowserCtrlPvt(); m_pvt->setBrowser( browser ); + + connect( m_pvt, SIGNAL( arrayResized( const QString&, int ) ), this, SLOT( onArrayResized( const QString&, int ) ) ); } BrowserCtrl::~BrowserCtrl() @@ -50,6 +52,11 @@ void BrowserCtrl::onValueChanged( QtProperty *p, const QVariant &value ) m_pvt->onValueChanged( p, value ); } +void BrowserCtrl::onArrayResized( const QString &name, int size ) +{ + Q_EMIT arrayResized( name, size ); +} + void BrowserCtrl::enableMgrConnections() { QtVariantPropertyManager *mgr = m_pvt->manager(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h index da14e14c9..6014b0419 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -26,8 +26,12 @@ public: public Q_SLOTS: void clicked( const QModelIndex &idx ); +Q_SIGNALS: + void arrayResized( const QString &name, int size ); + private Q_SLOTS: void onValueChanged( QtProperty *p, const QVariant &value ); + void onArrayResized( const QString &name, int size ); private: void enableMgrConnections(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp index f49ebc1ba..52eaabfa6 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -139,6 +139,52 @@ void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); std::string formName; arr->getFormName( formName, NULL ); + + int newSize = value.toInt(); + int oldSize = arr->Elements.size(); + + if( newSize == oldSize ) + return; + + if( newSize < oldSize ) + { + for( int i = newSize; i < oldSize; i++ ) + { + delete arr->Elements[ i ].Element; + } + + arr->Elements.resize( newSize ); + } + else + { + arr->Elements.resize( newSize ); + + + const NLGEORGES::CFormDfn *parentDfn; + const NLGEORGES::CFormDfn *nodeDfn; + uint indexDfn; + const NLGEORGES::CType *type; + NLGEORGES::UFormDfn::TEntryType entryType; + NLGEORGES::CFormElm *node; + bool created; + bool isArray; + + QString idx; + + for( int i = oldSize; i < newSize; i++ ) + { + idx.clear(); + idx += "["; + idx += QString::number( i ); + idx += "]"; + + bool b; + b = arr->createNodeByName( idx.toUtf8().constData(), &parentDfn, indexDfn, &nodeDfn, &type, &node, entryType, isArray, created ); + } + } + + QString name = formName.c_str(); + Q_EMIT arrayResized( name, newSize ); } void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h index 51d756cfa..5bf93da4a 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h @@ -31,6 +31,9 @@ public: void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } void setBrowser( QtTreePropertyBrowser *browser ){ m_browser = browser; } +Q_SIGNALS: + void arrayResized( const QString &name, int size ); + private: void setupStruct( NLGEORGES::UFormElm *node ); void setupArray( NLGEORGES::UFormElm *node ); diff --git a/code/studio/src/plugins/georges_editor/formitem.cpp b/code/studio/src/plugins/georges_editor/formitem.cpp index 426009ca3..1ca2ecbe1 100644 --- a/code/studio/src/plugins/georges_editor/formitem.cpp +++ b/code/studio/src/plugins/georges_editor/formitem.cpp @@ -38,7 +38,7 @@ namespace GeorgesQt CFormItem::~CFormItem() { - qDeleteAll(childItems); + clearChildren(); } void CFormItem::appendChild(CFormItem *item) @@ -214,6 +214,29 @@ namespace GeorgesQt return QIcon(); } + CFormItem* CFormItem::findItem( const QString &formName ) + { + CFormItem *item = NULL; + + if( _FormName.c_str() == formName ) + return this; + + for( int i = 0; i < childItems.count(); i++ ) + { + item = childItems[ i ]->findItem( formName ); + if( item != NULL ) + return item; + } + + return item; + } + + void CFormItem::clearChildren() + { + qDeleteAll( childItems ); + childItems.clear(); + } + CFormItem *CFormItem::add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr) { CFormItem *newNode = new CFormItem(); diff --git a/code/studio/src/plugins/georges_editor/formitem.h b/code/studio/src/plugins/georges_editor/formitem.h index cc2dafece..d29dfce0c 100644 --- a/code/studio/src/plugins/georges_editor/formitem.h +++ b/code/studio/src/plugins/georges_editor/formitem.h @@ -72,6 +72,10 @@ namespace GeorgesQt QIcon getItemImage(CFormItem *rootItem); + CFormItem* findItem( const QString &formName ); + + void clearChildren(); + private: QList childItems; QList itemData; diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp index a8e7e7451..838fa8cc2 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -74,6 +74,7 @@ namespace GeorgesQt m_ui.treeViewTabWidget->setTabEnabled (2,false); m_form = 0; + m_model = NULL; m_ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -87,11 +88,13 @@ namespace GeorgesQt m_browserCtrl, SLOT(clicked(const QModelIndex&))); connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); + connect(m_browserCtrl, SIGNAL(arrayResized(const QString&,int)), this, SLOT(onArrayResized(const QString&,int))); } CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog() { m_browserCtrl = NULL; + m_model = NULL; delete m_form; qDebug() << "DTOR"; @@ -265,6 +268,8 @@ namespace GeorgesQt setWindowTitle(loadedForm); // //Modules::mainWin().getTabBar(); + + m_model = model; } } @@ -446,6 +451,23 @@ namespace GeorgesQt //} } + void CGeorgesTreeViewDialog::onArrayResized( const QString &name, int size ) + { + QModelIndex current = m_ui.treeView->currentIndex(); + QModelIndex parent = current.parent(); + int r = current.row(); + int c = current.column(); + + m_model->arrayResized( name, size ); + m_ui.treeView->reset(); + m_ui.treeView->expandAll(); + + QModelIndex idx = m_model->index( r, c, parent ); + if( !idx.isValid() ) + return; + m_ui.treeView->setCurrentIndex( idx ); + } + void CGeorgesTreeViewDialog::closeEvent(QCloseEvent *event) { Q_EMIT closing(); diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h index b2171cf03..7b40fc3ef 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h @@ -47,6 +47,7 @@ namespace GeorgesQt { class CGeorges; + class CGeorgesFormModel; class CGeorgesTreeViewDialog: public QDockWidget { @@ -102,6 +103,8 @@ namespace GeorgesQt void filterRows(); void headerClicked(int); + void onArrayResized( const QString &name, int size ); + private: Ui::CGeorgesTreeViewDialog m_ui; ExpandableHeaderView *m_header; @@ -116,6 +119,7 @@ namespace GeorgesQt bool m_modified; BrowserCtrl *m_browserCtrl; + CGeorgesFormModel *m_model; }; /* CGeorgesTreeViewDialog */ diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_model.cpp index 2cc5c1280..90eaaaacd 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/studio/src/plugins/georges_editor/georgesform_model.cpp @@ -460,6 +460,46 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, } +void CGeorgesFormModel::arrayResized( const QString &name, int size ) +{ + CFormItem *item = m_rootItem->findItem( name ); + if( item == NULL ) + return; + + NLGEORGES::UFormElm *elm = NULL; + + item->form()->getRootNode().getNodeByName( &elm, name.toUtf8().constData() ); + + if( elm == NULL ) + return; + + NLGEORGES::CFormElmArray *celm = dynamic_cast< NLGEORGES::CFormElmArray* >( elm ); + if( celm == NULL ) + return; + + item->clearChildren(); + + for( int i = 0; i < celm->Elements.size(); i++ ) + { + NLGEORGES::CFormElmArray::CElement &e = celm->Elements[ i ]; + + QString formName = name; + formName += '['; + formName += QString::number( i ); + formName += ']'; + + QString n; + if( e.Name.empty() ) + n = "#" + QString::number( i ); + else + n = e.Name.c_str(); + + item->add( CFormItem::Form, n.toUtf8().constData(), i, formName.toUtf8().constData(), 0, item->form() ); + } + +} + + /******************************************************************************/ diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.h b/code/studio/src/plugins/georges_editor/georgesform_model.h index 07589b63c..4ca91398b 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.h +++ b/code/studio/src/plugins/georges_editor/georgesform_model.h @@ -74,6 +74,9 @@ namespace GeorgesQt { Q_EMIT dataChanged(index, index); } + + void arrayResized( const QString &name, int size ); + private: void setupModelData(); void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent); From 0b44c8a7a0c7025e35a7e86d8ee840b13d98d054 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 19:49:32 +0200 Subject: [PATCH 277/282] Save changes. --HG-- branch : gsoc2014-dfighter --- .../studio/src/plugins/georges_editor/browser_ctrl.cpp | 6 ++++++ code/studio/src/plugins/georges_editor/browser_ctrl.h | 2 ++ .../src/plugins/georges_editor/browser_ctrl_pvt.cpp | 3 +++ .../src/plugins/georges_editor/browser_ctrl_pvt.h | 1 + .../src/plugins/georges_editor/georges_editor_form.cpp | 10 ++++++++-- .../plugins/georges_editor/georges_treeview_dialog.cpp | 2 ++ 6 files changed, 22 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index d881f42a2..aa431b45c 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -16,6 +16,7 @@ QObject( browser ) m_pvt->setBrowser( browser ); connect( m_pvt, SIGNAL( arrayResized( const QString&, int ) ), this, SLOT( onArrayResized( const QString&, int ) ) ); + connect( m_pvt, SIGNAL( modified() ), this, SLOT( onModified() ) ); } BrowserCtrl::~BrowserCtrl() @@ -57,6 +58,11 @@ void BrowserCtrl::onArrayResized( const QString &name, int size ) Q_EMIT arrayResized( name, size ); } +void BrowserCtrl::onModified() +{ + Q_EMIT modified(); +} + void BrowserCtrl::enableMgrConnections() { QtVariantPropertyManager *mgr = m_pvt->manager(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h index 6014b0419..9c70f51bb 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -28,10 +28,12 @@ public Q_SLOTS: Q_SIGNALS: void arrayResized( const QString &name, int size ); + void modified(); private Q_SLOTS: void onValueChanged( QtProperty *p, const QVariant &value ); void onArrayResized( const QString &name, int size ); + void onModified(); private: void enableMgrConnections(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp index 52eaabfa6..0e22765da 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -132,6 +132,8 @@ void BrowserCtrlPvt::onStructValueChanged( QtProperty *p, const QVariant &value bool created = false; m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); + + Q_EMIT modified(); } void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) @@ -185,6 +187,7 @@ void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) QString name = formName.c_str(); Q_EMIT arrayResized( name, newSize ); + Q_EMIT modified(); } void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h index 5bf93da4a..0d0363c1f 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h @@ -33,6 +33,7 @@ public: Q_SIGNALS: void arrayResized( const QString &name, int size ); + void modified(); private: void setupStruct( NLGEORGES::UFormElm *node ); diff --git a/code/studio/src/plugins/georges_editor/georges_editor_form.cpp b/code/studio/src/plugins/georges_editor/georges_editor_form.cpp index a0240eef8..dc0ca409d 100644 --- a/code/studio/src/plugins/georges_editor/georges_editor_form.cpp +++ b/code/studio/src/plugins/georges_editor/georges_editor_form.cpp @@ -271,10 +271,16 @@ namespace GeorgesQt void GeorgesEditorForm::setModified () { qDebug() << "setModified"; + bool saveEnabled = false; if (m_lastActiveDock) - m_saveAction->setEnabled(m_lastActiveDock->isModified()); + saveEnabled = m_lastActiveDock->isModified(); else - m_saveAction->setEnabled(false); + saveEnabled = false; + + m_saveAction->setEnabled( saveEnabled ); + + QAction *saveAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE ); + saveAction->setEnabled( saveEnabled ); } void GeorgesEditorForm::focusChanged ( QWidget * old, QWidget * now ) diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp index 838fa8cc2..3ecc73045 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -89,6 +89,8 @@ namespace GeorgesQt connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); connect(m_browserCtrl, SIGNAL(arrayResized(const QString&,int)), this, SLOT(onArrayResized(const QString&,int))); + + connect(m_browserCtrl, SIGNAL(modified()), this, SLOT(modifiedFile())); } CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog() From 683a0adc6081fea5289c64598bbf76942f8c8b7c Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 18 Aug 2014 20:23:27 +0200 Subject: [PATCH 278/282] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp b/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp index 7d958d81c..b109c2db2 100644 --- a/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp +++ b/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp @@ -607,11 +607,15 @@ static void computeIGBBox(const NL3D::CInstanceGroup &ig, CLightingBBox &result, std::string toLoad = it->Name; if (getExt(toLoad).empty()) toLoad += ".shape"; shapePathName = NLMISC::CPath::lookup(toLoad, false, false); - + if (shapePathName.empty()) { nlwarning("Unable to find shape '%s'", it->Name.c_str()); } + else if (toLower (CFile::getExtension (shapePathName)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", shapePathName.c_str()); + } else { CIFile shapeInputFile; From 8fab3ccce1f5682f4baefea81bc573bc73d923f2 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 19 Aug 2014 15:37:31 +0200 Subject: [PATCH 279/282] EOL --- code/studio/src/settings_dialog.cpp | 472 ++++++++++++++-------------- code/studio/src/settings_dialog.h | 124 ++++---- code/studio/src/splash_screen.cpp | 218 ++++++------- code/studio/src/splash_screen.h | 120 +++---- 4 files changed, 467 insertions(+), 467 deletions(-) diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp index 6824b0f56..78773a666 100644 --- a/code/studio/src/settings_dialog.cpp +++ b/code/studio/src/settings_dialog.cpp @@ -1,236 +1,236 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "settings_dialog.h" -#include -#include -#include - -int findListItem( QListWidget *l, const QString &s ) -{ - for( int i = 0; i < l->count(); i++ ) - { - QListWidgetItem *item = l->item( i ); - if( item->text() == s ) - return i; - } - - return -1; -} - -SettingsDialog::SettingsDialog( QDialog *parent ) : -QDialog( parent ) -{ - setupUi( this ); - setupConnections(); - settings = NULL; -} - -SettingsDialog::~SettingsDialog() -{ -} - -void SettingsDialog::load() -{ - pluginsLE->setText( settings->value( "PluginPath" ).toString() ); - - settings->beginGroup( "DataPath" ); - - sheetsLE->setText( settings->value( "LevelDesignPath" ).toString() ); - assetsLE->setText( settings->value( "AssetsPath" ).toString() ); - primitivesLE->setText( settings->value( "PrimitivesPath" ).toString() ); - ligoLE->setText( settings->value( "LigoConfigFile" ).toString() ); - - QStringList l = settings->value( "SearchPaths" ).toStringList(); - { - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - QString p = itr.next(); - if( findListItem( searchLW, p ) == -1 ) - searchLW->addItem( p ); - } - } - - l.clear(); - - l = settings->value( "RecursiveSearchPathes" ).toStringList(); - { - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - QString p = itr.next(); - if( findListItem( recursiveLW, p ) == -1 ) - recursiveLW->addItem( p ); - } - } - - settings->endGroup(); -} - -void SettingsDialog::saveSearchPaths() -{ - QStringList l; - for( int i = 0; i < searchLW->count(); i++ ) - { - l.push_back( searchLW->item( i )->text() ); - } - - settings->setValue( "SearchPaths", l ); -} - -void SettingsDialog::saveRecursivePaths() -{ - QStringList l; - for( int i = 0; i < recursiveLW->count(); i++ ) - { - l.push_back( recursiveLW->item( i )->text() ); - } - - settings->setValue( "RecursiveSearchPathes", l ); -} - -void SettingsDialog::save() -{ - settings->setValue( "PluginPath", pluginsLE->text() ); - - settings->beginGroup( "DataPath" ); - - settings->setValue( "LevelDesignPath", sheetsLE->text() ); - settings->setValue( "AssetsPath", assetsLE->text() ); - settings->setValue( "PrimitivesPath", primitivesLE->text() ); - settings->setValue( "LigoConfigFile", ligoLE->text() ); - - saveSearchPaths(); - saveRecursivePaths(); - - settings->endGroup(); - - settings->sync(); -} - -void SettingsDialog::accept() -{ - save(); - QDialog::accept(); -} - -void SettingsDialog::reject() -{ - QDialog::reject(); -} - -void SettingsDialog::onOKClicked() -{ - accept(); -} - -void SettingsDialog::onCancelClicked() -{ - reject(); -} - -void SettingsDialog::onPluginBClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "Plugins directory" ), "" ); - pluginsLE->setText( p ); -} - -void SettingsDialog::onSheetsBClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "Sheets directory" ), "" ); - sheetsLE->setText( p ); -} - -void SettingsDialog::onAssetsBClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "Assets directory" ), "" ); - assetsLE->setText( p ); -} - -void SettingsDialog::onPrimitivesBClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "Primitives directory" ), "" ); - primitivesLE->setText( p ); -} - -void SettingsDialog::onLigoBClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "LIGO directory" ), "" ); - ligoLE->setText( p ); -} - -void SettingsDialog::onPathAddClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "Search path" ), "" ); - if( p.isEmpty() ) - return; - - if( findListItem( searchLW, p ) != -1 ) - return; - - searchLW->addItem( p ); -} - -void SettingsDialog::onPathRemoveClicked() -{ - QListWidgetItem *i = searchLW->currentItem(); - if( i == NULL ) - return; - - delete i; -} - -void SettingsDialog::onRecursiveAddClicked() -{ - QString p = QFileDialog::getExistingDirectory( this, tr( "Recursive search path" ), "" ); - if( p.isEmpty() ) - return; - - if( findListItem( recursiveLW, p ) != -1 ) - return; - - recursiveLW->addItem( p ); -} - -void SettingsDialog::onRecursiveRemoveClicked() -{ - QListWidgetItem *i = recursiveLW->currentItem(); - if( i == NULL ) - return; - - delete i; -} - - -void SettingsDialog::setupConnections() -{ - connect( bb, SIGNAL( accepted() ), this, SLOT( onOKClicked() ) ); - connect( bb, SIGNAL( rejected() ), this, SLOT( onCancelClicked() ) ); - - connect( pluginsB, SIGNAL( clicked( bool ) ), this, SLOT( onPluginBClicked() ) ); - connect( sheetsB, SIGNAL( clicked( bool ) ), this, SLOT( onSheetsBClicked() ) ); - connect( assetsB, SIGNAL( clicked( bool ) ), this, SLOT( onAssetsBClicked() ) ); - connect( primitivesB, SIGNAL( clicked( bool ) ), this, SLOT( onPrimitivesBClicked() ) ); - connect( ligoB, SIGNAL( clicked( bool ) ), this, SLOT( onLigoBClicked() ) ); - - connect( pathAddB, SIGNAL( clicked( bool ) ), this, SLOT( onPathAddClicked() ) ); - connect( pathRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onPathRemoveClicked() ) ); - connect( recAddB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveAddClicked() ) ); - connect( recRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveRemoveClicked() ) ); -} - +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "settings_dialog.h" +#include +#include +#include + +int findListItem( QListWidget *l, const QString &s ) +{ + for( int i = 0; i < l->count(); i++ ) + { + QListWidgetItem *item = l->item( i ); + if( item->text() == s ) + return i; + } + + return -1; +} + +SettingsDialog::SettingsDialog( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); + settings = NULL; +} + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::load() +{ + pluginsLE->setText( settings->value( "PluginPath" ).toString() ); + + settings->beginGroup( "DataPath" ); + + sheetsLE->setText( settings->value( "LevelDesignPath" ).toString() ); + assetsLE->setText( settings->value( "AssetsPath" ).toString() ); + primitivesLE->setText( settings->value( "PrimitivesPath" ).toString() ); + ligoLE->setText( settings->value( "LigoConfigFile" ).toString() ); + + QStringList l = settings->value( "SearchPaths" ).toStringList(); + { + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + QString p = itr.next(); + if( findListItem( searchLW, p ) == -1 ) + searchLW->addItem( p ); + } + } + + l.clear(); + + l = settings->value( "RecursiveSearchPathes" ).toStringList(); + { + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + QString p = itr.next(); + if( findListItem( recursiveLW, p ) == -1 ) + recursiveLW->addItem( p ); + } + } + + settings->endGroup(); +} + +void SettingsDialog::saveSearchPaths() +{ + QStringList l; + for( int i = 0; i < searchLW->count(); i++ ) + { + l.push_back( searchLW->item( i )->text() ); + } + + settings->setValue( "SearchPaths", l ); +} + +void SettingsDialog::saveRecursivePaths() +{ + QStringList l; + for( int i = 0; i < recursiveLW->count(); i++ ) + { + l.push_back( recursiveLW->item( i )->text() ); + } + + settings->setValue( "RecursiveSearchPathes", l ); +} + +void SettingsDialog::save() +{ + settings->setValue( "PluginPath", pluginsLE->text() ); + + settings->beginGroup( "DataPath" ); + + settings->setValue( "LevelDesignPath", sheetsLE->text() ); + settings->setValue( "AssetsPath", assetsLE->text() ); + settings->setValue( "PrimitivesPath", primitivesLE->text() ); + settings->setValue( "LigoConfigFile", ligoLE->text() ); + + saveSearchPaths(); + saveRecursivePaths(); + + settings->endGroup(); + + settings->sync(); +} + +void SettingsDialog::accept() +{ + save(); + QDialog::accept(); +} + +void SettingsDialog::reject() +{ + QDialog::reject(); +} + +void SettingsDialog::onOKClicked() +{ + accept(); +} + +void SettingsDialog::onCancelClicked() +{ + reject(); +} + +void SettingsDialog::onPluginBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Plugins directory" ), "" ); + pluginsLE->setText( p ); +} + +void SettingsDialog::onSheetsBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Sheets directory" ), "" ); + sheetsLE->setText( p ); +} + +void SettingsDialog::onAssetsBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Assets directory" ), "" ); + assetsLE->setText( p ); +} + +void SettingsDialog::onPrimitivesBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Primitives directory" ), "" ); + primitivesLE->setText( p ); +} + +void SettingsDialog::onLigoBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "LIGO directory" ), "" ); + ligoLE->setText( p ); +} + +void SettingsDialog::onPathAddClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Search path" ), "" ); + if( p.isEmpty() ) + return; + + if( findListItem( searchLW, p ) != -1 ) + return; + + searchLW->addItem( p ); +} + +void SettingsDialog::onPathRemoveClicked() +{ + QListWidgetItem *i = searchLW->currentItem(); + if( i == NULL ) + return; + + delete i; +} + +void SettingsDialog::onRecursiveAddClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Recursive search path" ), "" ); + if( p.isEmpty() ) + return; + + if( findListItem( recursiveLW, p ) != -1 ) + return; + + recursiveLW->addItem( p ); +} + +void SettingsDialog::onRecursiveRemoveClicked() +{ + QListWidgetItem *i = recursiveLW->currentItem(); + if( i == NULL ) + return; + + delete i; +} + + +void SettingsDialog::setupConnections() +{ + connect( bb, SIGNAL( accepted() ), this, SLOT( onOKClicked() ) ); + connect( bb, SIGNAL( rejected() ), this, SLOT( onCancelClicked() ) ); + + connect( pluginsB, SIGNAL( clicked( bool ) ), this, SLOT( onPluginBClicked() ) ); + connect( sheetsB, SIGNAL( clicked( bool ) ), this, SLOT( onSheetsBClicked() ) ); + connect( assetsB, SIGNAL( clicked( bool ) ), this, SLOT( onAssetsBClicked() ) ); + connect( primitivesB, SIGNAL( clicked( bool ) ), this, SLOT( onPrimitivesBClicked() ) ); + connect( ligoB, SIGNAL( clicked( bool ) ), this, SLOT( onLigoBClicked() ) ); + + connect( pathAddB, SIGNAL( clicked( bool ) ), this, SLOT( onPathAddClicked() ) ); + connect( pathRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onPathRemoveClicked() ) ); + connect( recAddB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveAddClicked() ) ); + connect( recRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveRemoveClicked() ) ); +} + diff --git a/code/studio/src/settings_dialog.h b/code/studio/src/settings_dialog.h index c6e7cc93a..173ba37d4 100644 --- a/code/studio/src/settings_dialog.h +++ b/code/studio/src/settings_dialog.h @@ -1,62 +1,62 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SETTINGS_DIALOG_H -#define SETTINGS_DIALOG_H - -#include "ui_settings_dialog.h" - -class QSettings; - -class SettingsDialog : public QDialog, public Ui::SettingsDialog -{ - Q_OBJECT -public: - SettingsDialog( QDialog *parent = NULL ); - ~SettingsDialog(); - - void setSettings( QSettings *s ){ settings = s; } - - void load(); - -public Q_SLOTS: - void accept(); - void reject(); - - void onOKClicked(); - void onCancelClicked(); - - void onPluginBClicked(); - void onSheetsBClicked(); - void onAssetsBClicked(); - void onPrimitivesBClicked(); - void onLigoBClicked(); - - void onPathAddClicked(); - void onPathRemoveClicked(); - void onRecursiveAddClicked(); - void onRecursiveRemoveClicked(); - -private: - void setupConnections(); - void save(); - void saveSearchPaths(); - void saveRecursivePaths(); - - QSettings *settings; -}; - -#endif +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SETTINGS_DIALOG_H +#define SETTINGS_DIALOG_H + +#include "ui_settings_dialog.h" + +class QSettings; + +class SettingsDialog : public QDialog, public Ui::SettingsDialog +{ + Q_OBJECT +public: + SettingsDialog( QDialog *parent = NULL ); + ~SettingsDialog(); + + void setSettings( QSettings *s ){ settings = s; } + + void load(); + +public Q_SLOTS: + void accept(); + void reject(); + + void onOKClicked(); + void onCancelClicked(); + + void onPluginBClicked(); + void onSheetsBClicked(); + void onAssetsBClicked(); + void onPrimitivesBClicked(); + void onLigoBClicked(); + + void onPathAddClicked(); + void onPathRemoveClicked(); + void onRecursiveAddClicked(); + void onRecursiveRemoveClicked(); + +private: + void setupConnections(); + void save(); + void saveSearchPaths(); + void saveRecursivePaths(); + + QSettings *settings; +}; + +#endif diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 252472e8d..36f7b3bc0 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -1,109 +1,109 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "splash_screen.h" -#include -#include -#include -#include - -SplashScreen::SplashScreen() : -QSplashScreen() -{ - progress = 0; - textX = 5; - textY = 20; - pbLeft = 2; - pbTop = 0; - pbWidth = 100; - pbHeight = 20; -} - -SplashScreen::~SplashScreen() -{ -} - -void SplashScreen::setPixmap( const QPixmap &pixmap ) -{ - QSplashScreen::setPixmap( pixmap ); - - if( this->pixmap().width() > 0 ) - pbWidth = this->pixmap().width() - 4; - - if( this->pixmap().height() > 0 ) - pbTop = this->pixmap().height() - pbHeight - 2; - - textY = pbTop - pbHeight / 2; -} - -void SplashScreen::setText( const QString &text ) -{ - this->text = text; - repaint(); - QCoreApplication::instance()->processEvents(); -} - -void SplashScreen::clearText() -{ - setText( "" ); -} - -void SplashScreen::setProgress( int percent ) -{ - progress = percent; - repaint(); - QCoreApplication::instance()->processEvents(); -} - -void SplashScreen::advanceProgress( int percent ) -{ - progress += percent; - repaint(); - QCoreApplication::instance()->processEvents(); -} - -void SplashScreen::drawContents( QPainter *painter ) -{ - QSplashScreen::drawContents( painter ); - - if( progressBarEnabled ) - { - QStyleOptionProgressBarV2 pbStyle; - pbStyle.initFrom( this ); - pbStyle.state = QStyle::State_Enabled; - pbStyle.textVisible = false; - pbStyle.minimum = 0; - pbStyle.maximum = 100; - pbStyle.progress = progress; - pbStyle.invertedAppearance = false; - pbStyle.rect = QRect( pbLeft, pbTop, pbWidth, pbHeight ); - - style()->drawControl( QStyle::CE_ProgressBar, &pbStyle, painter, this ); - } - - if( !text.isEmpty() ) - { - QPen oldPen = painter->pen(); - QPen pen; - pen.setColor( Qt::white ); - painter->setPen( pen ); - painter->drawText( textX, textY, text ); - painter->setPen( oldPen ); - } -} - - +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "splash_screen.h" +#include +#include +#include +#include + +SplashScreen::SplashScreen() : +QSplashScreen() +{ + progress = 0; + textX = 5; + textY = 20; + pbLeft = 2; + pbTop = 0; + pbWidth = 100; + pbHeight = 20; +} + +SplashScreen::~SplashScreen() +{ +} + +void SplashScreen::setPixmap( const QPixmap &pixmap ) +{ + QSplashScreen::setPixmap( pixmap ); + + if( this->pixmap().width() > 0 ) + pbWidth = this->pixmap().width() - 4; + + if( this->pixmap().height() > 0 ) + pbTop = this->pixmap().height() - pbHeight - 2; + + textY = pbTop - pbHeight / 2; +} + +void SplashScreen::setText( const QString &text ) +{ + this->text = text; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::clearText() +{ + setText( "" ); +} + +void SplashScreen::setProgress( int percent ) +{ + progress = percent; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::advanceProgress( int percent ) +{ + progress += percent; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::drawContents( QPainter *painter ) +{ + QSplashScreen::drawContents( painter ); + + if( progressBarEnabled ) + { + QStyleOptionProgressBarV2 pbStyle; + pbStyle.initFrom( this ); + pbStyle.state = QStyle::State_Enabled; + pbStyle.textVisible = false; + pbStyle.minimum = 0; + pbStyle.maximum = 100; + pbStyle.progress = progress; + pbStyle.invertedAppearance = false; + pbStyle.rect = QRect( pbLeft, pbTop, pbWidth, pbHeight ); + + style()->drawControl( QStyle::CE_ProgressBar, &pbStyle, painter, this ); + } + + if( !text.isEmpty() ) + { + QPen oldPen = painter->pen(); + QPen pen; + pen.setColor( Qt::white ); + painter->setPen( pen ); + painter->drawText( textX, textY, text ); + painter->setPen( oldPen ); + } +} + + diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h index ec6cd3da8..c4ba0f648 100644 --- a/code/studio/src/splash_screen.h +++ b/code/studio/src/splash_screen.h @@ -1,60 +1,60 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef SPLASH_SCREEN_H -#define SPLASH_SCREEN_H - - -#include - -class SplashScreen : public QSplashScreen -{ - Q_OBJECT -public: - SplashScreen(); - ~SplashScreen(); - - void setPixmap( const QPixmap &pixmap ); - - void setText( const QString &text ); - void clearText(); - void setTextXY( int x, int y ){ textX = x; textY = y; } - void setProgress( int percent ); - void advanceProgress( int percent ); - - void setProgressBarEnabled( bool b ){ progressBarEnabled = b; } - void setProgressBarRect( int left, int top, int width, int height ){} - -protected: - void drawContents( QPainter *painter ); - -private: - int progress; - int pbLeft; - int pbTop; - int pbWidth; - int pbHeight; - - QString text; - int textX; - int textY; - - bool progressBarEnabled; -}; - -#endif - +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef SPLASH_SCREEN_H +#define SPLASH_SCREEN_H + + +#include + +class SplashScreen : public QSplashScreen +{ + Q_OBJECT +public: + SplashScreen(); + ~SplashScreen(); + + void setPixmap( const QPixmap &pixmap ); + + void setText( const QString &text ); + void clearText(); + void setTextXY( int x, int y ){ textX = x; textY = y; } + void setProgress( int percent ); + void advanceProgress( int percent ); + + void setProgressBarEnabled( bool b ){ progressBarEnabled = b; } + void setProgressBarRect( int left, int top, int width, int height ){} + +protected: + void drawContents( QPainter *painter ); + +private: + int progress; + int pbLeft; + int pbTop; + int pbWidth; + int pbHeight; + + QString text; + int textX; + int textY; + + bool progressBarEnabled; +}; + +#endif + From 02e8f6e95629ca88820a01e4f62f336b61001214 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 19 Aug 2014 15:38:16 +0200 Subject: [PATCH 280/282] EOL --- .../src/plugins/tile_editor/CMakeLists.txt | 100 +- .../plugins/tile_editor/land_edit_dialog.cpp | 210 +-- .../plugins/tile_editor/land_edit_dialog.h | 102 +- .../tile_editor/studio_plugin_tile_editor.xml | 18 +- .../src/plugins/tile_editor/tile_bank.cpp | 1284 ++++++++--------- .../src/plugins/tile_editor/tile_bank.h | 204 +-- .../src/plugins/tile_editor/tile_constants.h | 86 +- .../src/plugins/tile_editor/tile_images.h | 80 +- .../tile_editor/tile_item_delegate.cpp | 242 ++-- .../plugins/tile_editor/tilebank_loader.cpp | 84 +- .../src/plugins/tile_editor/tilebank_loader.h | 70 +- .../plugins/tile_editor/tilebank_saver.cpp | 96 +- .../src/plugins/tile_editor/tilebank_saver.h | 78 +- .../translation_manager/uxt_editor.cpp | 944 ++++++------ 14 files changed, 1799 insertions(+), 1799 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index 396522235..78cc5ef49 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -1,50 +1,50 @@ -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) - -FILE(GLOB SRC *.cpp *.h) -SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) - -SET(OVQT_TILE_EDITOR_PLUGIN_HDR - tile_model.h - tile_editor_main_window.h - tile_editor_plugin.h - land_edit_dialog.h) - -SET(OVQT_TILE_EDITOR_PLUGIN_UIS - tile_editor_main_window.ui - land_edit_dialog.ui) - -SET(OVQT_PLUG_TILE_EDITOR_RCS tile_editor.qrc) - -SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) - -QT4_WRAP_CPP(OVQT_TILE_EDITOR_PLUGIN_MOC_SRC ${OVQT_TILE_EDITOR_PLUGIN_HDR}) -QT4_ADD_RESOURCES( OVQT_PLUG_TILE_EDITOR_RC_SRCS ${OVQT_PLUG_TILE_EDITOR_RCS}) -QT4_WRAP_UI(OVQT_TILE_EDITOR_PLUGIN_UI_HDRS ${OVQT_TILE_EDITOR_PLUGIN_UIS}) - -SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) -SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS}) -SOURCE_GROUP("Tile Editor Plugin" FILES ${SRC}) -SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) - -ADD_LIBRARY(studio_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) - -TARGET_LINK_LIBRARIES(studio_plugin_tile_editor studio_plugin_core nelmisc ${QT_LIBRARIES}) - -IF(WITH_STLPORT) - TARGET_LINK_LIBRARIES(studio_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) -ENDIF(WITH_STLPORT) - -NL_DEFAULT_PROPS(studio_plugin_tile_editor "Tools: Studio Plugin: Tile Editor") -NL_ADD_RUNTIME_FLAGS(studio_plugin_tile_editor) -NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) - -ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) - -INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_tile_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_HDR + tile_model.h + tile_editor_main_window.h + tile_editor_plugin.h + land_edit_dialog.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_UIS + tile_editor_main_window.ui + land_edit_dialog.ui) + +SET(OVQT_PLUG_TILE_EDITOR_RCS tile_editor.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_WRAP_CPP(OVQT_TILE_EDITOR_PLUGIN_MOC_SRC ${OVQT_TILE_EDITOR_PLUGIN_HDR}) +QT4_ADD_RESOURCES( OVQT_PLUG_TILE_EDITOR_RC_SRCS ${OVQT_PLUG_TILE_EDITOR_RCS}) +QT4_WRAP_UI(OVQT_TILE_EDITOR_PLUGIN_UI_HDRS ${OVQT_TILE_EDITOR_PLUGIN_UIS}) + +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS}) +SOURCE_GROUP("Tile Editor Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(studio_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) + +TARGET_LINK_LIBRARIES(studio_plugin_tile_editor studio_plugin_core nelmisc ${QT_LIBRARIES}) + +IF(WITH_STLPORT) + TARGET_LINK_LIBRARIES(studio_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) +ENDIF(WITH_STLPORT) + +NL_DEFAULT_PROPS(studio_plugin_tile_editor "Tools: Studio Plugin: Tile Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_tile_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_tile_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp index 40fbf3024..025e55730 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -1,105 +1,105 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "land_edit_dialog.h" - -LandEditDialog::LandEditDialog( QWidget *parent ) : -QDialog( parent ) -{ - setupUi( this ); - setupConnections(); -} - -LandEditDialog::~LandEditDialog() -{ -} - -void LandEditDialog::getSelectedTileSets( QStringList &l ) const -{ - int c = tilesetLV->count(); - for( int i = 0; i < c; i++ ) - { - l.push_back( tilesetLV->item( i )->text() ); - } -} - -void LandEditDialog::setSelectedTileSets( QStringList &l ) -{ - tilesetLV->clear(); - - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - tilesetLV->addItem( itr.next() ); - } -} - -void LandEditDialog::setTileSets( const QStringList &l ) -{ - tilesetCB->clear(); - - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - tilesetCB->addItem( itr.next() ); - } -} - -void LandEditDialog::setupConnections() -{ - connect( okButton, SIGNAL( clicked( bool ) ), this, SLOT( onOkClicked() ) ); - connect( cancelButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); - connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( onAddClicked() ) ); - connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveClicked() ) ); -} - -void LandEditDialog::onOkClicked() -{ - accept(); -} - -void LandEditDialog::onCancelClicked() -{ - reject(); -} - -void LandEditDialog::onAddClicked() -{ - if( tilesetCB->currentIndex() < 0 ) - return; - - QString text = tilesetCB->currentText(); - - int c = tilesetLV->count(); - for( int i = 0; i < c; i++ ) - { - if( text == tilesetLV->item( i )->text() ) - return; - } - - tilesetLV->addItem( text ); -} - -void LandEditDialog::onRemoveClicked() -{ - if( tilesetLV->currentItem() == NULL ) - return; - - QListWidgetItem *item = tilesetLV->currentItem(); - delete item; -} - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "land_edit_dialog.h" + +LandEditDialog::LandEditDialog( QWidget *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); +} + +LandEditDialog::~LandEditDialog() +{ +} + +void LandEditDialog::getSelectedTileSets( QStringList &l ) const +{ + int c = tilesetLV->count(); + for( int i = 0; i < c; i++ ) + { + l.push_back( tilesetLV->item( i )->text() ); + } +} + +void LandEditDialog::setSelectedTileSets( QStringList &l ) +{ + tilesetLV->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetLV->addItem( itr.next() ); + } +} + +void LandEditDialog::setTileSets( const QStringList &l ) +{ + tilesetCB->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetCB->addItem( itr.next() ); + } +} + +void LandEditDialog::setupConnections() +{ + connect( okButton, SIGNAL( clicked( bool ) ), this, SLOT( onOkClicked() ) ); + connect( cancelButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); + connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( onAddClicked() ) ); + connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveClicked() ) ); +} + +void LandEditDialog::onOkClicked() +{ + accept(); +} + +void LandEditDialog::onCancelClicked() +{ + reject(); +} + +void LandEditDialog::onAddClicked() +{ + if( tilesetCB->currentIndex() < 0 ) + return; + + QString text = tilesetCB->currentText(); + + int c = tilesetLV->count(); + for( int i = 0; i < c; i++ ) + { + if( text == tilesetLV->item( i )->text() ) + return; + } + + tilesetLV->addItem( text ); +} + +void LandEditDialog::onRemoveClicked() +{ + if( tilesetLV->currentItem() == NULL ) + return; + + QListWidgetItem *item = tilesetLV->currentItem(); + delete item; +} + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h index ac3762b46..3873c6df5 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.h +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -1,51 +1,51 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef LAND_EDIT_DLG_H -#define LAND_EDIT_DLG_H - - -#include "ui_land_edit_dialog.h" -#include - -class LandEditDialog : public QDialog, public Ui::LandEditDialog -{ - Q_OBJECT -public: - LandEditDialog( QWidget *parent = NULL ); - ~LandEditDialog(); - - void getSelectedTileSets( QStringList &l ) const; - void setSelectedTileSets( QStringList &l ); - - void setTileSets( const QStringList &l ); - -private: - void setupConnections(); - - -private Q_SLOTS: - void onOkClicked(); - void onCancelClicked(); - void onAddClicked(); - void onRemoveClicked(); - -}; - - -#endif - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef LAND_EDIT_DLG_H +#define LAND_EDIT_DLG_H + + +#include "ui_land_edit_dialog.h" +#include + +class LandEditDialog : public QDialog, public Ui::LandEditDialog +{ + Q_OBJECT +public: + LandEditDialog( QWidget *parent = NULL ); + ~LandEditDialog(); + + void getSelectedTileSets( QStringList &l ) const; + void setSelectedTileSets( QStringList &l ); + + void setTileSets( const QStringList &l ); + +private: + void setupConnections(); + + +private Q_SLOTS: + void onOkClicked(); + void onCancelClicked(); + void onAddClicked(); + void onRemoveClicked(); + +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml index d69201f9b..0e5727896 100644 --- a/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml +++ b/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml @@ -1,10 +1,10 @@ - - studio_plugin_tile_editor - TileEditor - 1.0 - Ryzom Core - Tile bank editing plugin. - - - + + studio_plugin_tile_editor + TileEditor + 1.0 + Ryzom Core + Tile bank editing plugin. + + + \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 8e4d8f511..8e3578eeb 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -1,642 +1,642 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "tile_bank.h" -#include "nel/3d/tile_bank.h" - -#include - -namespace{ - - bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) - { - QImage img = pixmap.toImage(); - if( img.format() != QImage::Format_ARGB32 ) - img = img.convertToFormat( QImage::Format_ARGB32 ); - - if( img.format() != QImage::Format_ARGB32 ) - return false; - - int c = img.width() * img.height(); - - const unsigned char *data = img.bits(); - const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); - - NLMISC::CBGRA bgra; - pixels.clear(); - - int i = 0; - while( i < c ) - { - bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; - bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; - bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; - bgra.B = ( idata[ i ] & 0x000000FF ); - pixels.push_back( bgra ); - - i++; - } - - return true; - } - - - NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) - { - return NL3D::CTile::TBitmap( int( channel ) ); - } - - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -class TileBankPvt -{ -public: - - bool checkSize( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel, int w, int h ) - { - int width = -1; - - switch( type ) - { - case TileConstants::Tile128: - width = 128; - break; - - case TileConstants::Tile256: - width = 256; - break; - - case TileConstants::TileTransition: - { - if( channel == TileConstants::TileAlpha ) - width = 64; - else - width = 128; - - } - break; - - case TileConstants::TileDisplacement: - width = 32; - break; - } - - if( width == w ) - return true; - - return false; - } - - NL3D::CTileSet::TError checkTile( NL3D::CTileSet *set, int tile, TileConstants::TNodeTileType type, NL3D::CTileBorder &border, NL3D::CTile::TBitmap bitmap, QString &msg ) - { - NL3D::CTileSet::TError error; - - if( bitmap == NL3D::CTile::additive ) - return NL3D::CTileSet::ok; - - if( type == TileConstants::TileDisplacement ) - return NL3D::CTileSet::ok; - - int component; - int pixel; - int idx; - - switch( type ) - { - case TileConstants::Tile128: - error = set->checkTile128( bitmap, border, pixel, component ); - break; - - case TileConstants::Tile256: - error = set->checkTile256( bitmap, border, pixel, component ); - break; - - case TileConstants::TileTransition: - { - if( bitmap != NL3D::CTile::alpha ) - error = set->checkTile128( bitmap, border, pixel, component ); - else - error = set->checkTileTransition( NL3D::CTileSet::TTransition( tile ), bitmap, border, idx, pixel, component ); - - break; - } - } - - if( ( error != NL3D::CTileSet::ok ) && ( error != NL3D::CTileSet::addFirstA128128 ) ) - { - static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; - - msg = NL3D::CTileSet::getErrorMessage( error ); - msg += "\n"; - msg += " pixel %1 component %2"; - msg = msg.arg( pixel ); - msg = msg.arg( comp[ component ] ); - } - - return error; - } - - void setTile( NL3D::CTileSet *set, int tile, int rotation, const QString &name, NL3D::CTile::TBitmap bm, TileConstants::TNodeTileType type, NL3D::CTileBorder &border ) - { - switch( type ) - { - case TileConstants::Tile128: - set->setTile128( tile, name.toUtf8().constData(), bm, m_bank ); - break; - - case TileConstants::Tile256: - set->setTile256( tile, name.toUtf8().constData(), bm, m_bank ); - break; - - case TileConstants::TileTransition: - if( bm != NL3D::CTile::alpha ) - set->setTileTransition( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), bm, m_bank, border ); - else - set->setTileTransitionAlpha( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), m_bank, border, rotation ); - break; - - case TileConstants::TileDisplacement: - set->setDisplacement( NL3D::CTileSet::TDisplacement( tile ), name.toUtf8().constData(), m_bank ); - break; - } - - } - - void buildBorder( QPixmap &pm, NL3D::CTileBorder &border ) - { - std::vector< NLMISC::CBGRA > pixels; - pixmapToCBGRA( pm, pixels ); - border.set( pm.width(), pm.height(), pixels ); - } - - NL3D::CTileBank m_bank; -}; - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -TileBank::TileBank() -{ - m_pvt = new TileBankPvt(); - resetError(); - m_rotation = 0; -} - -TileBank::~TileBank() -{ - delete m_pvt; -} - -void TileBank::addTileSet( const QString &name ) -{ - m_pvt->m_bank.addTileSet( name.toUtf8().constData() ); - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( 0 ); -} - -void TileBank::removeTileSet( int idx ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); - if( set == NULL ) - return; - - int c = m_pvt->m_bank.getLandCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); - land->removeTileSet( set->getName() ); - } - - m_pvt->m_bank.removeTileSet( idx ); -} - -void TileBank::renameTileSet( int idx, const QString &newName ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); - if( set == NULL ) - return; - - std::string oldName = set->getName(); - set->setName( newName.toUtf8().constData() ); - - int c = m_pvt->m_bank.getLandCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); - land->removeTileSet( oldName ); - land->addTileSet( newName.toUtf8().constData() ); - } - -} - -void TileBank::getTileSets( QStringList &l ) -{ - int c = m_pvt->m_bank.getTileSetCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( i ); - l.push_back( set->getName().c_str() ); - } -} - -void TileBank::addLand( const QString &name ) -{ - m_pvt->m_bank.addLand( name.toUtf8().constData() ); -} - -void TileBank::removeLand( int idx ) -{ - m_pvt->m_bank.removeLand( idx ); -} - -void TileBank::getLands( QStringList &l ) -{ - l.clear(); - - int c = m_pvt->m_bank.getLandCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); - l.push_back( land->getName().c_str() ); - } -} - -void TileBank::setLandSets( int idx, const QStringList &l ) -{ - NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); - land->clear(); - - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - land->addTileSet( itr.next().toUtf8().constData() ); - } -} - -void TileBank::getLandSets( int idx, QStringList &l ) -{ - NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); - if( land == NULL ) - return; - - l.clear(); - - std::set< std::string> sets = land->getTileSets(); - std::set< std::string >::const_iterator itr = sets.begin(); - while( itr != sets.end() ) - { - l.push_back( itr->c_str() ); - ++itr; - } -} - -bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) -{ - resetError(); - - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( setIdx ); - - int tile; - switch( type ) - { - case TileConstants::Tile128: set->addTile128( tile, m_pvt->m_bank ); break; - case TileConstants::Tile256: set->addTile256( tile, m_pvt->m_bank ); break; - } - - bool b = setTile( setIdx, tile, name, pixmap, channel, type ); - if( b ) - return true; - - // There was an error, roll back - switch( type ) - { - case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; - case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; - } - - return false; -} - -void TileBank::removeTile( int ts, int type, int tile ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); - - switch( type ) - { - case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; - case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; - } -} - -bool TileBank::setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) -{ - resetError(); - - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileset ); - if( set == NULL ) - return false; - - QPixmap pm = pixmap.value< QPixmap >(); - if( pm.isNull() ) - { - m_hasError = true; - m_lastError = "Failed to load image."; - return false; - } - - if( pm.width() != pm.height() ) - { - m_hasError = true; - m_lastError = "Image isn't square."; - return false; - } - - if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) ) - { - m_hasError = true; - m_lastError = "Invalid image size."; - return false; - } - - NL3D::CTileBorder border; - m_pvt->buildBorder( pm, border ); - - if( ( type == TileConstants::TileTransition ) && ( channel == TileConstants::TileAlpha ) ) - { - int rotBits = m_rotation; - while( rotBits > 0 ) - { - border.rotate(); - rotBits--; - } - } - - QString msg; - NL3D::CTileSet::TError error = m_pvt->checkTile( set, tile, type, border, channelToTBitmap( channel ), msg ); - - // Tile checks out fine, set it - if( ( error == NL3D::CTileSet::ok ) || ( error == NL3D::CTileSet::addFirstA128128 ) ) - { - if( error == NL3D::CTileSet::addFirstA128128 ) - set->setBorder( channelToTBitmap( channel ), border ); - - m_pvt->setTile( set, tile, m_rotation, name, channelToTBitmap( channel ), type, border ); - - return true; - } - - setError( msg ); - - return false; -} - -void TileBank::replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ) -{ - setTile( ts, tile, name, pixmap, channel, TileConstants::TNodeTileType( type ) ); -} - -void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); - - int tileId; - - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - - switch( type ) - { - case TileConstants::Tile128: - set->clearTile128( tile, bm, m_pvt->m_bank ); - break; - - case TileConstants::Tile256: - set->clearTile256( tile, bm, m_pvt->m_bank ); - break; - - case TileConstants::TileTransition: - set->clearTransition( NL3D::CTileSet::TTransition( tile ), bm, m_pvt->m_bank ); - break; - - case TileConstants::TileDisplacement: - set->clearDisplacement( NL3D::CTileSet::TDisplacement( tile ), m_pvt->m_bank ); - break; - } - -} - -int TileBank::getTileCount( int tileSet, TileConstants::TNodeTileType type ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return -1; - - int c = 0; - - switch( type ) - { - case TileConstants::Tile128: - c = set->getNumTile128(); - break; - - case TileConstants::Tile256: - c = set->getNumTile256(); - break; - - case TileConstants::TileTransition: - c = NL3D::CTileSet::count; - break; - - case TileConstants::TileDisplacement: - c = NL3D::CTileSet::CountDisplace; - break; - } - - return c; -} - -int TileBank::getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return -1; - - int tile = -1; - - switch( type ) - { - case TileConstants::Tile128: - tile = set->getTile128( tileIdInSet ); - break; - - case TileConstants::Tile256: - tile = set->getTile256( tileIdInSet ); - break; - - case TileConstants::TileTransition: - tile = set->getTransition( tileIdInSet )->getTile(); - break; - - case TileConstants::TileDisplacement: - tile = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( tileIdInSet ) ); - break; - } - - return tile; -} - -void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return; - - switch( type ) - { - case TileConstants::Tile128: - case TileConstants::Tile256: - case TileConstants::TileTransition: - { - NL3D::CTile *t = m_pvt->m_bank.getTile( tileId ); - if( t == NULL ) - return; - - images.diffuse = t->getFileName( channelToTBitmap( TileConstants::TileDiffuse ) ).c_str(); - images.additive = t->getFileName( channelToTBitmap( TileConstants::TileAdditive ) ).c_str(); - images.alpha = t->getFileName( channelToTBitmap( TileConstants::TileAlpha ) ).c_str(); - } - break; - - case TileConstants::TileDisplacement: - { - images.diffuse = m_pvt->m_bank.getDisplacementMap( tileId ); - } - break; - } - -} - -void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ) -{ - l.clear(); - - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return; - - int c = getTileCount( tileSet, type ); - - TileImages images; - - for( int i = 0; i < c; i++ ) - { - images.clear(); - - int id = getRealTileId( tileSet, type, i ); - if( id < 0 ) - { - l.push_back( images ); - continue; - } - - getTileImages( tileSet, type, id, images ); - - l.push_back( images ); - } - -} - -void TileBank::setVegetation( int tileSet, const QString &vegetation ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return; - - set->setTileVegetableDescFileName( vegetation.toUtf8().constData() ); -} - - -QString TileBank::getVegetation( int tileSet ) const -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return ""; - - return set->getTileVegetableDescFileName().c_str(); -} - -void TileBank::setOriented( int tileSet, bool b ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return; - - set->setOriented( b ); -} - -bool TileBank::getOriented( int tileSet ) const -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return false; - - return set->getOriented(); -} - - -void TileBank::setSurfaceData( int tileSet, unsigned long data ) -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return; - - set->SurfaceData = data; -} - -unsigned long TileBank::getSurfaceData( int tileSet ) const -{ - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); - if( set == NULL ) - return 0; - - return set->SurfaceData; -} - -void TileBank::setTexturePath( const QString &path ) -{ - m_pvt->m_bank.setAbsPath( path.toUtf8().constData() ); -} - -QString TileBank::getTexturePath() const -{ - return m_pvt->m_bank.getAbsPath().c_str(); -} - -void TileBank::setRotation( int rotation ) -{ - m_rotation = rotation; -} - -void TileBank::serial( NLMISC::IStream &f ) -{ - m_pvt->m_bank.serial( f ); -} - - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "tile_bank.h" +#include "nel/3d/tile_bank.h" + +#include + +namespace{ + + bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) + { + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + + return true; + } + + + NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) + { + return NL3D::CTile::TBitmap( int( channel ) ); + } + + +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +class TileBankPvt +{ +public: + + bool checkSize( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel, int w, int h ) + { + int width = -1; + + switch( type ) + { + case TileConstants::Tile128: + width = 128; + break; + + case TileConstants::Tile256: + width = 256; + break; + + case TileConstants::TileTransition: + { + if( channel == TileConstants::TileAlpha ) + width = 64; + else + width = 128; + + } + break; + + case TileConstants::TileDisplacement: + width = 32; + break; + } + + if( width == w ) + return true; + + return false; + } + + NL3D::CTileSet::TError checkTile( NL3D::CTileSet *set, int tile, TileConstants::TNodeTileType type, NL3D::CTileBorder &border, NL3D::CTile::TBitmap bitmap, QString &msg ) + { + NL3D::CTileSet::TError error; + + if( bitmap == NL3D::CTile::additive ) + return NL3D::CTileSet::ok; + + if( type == TileConstants::TileDisplacement ) + return NL3D::CTileSet::ok; + + int component; + int pixel; + int idx; + + switch( type ) + { + case TileConstants::Tile128: + error = set->checkTile128( bitmap, border, pixel, component ); + break; + + case TileConstants::Tile256: + error = set->checkTile256( bitmap, border, pixel, component ); + break; + + case TileConstants::TileTransition: + { + if( bitmap != NL3D::CTile::alpha ) + error = set->checkTile128( bitmap, border, pixel, component ); + else + error = set->checkTileTransition( NL3D::CTileSet::TTransition( tile ), bitmap, border, idx, pixel, component ); + + break; + } + } + + if( ( error != NL3D::CTileSet::ok ) && ( error != NL3D::CTileSet::addFirstA128128 ) ) + { + static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; + + msg = NL3D::CTileSet::getErrorMessage( error ); + msg += "\n"; + msg += " pixel %1 component %2"; + msg = msg.arg( pixel ); + msg = msg.arg( comp[ component ] ); + } + + return error; + } + + void setTile( NL3D::CTileSet *set, int tile, int rotation, const QString &name, NL3D::CTile::TBitmap bm, TileConstants::TNodeTileType type, NL3D::CTileBorder &border ) + { + switch( type ) + { + case TileConstants::Tile128: + set->setTile128( tile, name.toUtf8().constData(), bm, m_bank ); + break; + + case TileConstants::Tile256: + set->setTile256( tile, name.toUtf8().constData(), bm, m_bank ); + break; + + case TileConstants::TileTransition: + if( bm != NL3D::CTile::alpha ) + set->setTileTransition( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), bm, m_bank, border ); + else + set->setTileTransitionAlpha( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), m_bank, border, rotation ); + break; + + case TileConstants::TileDisplacement: + set->setDisplacement( NL3D::CTileSet::TDisplacement( tile ), name.toUtf8().constData(), m_bank ); + break; + } + + } + + void buildBorder( QPixmap &pm, NL3D::CTileBorder &border ) + { + std::vector< NLMISC::CBGRA > pixels; + pixmapToCBGRA( pm, pixels ); + border.set( pm.width(), pm.height(), pixels ); + } + + NL3D::CTileBank m_bank; +}; + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TileBank::TileBank() +{ + m_pvt = new TileBankPvt(); + resetError(); + m_rotation = 0; +} + +TileBank::~TileBank() +{ + delete m_pvt; +} + +void TileBank::addTileSet( const QString &name ) +{ + m_pvt->m_bank.addTileSet( name.toUtf8().constData() ); + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( 0 ); +} + +void TileBank::removeTileSet( int idx ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return; + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + land->removeTileSet( set->getName() ); + } + + m_pvt->m_bank.removeTileSet( idx ); +} + +void TileBank::renameTileSet( int idx, const QString &newName ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return; + + std::string oldName = set->getName(); + set->setName( newName.toUtf8().constData() ); + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + land->removeTileSet( oldName ); + land->addTileSet( newName.toUtf8().constData() ); + } + +} + +void TileBank::getTileSets( QStringList &l ) +{ + int c = m_pvt->m_bank.getTileSetCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( i ); + l.push_back( set->getName().c_str() ); + } +} + +void TileBank::addLand( const QString &name ) +{ + m_pvt->m_bank.addLand( name.toUtf8().constData() ); +} + +void TileBank::removeLand( int idx ) +{ + m_pvt->m_bank.removeLand( idx ); +} + +void TileBank::getLands( QStringList &l ) +{ + l.clear(); + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + l.push_back( land->getName().c_str() ); + } +} + +void TileBank::setLandSets( int idx, const QStringList &l ) +{ + NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); + land->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + land->addTileSet( itr.next().toUtf8().constData() ); + } +} + +void TileBank::getLandSets( int idx, QStringList &l ) +{ + NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); + if( land == NULL ) + return; + + l.clear(); + + std::set< std::string> sets = land->getTileSets(); + std::set< std::string >::const_iterator itr = sets.begin(); + while( itr != sets.end() ) + { + l.push_back( itr->c_str() ); + ++itr; + } +} + +bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + resetError(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( setIdx ); + + int tile; + switch( type ) + { + case TileConstants::Tile128: set->addTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->addTile256( tile, m_pvt->m_bank ); break; + } + + bool b = setTile( setIdx, tile, name, pixmap, channel, type ); + if( b ) + return true; + + // There was an error, roll back + switch( type ) + { + case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; + } + + return false; +} + +void TileBank::removeTile( int ts, int type, int tile ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); + + switch( type ) + { + case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; + } +} + +bool TileBank::setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + resetError(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileset ); + if( set == NULL ) + return false; + + QPixmap pm = pixmap.value< QPixmap >(); + if( pm.isNull() ) + { + m_hasError = true; + m_lastError = "Failed to load image."; + return false; + } + + if( pm.width() != pm.height() ) + { + m_hasError = true; + m_lastError = "Image isn't square."; + return false; + } + + if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) ) + { + m_hasError = true; + m_lastError = "Invalid image size."; + return false; + } + + NL3D::CTileBorder border; + m_pvt->buildBorder( pm, border ); + + if( ( type == TileConstants::TileTransition ) && ( channel == TileConstants::TileAlpha ) ) + { + int rotBits = m_rotation; + while( rotBits > 0 ) + { + border.rotate(); + rotBits--; + } + } + + QString msg; + NL3D::CTileSet::TError error = m_pvt->checkTile( set, tile, type, border, channelToTBitmap( channel ), msg ); + + // Tile checks out fine, set it + if( ( error == NL3D::CTileSet::ok ) || ( error == NL3D::CTileSet::addFirstA128128 ) ) + { + if( error == NL3D::CTileSet::addFirstA128128 ) + set->setBorder( channelToTBitmap( channel ), border ); + + m_pvt->setTile( set, tile, m_rotation, name, channelToTBitmap( channel ), type, border ); + + return true; + } + + setError( msg ); + + return false; +} + +void TileBank::replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ) +{ + setTile( ts, tile, name, pixmap, channel, TileConstants::TNodeTileType( type ) ); +} + +void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); + + int tileId; + + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + + switch( type ) + { + case TileConstants::Tile128: + set->clearTile128( tile, bm, m_pvt->m_bank ); + break; + + case TileConstants::Tile256: + set->clearTile256( tile, bm, m_pvt->m_bank ); + break; + + case TileConstants::TileTransition: + set->clearTransition( NL3D::CTileSet::TTransition( tile ), bm, m_pvt->m_bank ); + break; + + case TileConstants::TileDisplacement: + set->clearDisplacement( NL3D::CTileSet::TDisplacement( tile ), m_pvt->m_bank ); + break; + } + +} + +int TileBank::getTileCount( int tileSet, TileConstants::TNodeTileType type ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return -1; + + int c = 0; + + switch( type ) + { + case TileConstants::Tile128: + c = set->getNumTile128(); + break; + + case TileConstants::Tile256: + c = set->getNumTile256(); + break; + + case TileConstants::TileTransition: + c = NL3D::CTileSet::count; + break; + + case TileConstants::TileDisplacement: + c = NL3D::CTileSet::CountDisplace; + break; + } + + return c; +} + +int TileBank::getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return -1; + + int tile = -1; + + switch( type ) + { + case TileConstants::Tile128: + tile = set->getTile128( tileIdInSet ); + break; + + case TileConstants::Tile256: + tile = set->getTile256( tileIdInSet ); + break; + + case TileConstants::TileTransition: + tile = set->getTransition( tileIdInSet )->getTile(); + break; + + case TileConstants::TileDisplacement: + tile = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( tileIdInSet ) ); + break; + } + + return tile; +} + +void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + switch( type ) + { + case TileConstants::Tile128: + case TileConstants::Tile256: + case TileConstants::TileTransition: + { + NL3D::CTile *t = m_pvt->m_bank.getTile( tileId ); + if( t == NULL ) + return; + + images.diffuse = t->getFileName( channelToTBitmap( TileConstants::TileDiffuse ) ).c_str(); + images.additive = t->getFileName( channelToTBitmap( TileConstants::TileAdditive ) ).c_str(); + images.alpha = t->getFileName( channelToTBitmap( TileConstants::TileAlpha ) ).c_str(); + } + break; + + case TileConstants::TileDisplacement: + { + images.diffuse = m_pvt->m_bank.getDisplacementMap( tileId ); + } + break; + } + +} + +void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ) +{ + l.clear(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + int c = getTileCount( tileSet, type ); + + TileImages images; + + for( int i = 0; i < c; i++ ) + { + images.clear(); + + int id = getRealTileId( tileSet, type, i ); + if( id < 0 ) + { + l.push_back( images ); + continue; + } + + getTileImages( tileSet, type, id, images ); + + l.push_back( images ); + } + +} + +void TileBank::setVegetation( int tileSet, const QString &vegetation ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->setTileVegetableDescFileName( vegetation.toUtf8().constData() ); +} + + +QString TileBank::getVegetation( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return ""; + + return set->getTileVegetableDescFileName().c_str(); +} + +void TileBank::setOriented( int tileSet, bool b ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->setOriented( b ); +} + +bool TileBank::getOriented( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return false; + + return set->getOriented(); +} + + +void TileBank::setSurfaceData( int tileSet, unsigned long data ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->SurfaceData = data; +} + +unsigned long TileBank::getSurfaceData( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return 0; + + return set->SurfaceData; +} + +void TileBank::setTexturePath( const QString &path ) +{ + m_pvt->m_bank.setAbsPath( path.toUtf8().constData() ); +} + +QString TileBank::getTexturePath() const +{ + return m_pvt->m_bank.getAbsPath().c_str(); +} + +void TileBank::setRotation( int rotation ) +{ + m_rotation = rotation; +} + +void TileBank::serial( NLMISC::IStream &f ) +{ + m_pvt->m_bank.serial( f ); +} + + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index a4620ad41..9d765b8ae 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -1,102 +1,102 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef TILE_BANK_H -#define TILE_BANK_H - -#include -#include -#include -#include - -#include "tile_constants.h" -#include "tile_images.h" - -namespace NLMISC -{ - class IStream; -} - -class TileBankPvt; - -class TileBank -{ -public: - TileBank(); - ~TileBank(); - - void addTileSet( const QString &name ); - void removeTileSet( int idx ); - void renameTileSet( int idx, const QString &newName ); - void getTileSets( QStringList &l ); - - void addLand( const QString &name ); - void removeLand( int idx ); - void getLands( QStringList &l ); - void setLandSets( int idx, const QStringList &l ); - void getLandSets( int idx, QStringList &l ); - - bool addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); - void removeTile( int ts, int type, int tile ); - bool setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); - void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); - void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); - - - int getTileCount( int tileSet, TileConstants::TNodeTileType type ); - int getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ); - void getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ); - void getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ); - - void setVegetation( int tileSet, const QString &vegetation ); - QString getVegetation( int tileSet ) const; - - void setOriented( int tileSet, bool b ); - bool getOriented( int tileSet ) const; - - void setSurfaceData( int tileSet, unsigned long data ); - unsigned long getSurfaceData( int tileSet ) const; - - void setTexturePath( const QString &path ); - QString getTexturePath() const; - - void setRotation( int rotation ); - - void serial( NLMISC::IStream &f ); - - bool hasError() const{ return m_hasError; } - QString getLastError() const{ return m_lastError; } - void resetError(){ - m_hasError = false; - m_lastError = ""; - } - - void setError( const QString &msg ) - { - m_hasError = true; - m_lastError = msg; - } - -private: - TileBankPvt *m_pvt; - QString m_lastError; - bool m_hasError; - int m_rotation; -}; - -#endif - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TILE_BANK_H +#define TILE_BANK_H + +#include +#include +#include +#include + +#include "tile_constants.h" +#include "tile_images.h" + +namespace NLMISC +{ + class IStream; +} + +class TileBankPvt; + +class TileBank +{ +public: + TileBank(); + ~TileBank(); + + void addTileSet( const QString &name ); + void removeTileSet( int idx ); + void renameTileSet( int idx, const QString &newName ); + void getTileSets( QStringList &l ); + + void addLand( const QString &name ); + void removeLand( int idx ); + void getLands( QStringList &l ); + void setLandSets( int idx, const QStringList &l ); + void getLandSets( int idx, QStringList &l ); + + bool addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void removeTile( int ts, int type, int tile ); + bool setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); + void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + + int getTileCount( int tileSet, TileConstants::TNodeTileType type ); + int getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ); + void getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ); + void getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ); + + void setVegetation( int tileSet, const QString &vegetation ); + QString getVegetation( int tileSet ) const; + + void setOriented( int tileSet, bool b ); + bool getOriented( int tileSet ) const; + + void setSurfaceData( int tileSet, unsigned long data ); + unsigned long getSurfaceData( int tileSet ) const; + + void setTexturePath( const QString &path ); + QString getTexturePath() const; + + void setRotation( int rotation ); + + void serial( NLMISC::IStream &f ); + + bool hasError() const{ return m_hasError; } + QString getLastError() const{ return m_lastError; } + void resetError(){ + m_hasError = false; + m_lastError = ""; + } + + void setError( const QString &msg ) + { + m_hasError = true; + m_lastError = msg; + } + +private: + TileBankPvt *m_pvt; + QString m_lastError; + bool m_hasError; + int m_rotation; +}; + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_constants.h b/code/studio/src/plugins/tile_editor/tile_constants.h index bf09f21a5..56748cb58 100644 --- a/code/studio/src/plugins/tile_editor/tile_constants.h +++ b/code/studio/src/plugins/tile_editor/tile_constants.h @@ -1,43 +1,43 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef TILE_CONSTANTS_H -#define TILE_CONSTANTS_H - - -namespace TileConstants -{ - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - TileChannelCount = 3 - }; - - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3, - TileNodeTypeCount = 4 - }; -} - - -#endif +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TILE_CONSTANTS_H +#define TILE_CONSTANTS_H + + +namespace TileConstants +{ + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + TileChannelCount = 3 + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3, + TileNodeTypeCount = 4 + }; +} + + +#endif diff --git a/code/studio/src/plugins/tile_editor/tile_images.h b/code/studio/src/plugins/tile_editor/tile_images.h index e17267001..280e0a126 100644 --- a/code/studio/src/plugins/tile_editor/tile_images.h +++ b/code/studio/src/plugins/tile_editor/tile_images.h @@ -1,40 +1,40 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef TILE_IMAGES_H -#define TILE_IMAGES_H - -#include - -struct TileImages -{ - QString diffuse; - QString additive; - QString alpha; - - void clear() - { - diffuse.clear(); - additive.clear(); - alpha.clear(); - } -}; - - - -#endif - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TILE_IMAGES_H +#define TILE_IMAGES_H + +#include + +struct TileImages +{ + QString diffuse; + QString additive; + QString alpha; + + void clear() + { + diffuse.clear(); + additive.clear(); + alpha.clear(); + } +}; + + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp b/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp index 43751d612..6f9479354 100644 --- a/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp @@ -1,122 +1,122 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include - -#include - -#include "tile_item_delegate.h" - -#include "tile_model.h" - -TileItemDelegate::TileItemDelegate() -{ - m_zoomFactor = ZoomNormal; - m_imageHint = 128; -} - -TileItemDelegate::~TileItemDelegate() -{ -} - -void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - QStyledItemDelegate::paint(painter,option,index); - - painter->save(); - - QFont font = QApplication::font(); - - //font.setBold(true); - //SubFont.setWeight(SubFont.weight()-2); - QFontMetrics fm(font); - - QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - QString tileFileText = qvariant_cast(index.data(TileModel::TileFilenameRole)); - QString tileIdText = qvariant_cast(index.data(TileModel::TileIndexRole)); - - QSize tileSize = tile.size(); - - //QRect headerRect = option.rect; - QRect rect(option.rect); - //QRect tileRect(option.rect); - int textHeight = fm.height(); - int iconPosModX = PIXMAP_MARGIN + (tile.width() / 2); - int iconPosModY = (option.rect.height() - tile.height()) / 2; - - painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); - - - - //tileRect.setRight(tileSize.width()+30); - //tileRect.setTop(tileRect.top()+5); - //headerRect.setLeft(tileRect.right()); - //subheaderRect.setLeft(tileRect.right()); - //headerRect.setTop(headerRect.top()+5); - //headerRect.setBottom(headerRect.top()+fm.height()); - - //subheaderRect.setTop(headerRect.bottom()+2); - - //painter->drawPixmap(targetrect, pixmap, sourcerect) - - //painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); - //painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); - - //painter->setFont(font); - //painter->drawText(headerRect,headerText); - - - //painter->setFont(SubFont); - //painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); - - painter->restore(); -} - -QSize TileItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const -{ - QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - QSize tileSize = tile.size(); - QFont font = QApplication::font(); - QFontMetrics fm(font); - - return(QSize(tileSize.width()+(2*PIXMAP_MARGIN), tileSize.height()+fm.height()+(2*PIXMAP_MARGIN))); -} - -TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() -{ - return m_zoomFactor; -} - -void TileItemDelegate::setZoomFactor(TileItemDelegate::TZoomFactor zoomFactor) -{ - m_zoomFactor = zoomFactor; -} - -// SLOTS - -void TileItemDelegate::currentTab(int index) -{ - if(index == 1) - { - nlinfo("switching delegate to 1 or 256"); - m_imageHint = 256; - } - else - { - nlinfo("switching delegate to 0,2,3 or 128"); - m_imageHint = 128; - } +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include + +#include + +#include "tile_item_delegate.h" + +#include "tile_model.h" + +TileItemDelegate::TileItemDelegate() +{ + m_zoomFactor = ZoomNormal; + m_imageHint = 128; +} + +TileItemDelegate::~TileItemDelegate() +{ +} + +void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyledItemDelegate::paint(painter,option,index); + + painter->save(); + + QFont font = QApplication::font(); + + //font.setBold(true); + //SubFont.setWeight(SubFont.weight()-2); + QFontMetrics fm(font); + + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + QString tileFileText = qvariant_cast(index.data(TileModel::TileFilenameRole)); + QString tileIdText = qvariant_cast(index.data(TileModel::TileIndexRole)); + + QSize tileSize = tile.size(); + + //QRect headerRect = option.rect; + QRect rect(option.rect); + //QRect tileRect(option.rect); + int textHeight = fm.height(); + int iconPosModX = PIXMAP_MARGIN + (tile.width() / 2); + int iconPosModY = (option.rect.height() - tile.height()) / 2; + + painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); + + + + //tileRect.setRight(tileSize.width()+30); + //tileRect.setTop(tileRect.top()+5); + //headerRect.setLeft(tileRect.right()); + //subheaderRect.setLeft(tileRect.right()); + //headerRect.setTop(headerRect.top()+5); + //headerRect.setBottom(headerRect.top()+fm.height()); + + //subheaderRect.setTop(headerRect.bottom()+2); + + //painter->drawPixmap(targetrect, pixmap, sourcerect) + + //painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); + //painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); + + //painter->setFont(font); + //painter->drawText(headerRect,headerText); + + + //painter->setFont(SubFont); + //painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); + + painter->restore(); +} + +QSize TileItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + QSize tileSize = tile.size(); + QFont font = QApplication::font(); + QFontMetrics fm(font); + + return(QSize(tileSize.width()+(2*PIXMAP_MARGIN), tileSize.height()+fm.height()+(2*PIXMAP_MARGIN))); +} + +TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() +{ + return m_zoomFactor; +} + +void TileItemDelegate::setZoomFactor(TileItemDelegate::TZoomFactor zoomFactor) +{ + m_zoomFactor = zoomFactor; +} + +// SLOTS + +void TileItemDelegate::currentTab(int index) +{ + if(index == 1) + { + nlinfo("switching delegate to 1 or 256"); + m_imageHint = 256; + } + else + { + nlinfo("switching delegate to 0,2,3 or 128"); + m_imageHint = 128; + } } \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 1aaa055f0..ceae137cc 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -1,42 +1,42 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "tilebank_loader.h" - -#include "tile_model.h" -#include "nel/misc/file.h" - -TileBankLoader::TileBankLoader() -{ -} - -TileBankLoader::~TileBankLoader() -{ -} - -bool TileBankLoader::load( const char *filename, TileModel *model ) -{ - NLMISC::CIFile file; - if( !file.open( filename, false ) ) - return false; - - model->serial( file ); - - file.close(); - - return true; -} +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "tilebank_loader.h" + +#include "tile_model.h" +#include "nel/misc/file.h" + +TileBankLoader::TileBankLoader() +{ +} + +TileBankLoader::~TileBankLoader() +{ +} + +bool TileBankLoader::load( const char *filename, TileModel *model ) +{ + NLMISC::CIFile file; + if( !file.open( filename, false ) ) + return false; + + model->serial( file ); + + file.close(); + + return true; +} diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h index 643cab67f..6f41234ba 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.h +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -1,35 +1,35 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef TILEBANK_LOADER_H -#define TILEBANK_LOADER_H - -class TileModel; - -class TileBankLoader -{ -public: - TileBankLoader(); - ~TileBankLoader(); - - bool load( const char *filename, TileModel *model ); - -private: -}; - - -#endif - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILEBANK_LOADER_H +#define TILEBANK_LOADER_H + +class TileModel; + +class TileBankLoader +{ +public: + TileBankLoader(); + ~TileBankLoader(); + + bool load( const char *filename, TileModel *model ); + +private: +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 3f087c979..85c96ee94 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -1,48 +1,48 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "tilebank_saver.h" -#include "tile_model.h" -#include "tile_item.h" - -#include "nel/3d/tile_bank.h" -#include "nel/misc/file.h" - -TileBankSaver::TileBankSaver() -{ -} - -TileBankSaver::~TileBankSaver() -{ -} - -bool TileBankSaver::save( const char *fileName, TileModel* model ) -{ - // Save to file - NLMISC::COFile f; - bool b = f.open( fileName, false, false, false ); - if( !b ) - return false; - - model->serial( f ); - - f.flush(); - f.close(); - - return true; -} - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "tilebank_saver.h" +#include "tile_model.h" +#include "tile_item.h" + +#include "nel/3d/tile_bank.h" +#include "nel/misc/file.h" + +TileBankSaver::TileBankSaver() +{ +} + +TileBankSaver::~TileBankSaver() +{ +} + +bool TileBankSaver::save( const char *fileName, TileModel* model ) +{ + // Save to file + NLMISC::COFile f; + bool b = f.open( fileName, false, false, false ); + if( !b ) + return false; + + model->serial( f ); + + f.flush(); + f.close(); + + return true; +} + diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index 0f8983157..ba9c3c7fd 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -1,39 +1,39 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef TILEBANK_SAVER_H -#define TILEBANK_SAVER_H - -#include -#include - -class TileModel; - -class TileBankSaver -{ -public: - TileBankSaver(); - ~TileBankSaver(); - - bool save( const char *filename, TileModel* model ); - -private: - -}; - -#endif - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TILEBANK_SAVER_H +#define TILEBANK_SAVER_H + +#include +#include + +class TileModel; + +class TileBankSaver +{ +public: + TileBankSaver(); + ~TileBankSaver(); + + bool save( const char *filename, TileModel* model ); + +private: + +}; + +#endif + diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 99b0b200c..06e6f98b4 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -1,472 +1,472 @@ -// Ryzom Core Studio - Translation Manager Plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "translation_manager_constants.h" -#include "uxt_editor.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "nel/misc/diff_tool.h" -#include "nel/misc/i18n.h" - -namespace -{ - -QString getLang( const QString &fn ) -{ - QString lang = fn; - int idx = lang.lastIndexOf( '/' ); - if( idx == -1 ) - return ""; - - lang = lang.mid( idx + 1 ); - idx = lang.lastIndexOf( '.' ); - if( idx == -1 ) - return ""; - - lang = lang.left( idx ); - return lang; -} - -} - -namespace TranslationManager -{ - -void markItemTranslated( QTableWidgetItem *item ) -{ - item->setBackground( QColor::fromRgb( 126, 247, 134 ) ); -} - -void markItemUntranslated( QTableWidgetItem *item ) -{ - item->setBackground( QColor::fromRgb( 247, 126, 126 ) ); -} - -class UXTEditorPvt -{ -public: - - UXTEditorPvt() - { - t = new QTableWidget(); - loadedFromWK = false; - } - - QTableWidget *t; - std::vector< STRING_MANAGER::TStringInfo > infos; - bool loadedFromWK; -}; - - -UXTEditor::UXTEditor( QMdiArea *parent ) : -CEditor( parent ) -{ - editor_type = Constants::ED_UXT; - setAttribute( Qt::WA_DeleteOnClose ); - - d_ptr = new UXTEditorPvt(); - - blockTableSignals( false ); -} - -UXTEditor::~UXTEditor() -{ - delete d_ptr; - d_ptr = NULL; -} - -void UXTEditor::open( QString filename ) -{ - std::vector< STRING_MANAGER::TStringInfo > &infos = d_ptr->infos; - QString lang = getLang( filename ); - - infos.clear(); - STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, false ); - - if( d_ptr->infos.size() == 0 ) - { - // The work file cannot be found, cannot proceed - if( filename.endsWith( "wk.uxt" ) ) - { - QMessageBox::critical( this, - tr( "Error opening file.." ), - tr( "There was an error opening wk.uxt" ) ); - return; - } - - int l = filename.lastIndexOf( "/" ); - if( l == -1 ) - return; - - QString fn = filename.left( l ); - fn += "/wk.uxt"; - - // The work file cannot be found, cannot proceed - STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); - if( d_ptr->infos.size() == 0 ) - { - QMessageBox::critical( this, - tr( "Error opening Uxt file" ), - tr( "Neither the specified file nor wk.uxt could be opened." ) ); - return; - } - - d_ptr->loadedFromWK = true; - } - - blockTableSignals( true ); - - d_ptr->t->clear(); - d_ptr->t->setColumnCount( 2 ); - d_ptr->t->setRowCount( infos.size() ); - - setHeaderText( "Id", lang.toUpper() + " Text" ); - - int i = 0; - - std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = infos.begin(); - while( itr != infos.end() ) - { - const STRING_MANAGER::TStringInfo &info = *itr; - - QTableWidgetItem *name = new QTableWidgetItem( info.Identifier.c_str() ); - QTableWidgetItem *text1 = new QTableWidgetItem( info.Text.toUtf8().c_str() ); - - d_ptr->t->setItem( i, 0, name ); - d_ptr->t->setItem( i, 1, text1 ); - - if( ( info.HashValue != 0 ) && !d_ptr->loadedFromWK ) - { - markItemTranslated( name ); - markItemTranslated( text1 ); - } - else - { - markItemUntranslated( name ); - markItemUntranslated( text1 ); - } - - ++itr; - i++; - } - - d_ptr->t->resizeColumnsToContents(); - - blockTableSignals( false ); - - setWidget( d_ptr->t ); - - current_file = filename; - setWindowTitle( filename + "[*]" ); - setWindowFilePath( filename ); -} - -void UXTEditor::save() -{ - saveAs( current_file ); -} - -void UXTEditor::saveAs( QString filename ) -{ - QFile f( filename ); - if( !f.open( QIODevice::WriteOnly ) ) - return; - - QTextStream out( &f ); - - int idx = 0; - std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); - while( itr != d_ptr->infos.end() ) - { - uint64 hash = 0; - - // If text2 is not empty we can assume the string was translated, so we store with the correct hash - // If text2 is empty, it wasn't translated so we can just use the old hash. - // Additionally, if the strings were loaded from the wk.uxt file, we use a hash of 0 so we know it was not translated - if( itr->Text2.empty() ) - { - if( d_ptr->loadedFromWK ) - hash = 0; - else - hash = itr->HashValue; - } - else - { - hash = NLMISC::CI18N::makeHash( itr->Text2 ); - } - - QString hashLine = "// HASH_VALUE "; - hashLine += QString( NLMISC::CI18N::hashToString( hash ).c_str() ).toUpper(); - hashLine += "\r\n"; - - QString idxLine = "// INDEX "; - idxLine += QString::number( idx ); - idxLine += "\r\n"; - - - QString trLine = ""; - trLine += itr->Identifier.c_str(); - trLine += "\t"; - trLine += "["; - - if( itr->Text2.empty() ) - trLine += itr->Text.toUtf8().c_str(); - else - trLine += itr->Text2.toUtf8().c_str(); - - trLine += "]"; - trLine += "\r\n"; - - QString newLine = "\r\n"; - - out << hashLine; - out << idxLine; - out << trLine; - out << newLine; - - ++itr; - idx++; - } - - f.close(); - - setWindowModified( false ); -} - -void UXTEditor::activateWindow() -{ - showMaximized(); -} - - -void UXTEditor::insertRow() -{ - blockTableSignals( true ); - - d_ptr->infos.push_back( STRING_MANAGER::TStringInfo() ); - d_ptr->t->setRowCount( d_ptr->t->rowCount() + 1 ); - int row = d_ptr->t->rowCount() - 1; - - QTableWidgetItem *item1 = new QTableWidgetItem(); - QTableWidgetItem *item2 = new QTableWidgetItem(); - d_ptr->t->setItem( row, 0, item1 ); - d_ptr->t->setItem( row, 1, item2 ); - - markRowUntranslated( row ); - - setWindowModified( true ); - - blockTableSignals( false ); -} - - -void UXTEditor::deleteRow() -{ - int r = d_ptr->t->currentRow(); - if( r < 0 ) - return; - - int answer = QMessageBox::question( this, - tr( "Deleting a row" ), - tr( "Are you sure you want to delete this row?" ), - QMessageBox::Yes, - QMessageBox::Cancel ); - if( QMessageBox::Yes != answer ) - return; - - std::vector< STRING_MANAGER::TStringInfo >::iterator itr = d_ptr->infos.begin(); - itr += r; - d_ptr->infos.erase( itr ); - - d_ptr->t->removeRow( r ); - - setWindowModified( true ); -} - -void UXTEditor::closeEvent( QCloseEvent *e ) -{ - if( isWindowModified() ) - { - int reply = QMessageBox::question( this, - tr( "Table changed" ), - tr( "The table has changed. Would you like to save your changes?" ), - QMessageBox::Yes, - QMessageBox::No - ); - - if( reply == QMessageBox::Yes ) - save(); - - } - - e->accept(); - close(); -} - -void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) -{ - QMenu *menu = new QMenu( this ); - QAction *insertAction = new QAction( "Insert row", menu ); - QAction *deleteAction = new QAction( "Delete row", menu ); - QAction *markAction = new QAction( "Mark translated", menu ); - QAction *unmarkAction = new QAction( "Mark not-translated", menu ); - QAction *saveAction = new QAction( "Save", menu ); - QAction *saveAsAction = new QAction( "Save as..", menu ); - - connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); - connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); - connect( markAction, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) ); - connect( unmarkAction, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) ); - connect( saveAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveClicked() ) ); - connect( saveAsAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAsClicked() ) ); - - menu->addAction( insertAction ); - menu->addAction( deleteAction ); - menu->addAction( markAction ); - menu->addAction( unmarkAction ); - menu->addAction( saveAction ); - menu->addAction( saveAsAction ); - menu->exec( e->globalPos() ); -} - -void UXTEditor::onCellChanged( int row, int column ) -{ - QTableWidgetItem *item = d_ptr->t->item( row, column ); - STRING_MANAGER::TStringInfo &info = d_ptr->infos[ row ]; - - if( column == 0 ) - info.Identifier = item->text().toUtf8().constData(); - else - if( column == 1 ) - info.Text2 = item->text().toUtf8().constData(); - - setWindowModified( true ); - - markRowTranslated( row ); -} - -void UXTEditor::markTranslated() -{ - int r = d_ptr->t->currentRow(); - if( r < 0 ) - return; - - STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; - if( !info.Text2.empty() ) - return; - - info.Text2 = info.Text; - - setWindowModified( true ); - - markRowTranslated( r ); -} - -void UXTEditor::markUntranslated() -{ - int r = d_ptr->t->currentRow(); - if( r < 0 ) - return; - - STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; - - info.Text2.clear(); - info.HashValue = 0; - - setWindowModified( true ); - - markRowUntranslated( r ); -} - -void UXTEditor::onSaveClicked() -{ - save(); -} - -void UXTEditor::onSaveAsClicked() -{ - QString path = current_file; - int idx = path.lastIndexOf( '/' ); - if( idx < 0 ) - path = ""; - else - path = path.left( idx + 1 ); - - QString file = QFileDialog::getSaveFileName( this, - tr( "Save Uxt as.." ), - path, - tr( "Uxt files ( *.uxt)" ) ); - - if( file.isEmpty() ) - return; - - saveAs( file ); -} - -void UXTEditor::setHeaderText( const QString &id, const QString &text ) -{ - QTableWidgetItem *h1 = new QTableWidgetItem( id ); - QTableWidgetItem *h2 = new QTableWidgetItem( text ); - h1->setTextAlignment( Qt::AlignLeft ); - h2->setTextAlignment( Qt::AlignLeft ); - d_ptr->t->setHorizontalHeaderItem( 0, h1 ); - d_ptr->t->setHorizontalHeaderItem( 1, h2 ); -} - -void UXTEditor::blockTableSignals( bool block ) -{ - if( block ) - disconnect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); - else - connect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); -} - -void UXTEditor::markRowTranslated( int row ) -{ - blockTableSignals( true ); - - QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); - QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); - markItemTranslated( item1 ); - markItemTranslated( item2 ); - - blockTableSignals( false ); -} - -void UXTEditor::markRowUntranslated( int row ) -{ - blockTableSignals( true ); - - QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); - QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); - markItemUntranslated( item1 ); - markItemUntranslated( item2 ); - - blockTableSignals( false ); -} - -} +// Ryzom Core Studio - Translation Manager Plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "translation_manager_constants.h" +#include "uxt_editor.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "nel/misc/diff_tool.h" +#include "nel/misc/i18n.h" + +namespace +{ + +QString getLang( const QString &fn ) +{ + QString lang = fn; + int idx = lang.lastIndexOf( '/' ); + if( idx == -1 ) + return ""; + + lang = lang.mid( idx + 1 ); + idx = lang.lastIndexOf( '.' ); + if( idx == -1 ) + return ""; + + lang = lang.left( idx ); + return lang; +} + +} + +namespace TranslationManager +{ + +void markItemTranslated( QTableWidgetItem *item ) +{ + item->setBackground( QColor::fromRgb( 126, 247, 134 ) ); +} + +void markItemUntranslated( QTableWidgetItem *item ) +{ + item->setBackground( QColor::fromRgb( 247, 126, 126 ) ); +} + +class UXTEditorPvt +{ +public: + + UXTEditorPvt() + { + t = new QTableWidget(); + loadedFromWK = false; + } + + QTableWidget *t; + std::vector< STRING_MANAGER::TStringInfo > infos; + bool loadedFromWK; +}; + + +UXTEditor::UXTEditor( QMdiArea *parent ) : +CEditor( parent ) +{ + editor_type = Constants::ED_UXT; + setAttribute( Qt::WA_DeleteOnClose ); + + d_ptr = new UXTEditorPvt(); + + blockTableSignals( false ); +} + +UXTEditor::~UXTEditor() +{ + delete d_ptr; + d_ptr = NULL; +} + +void UXTEditor::open( QString filename ) +{ + std::vector< STRING_MANAGER::TStringInfo > &infos = d_ptr->infos; + QString lang = getLang( filename ); + + infos.clear(); + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, false ); + + if( d_ptr->infos.size() == 0 ) + { + // The work file cannot be found, cannot proceed + if( filename.endsWith( "wk.uxt" ) ) + { + QMessageBox::critical( this, + tr( "Error opening file.." ), + tr( "There was an error opening wk.uxt" ) ); + return; + } + + int l = filename.lastIndexOf( "/" ); + if( l == -1 ) + return; + + QString fn = filename.left( l ); + fn += "/wk.uxt"; + + // The work file cannot be found, cannot proceed + STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); + if( d_ptr->infos.size() == 0 ) + { + QMessageBox::critical( this, + tr( "Error opening Uxt file" ), + tr( "Neither the specified file nor wk.uxt could be opened." ) ); + return; + } + + d_ptr->loadedFromWK = true; + } + + blockTableSignals( true ); + + d_ptr->t->clear(); + d_ptr->t->setColumnCount( 2 ); + d_ptr->t->setRowCount( infos.size() ); + + setHeaderText( "Id", lang.toUpper() + " Text" ); + + int i = 0; + + std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = infos.begin(); + while( itr != infos.end() ) + { + const STRING_MANAGER::TStringInfo &info = *itr; + + QTableWidgetItem *name = new QTableWidgetItem( info.Identifier.c_str() ); + QTableWidgetItem *text1 = new QTableWidgetItem( info.Text.toUtf8().c_str() ); + + d_ptr->t->setItem( i, 0, name ); + d_ptr->t->setItem( i, 1, text1 ); + + if( ( info.HashValue != 0 ) && !d_ptr->loadedFromWK ) + { + markItemTranslated( name ); + markItemTranslated( text1 ); + } + else + { + markItemUntranslated( name ); + markItemUntranslated( text1 ); + } + + ++itr; + i++; + } + + d_ptr->t->resizeColumnsToContents(); + + blockTableSignals( false ); + + setWidget( d_ptr->t ); + + current_file = filename; + setWindowTitle( filename + "[*]" ); + setWindowFilePath( filename ); +} + +void UXTEditor::save() +{ + saveAs( current_file ); +} + +void UXTEditor::saveAs( QString filename ) +{ + QFile f( filename ); + if( !f.open( QIODevice::WriteOnly ) ) + return; + + QTextStream out( &f ); + + int idx = 0; + std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); + while( itr != d_ptr->infos.end() ) + { + uint64 hash = 0; + + // If text2 is not empty we can assume the string was translated, so we store with the correct hash + // If text2 is empty, it wasn't translated so we can just use the old hash. + // Additionally, if the strings were loaded from the wk.uxt file, we use a hash of 0 so we know it was not translated + if( itr->Text2.empty() ) + { + if( d_ptr->loadedFromWK ) + hash = 0; + else + hash = itr->HashValue; + } + else + { + hash = NLMISC::CI18N::makeHash( itr->Text2 ); + } + + QString hashLine = "// HASH_VALUE "; + hashLine += QString( NLMISC::CI18N::hashToString( hash ).c_str() ).toUpper(); + hashLine += "\r\n"; + + QString idxLine = "// INDEX "; + idxLine += QString::number( idx ); + idxLine += "\r\n"; + + + QString trLine = ""; + trLine += itr->Identifier.c_str(); + trLine += "\t"; + trLine += "["; + + if( itr->Text2.empty() ) + trLine += itr->Text.toUtf8().c_str(); + else + trLine += itr->Text2.toUtf8().c_str(); + + trLine += "]"; + trLine += "\r\n"; + + QString newLine = "\r\n"; + + out << hashLine; + out << idxLine; + out << trLine; + out << newLine; + + ++itr; + idx++; + } + + f.close(); + + setWindowModified( false ); +} + +void UXTEditor::activateWindow() +{ + showMaximized(); +} + + +void UXTEditor::insertRow() +{ + blockTableSignals( true ); + + d_ptr->infos.push_back( STRING_MANAGER::TStringInfo() ); + d_ptr->t->setRowCount( d_ptr->t->rowCount() + 1 ); + int row = d_ptr->t->rowCount() - 1; + + QTableWidgetItem *item1 = new QTableWidgetItem(); + QTableWidgetItem *item2 = new QTableWidgetItem(); + d_ptr->t->setItem( row, 0, item1 ); + d_ptr->t->setItem( row, 1, item2 ); + + markRowUntranslated( row ); + + setWindowModified( true ); + + blockTableSignals( false ); +} + + +void UXTEditor::deleteRow() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + int answer = QMessageBox::question( this, + tr( "Deleting a row" ), + tr( "Are you sure you want to delete this row?" ), + QMessageBox::Yes, + QMessageBox::Cancel ); + if( QMessageBox::Yes != answer ) + return; + + std::vector< STRING_MANAGER::TStringInfo >::iterator itr = d_ptr->infos.begin(); + itr += r; + d_ptr->infos.erase( itr ); + + d_ptr->t->removeRow( r ); + + setWindowModified( true ); +} + +void UXTEditor::closeEvent( QCloseEvent *e ) +{ + if( isWindowModified() ) + { + int reply = QMessageBox::question( this, + tr( "Table changed" ), + tr( "The table has changed. Would you like to save your changes?" ), + QMessageBox::Yes, + QMessageBox::No + ); + + if( reply == QMessageBox::Yes ) + save(); + + } + + e->accept(); + close(); +} + +void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) +{ + QMenu *menu = new QMenu( this ); + QAction *insertAction = new QAction( "Insert row", menu ); + QAction *deleteAction = new QAction( "Delete row", menu ); + QAction *markAction = new QAction( "Mark translated", menu ); + QAction *unmarkAction = new QAction( "Mark not-translated", menu ); + QAction *saveAction = new QAction( "Save", menu ); + QAction *saveAsAction = new QAction( "Save as..", menu ); + + connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); + connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + connect( markAction, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) ); + connect( unmarkAction, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) ); + connect( saveAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveClicked() ) ); + connect( saveAsAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAsClicked() ) ); + + menu->addAction( insertAction ); + menu->addAction( deleteAction ); + menu->addAction( markAction ); + menu->addAction( unmarkAction ); + menu->addAction( saveAction ); + menu->addAction( saveAsAction ); + menu->exec( e->globalPos() ); +} + +void UXTEditor::onCellChanged( int row, int column ) +{ + QTableWidgetItem *item = d_ptr->t->item( row, column ); + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ row ]; + + if( column == 0 ) + info.Identifier = item->text().toUtf8().constData(); + else + if( column == 1 ) + info.Text2 = item->text().toUtf8().constData(); + + setWindowModified( true ); + + markRowTranslated( row ); +} + +void UXTEditor::markTranslated() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; + if( !info.Text2.empty() ) + return; + + info.Text2 = info.Text; + + setWindowModified( true ); + + markRowTranslated( r ); +} + +void UXTEditor::markUntranslated() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; + + info.Text2.clear(); + info.HashValue = 0; + + setWindowModified( true ); + + markRowUntranslated( r ); +} + +void UXTEditor::onSaveClicked() +{ + save(); +} + +void UXTEditor::onSaveAsClicked() +{ + QString path = current_file; + int idx = path.lastIndexOf( '/' ); + if( idx < 0 ) + path = ""; + else + path = path.left( idx + 1 ); + + QString file = QFileDialog::getSaveFileName( this, + tr( "Save Uxt as.." ), + path, + tr( "Uxt files ( *.uxt)" ) ); + + if( file.isEmpty() ) + return; + + saveAs( file ); +} + +void UXTEditor::setHeaderText( const QString &id, const QString &text ) +{ + QTableWidgetItem *h1 = new QTableWidgetItem( id ); + QTableWidgetItem *h2 = new QTableWidgetItem( text ); + h1->setTextAlignment( Qt::AlignLeft ); + h2->setTextAlignment( Qt::AlignLeft ); + d_ptr->t->setHorizontalHeaderItem( 0, h1 ); + d_ptr->t->setHorizontalHeaderItem( 1, h2 ); +} + +void UXTEditor::blockTableSignals( bool block ) +{ + if( block ) + disconnect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); + else + connect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); +} + +void UXTEditor::markRowTranslated( int row ) +{ + blockTableSignals( true ); + + QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); + QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); + markItemTranslated( item1 ); + markItemTranslated( item2 ); + + blockTableSignals( false ); +} + +void UXTEditor::markRowUntranslated( int row ) +{ + blockTableSignals( true ); + + QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); + QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); + markItemUntranslated( item1 ); + markItemUntranslated( item2 ); + + blockTableSignals( false ); +} + +} From 46aa5cef294bad0df41535330e1e288ab50a8ad1 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 19 Aug 2014 15:42:42 +0200 Subject: [PATCH 281/282] EOL --- .../src/plugins/georges_editor/actions.cpp | 100 ++--- .../plugins/georges_editor/browser_ctrl.cpp | 130 +++--- .../georges_editor/browser_ctrl_pvt.cpp | 394 +++++++++--------- .../georges_editor/georgesform_model.h | 6 +- .../tile_editor/tile_editor_plugin.cpp | 154 +++---- 5 files changed, 392 insertions(+), 392 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/actions.cpp b/code/studio/src/plugins/georges_editor/actions.cpp index c96bca95c..08196f79b 100644 --- a/code/studio/src/plugins/georges_editor/actions.cpp +++ b/code/studio/src/plugins/georges_editor/actions.cpp @@ -31,7 +31,7 @@ #include #include -namespace GeorgesQt +namespace GeorgesQt { CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, CFormItem *item, const QVariant &value, QUndoCommand *parent) @@ -41,63 +41,63 @@ namespace GeorgesQt } void CUndoFormArrayRenameCommand::redo() - { + { update(true); } void CUndoFormArrayRenameCommand::undo() - { + { update(false); } void CUndoFormArrayRenameCommand::update(bool redo) - { - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *node; - NLGEORGES::UFormDfn::TEntryType type; - bool isArray; - bool vdfnArray; - NLGEORGES::CForm *form=static_cast(m_item->form()); - NLGEORGES::CFormElm *elm = static_cast(&form->Elements); - - nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); - if (node) - { - std::string tmpName; - node->getFormName(tmpName); - - NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); - - // In the redo stage save the old value, just in case. - if(redo) - { - // If the name of the element is empty then give it a nice default. - if(array->Elements[m_item->structId()].Name.empty()) - { - m_oldValue.append("#"); - m_oldValue.append(QString("%1").arg(m_item->structId())); - } - else - { - m_oldValue = QString(array->Elements[m_item->structId()].Name.c_str()); - } - } - - QString value; - if(redo) - value = m_newValue; - else - value = m_oldValue; - - - array->Elements[m_item->structId()].Name = value.toAscii().data(); - m_item->setName(value.toAscii().data()); - - m_model->emitDataChanged(m_model->index(m_item->row(), 0, m_item)); + { + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool vdfnArray; + NLGEORGES::CForm *form=static_cast(m_item->form()); + NLGEORGES::CFormElm *elm = static_cast(&form->Elements); + + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + if (node) + { + std::string tmpName; + node->getFormName(tmpName); + + NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); + + // In the redo stage save the old value, just in case. + if(redo) + { + // If the name of the element is empty then give it a nice default. + if(array->Elements[m_item->structId()].Name.empty()) + { + m_oldValue.append("#"); + m_oldValue.append(QString("%1").arg(m_item->structId())); + } + else + { + m_oldValue = QString(array->Elements[m_item->structId()].Name.c_str()); + } + } + + QString value; + if(redo) + value = m_newValue; + else + value = m_oldValue; + + + array->Elements[m_item->structId()].Name = value.toAscii().data(); + m_item->setName(value.toAscii().data()); + + m_model->emitDataChanged(m_model->index(m_item->row(), 0, m_item)); } } } \ No newline at end of file diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index aa431b45c..5c4d2a499 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -1,31 +1,31 @@ -#include "browser_ctrl.h" -#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" -#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" -#include - -#include "nel/georges/form.h" - -#include "formitem.h" - -#include "browser_ctrl_pvt.h" - -BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : -QObject( browser ) -{ - m_pvt = new BrowserCtrlPvt(); - m_pvt->setBrowser( browser ); - - connect( m_pvt, SIGNAL( arrayResized( const QString&, int ) ), this, SLOT( onArrayResized( const QString&, int ) ) ); - connect( m_pvt, SIGNAL( modified() ), this, SLOT( onModified() ) ); -} - -BrowserCtrl::~BrowserCtrl() -{ - delete m_pvt; - m_pvt = NULL; -} - -void BrowserCtrl::clicked( const QModelIndex &idx ) +#include "browser_ctrl.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +#include "nel/georges/form.h" + +#include "formitem.h" + +#include "browser_ctrl_pvt.h" + +BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : +QObject( browser ) +{ + m_pvt = new BrowserCtrlPvt(); + m_pvt->setBrowser( browser ); + + connect( m_pvt, SIGNAL( arrayResized( const QString&, int ) ), this, SLOT( onArrayResized( const QString&, int ) ) ); + connect( m_pvt, SIGNAL( modified() ), this, SLOT( onModified() ) ); +} + +BrowserCtrl::~BrowserCtrl() +{ + delete m_pvt; + m_pvt = NULL; +} + +void BrowserCtrl::clicked( const QModelIndex &idx ) { disableMgrConnections(); m_pvt->clear(); @@ -42,40 +42,40 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) if( !b || ( node == NULL ) ) return; - m_pvt->setupNode( node ); - - enableMgrConnections(); - -} - -void BrowserCtrl::onValueChanged( QtProperty *p, const QVariant &value ) -{ - m_pvt->onValueChanged( p, value ); -} - -void BrowserCtrl::onArrayResized( const QString &name, int size ) -{ - Q_EMIT arrayResized( name, size ); -} - -void BrowserCtrl::onModified() -{ - Q_EMIT modified(); -} - -void BrowserCtrl::enableMgrConnections() -{ - QtVariantPropertyManager *mgr = m_pvt->manager(); - - connect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), - this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); -} - -void BrowserCtrl::disableMgrConnections() -{ - QtVariantPropertyManager *mgr = m_pvt->manager(); - - disconnect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), - this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); -} - + m_pvt->setupNode( node ); + + enableMgrConnections(); + +} + +void BrowserCtrl::onValueChanged( QtProperty *p, const QVariant &value ) +{ + m_pvt->onValueChanged( p, value ); +} + +void BrowserCtrl::onArrayResized( const QString &name, int size ) +{ + Q_EMIT arrayResized( name, size ); +} + +void BrowserCtrl::onModified() +{ + Q_EMIT modified(); +} + +void BrowserCtrl::enableMgrConnections() +{ + QtVariantPropertyManager *mgr = m_pvt->manager(); + + connect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), + this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); +} + +void BrowserCtrl::disableMgrConnections() +{ + QtVariantPropertyManager *mgr = m_pvt->manager(); + + disconnect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), + this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); +} + diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp index 0e22765da..d5026ef71 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -1,205 +1,205 @@ -#include "browser_ctrl_pvt.h" -#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" -#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" -#include - -namespace -{ - - QVariant::Type getValueType( const NLGEORGES::UType *typ ) - { - QVariant::Type t = QVariant::String; - - NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; - if( typ != NULL ) - ttyp = typ->getType(); - - switch( ttyp ) - { - case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; - case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; - case NLGEORGES::UType::Double: t = QVariant::Double; break; - case NLGEORGES::UType::Color: t = QVariant::Color; break; - case NLGEORGES::UType::String: t = QVariant::String; break; - } - - return t; - } - -} - - -BrowserCtrlPvt::BrowserCtrlPvt( QObject *parent ) : -QObject( parent ) -{ - mgr = new QtVariantPropertyManager(); - factory = new QtVariantEditorFactory(); - m_currentNode = NULL; - m_rootNode = NULL; -} - -BrowserCtrlPvt::~BrowserCtrlPvt() -{ - delete mgr; - mgr = NULL; - delete factory; - factory = NULL; - m_browser = NULL; -} - -void BrowserCtrlPvt::setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) -{ +#include "browser_ctrl_pvt.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +namespace +{ + + QVariant::Type getValueType( const NLGEORGES::UType *typ ) + { + QVariant::Type t = QVariant::String; + + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + switch( ttyp ) + { + case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; + case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; + case NLGEORGES::UType::Double: t = QVariant::Double; break; + case NLGEORGES::UType::Color: t = QVariant::Color; break; + case NLGEORGES::UType::String: t = QVariant::String; break; + } + + return t; + } + +} + + +BrowserCtrlPvt::BrowserCtrlPvt( QObject *parent ) : +QObject( parent ) +{ + mgr = new QtVariantPropertyManager(); + factory = new QtVariantEditorFactory(); + m_currentNode = NULL; + m_rootNode = NULL; +} + +BrowserCtrlPvt::~BrowserCtrlPvt() +{ + delete mgr; + mgr = NULL; + delete factory; + factory = NULL; + m_browser = NULL; +} + +void BrowserCtrlPvt::setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) +{ QString key = elm.Name.c_str(); QString value = ""; QVariant::Type t = QVariant::String; if( elm.Element != NULL ) { - t = getValueType( elm.Element->getType() ); - - std::string formName; - elm.Element->getFormName( formName, NULL ); - - std::string v; - m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); - value = v.c_str(); - } - - QtVariantProperty *p = mgr->addProperty( t, key ); - p->setValue( value ); - m_browser->addProperty( p ); -} - -void BrowserCtrlPvt::setupArray( NLGEORGES::UFormElm *node ) -{ - NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); - uint size = 0; - arr->getArraySize( size ); - - QString key = QObject::tr( "Array size" ); - QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); - p->setValue( size ); - m_browser->addProperty( p ); - -} - -void BrowserCtrlPvt::setupStruct( NLGEORGES::UFormElm *node ) -{ - NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - + t = getValueType( elm.Element->getType() ); + + std::string formName; + elm.Element->getFormName( formName, NULL ); + + std::string v; + m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); + value = v.c_str(); + } + + QtVariantProperty *p = mgr->addProperty( t, key ); + p->setValue( value ); + m_browser->addProperty( p ); +} + +void BrowserCtrlPvt::setupArray( NLGEORGES::UFormElm *node ) +{ + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); + uint size = 0; + arr->getArraySize( size ); + + QString key = QObject::tr( "Array size" ); + QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); + p->setValue( size ); + m_browser->addProperty( p ); + +} + +void BrowserCtrlPvt::setupStruct( NLGEORGES::UFormElm *node ) +{ + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + for( int i = 0; i < st->Elements.size(); i++ ) { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) - continue; - - if( elm.Element == NULL ) - { - NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); - if( entry.getArrayFlag() ) - continue; - } - - setupAtom( elm ); - } -} - -void BrowserCtrlPvt::setupNode( NLGEORGES::UFormElm *node ) -{ - if( node->isStruct() ) - setupStruct( node ); - else - if( node->isArray() ) - setupArray( node ); - else - return; - - m_currentNode = node; - m_browser->setFactoryForManager( mgr, factory ); -} - -void BrowserCtrlPvt::clear() -{ - m_browser->clear(); - m_currentNode = NULL; -} - - -void BrowserCtrlPvt::onStructValueChanged( QtProperty *p, const QVariant &value ) -{ - std::string k = p->propertyName().toUtf8().constData(); - std::string v = value.toString().toUtf8().constData(); - - bool created = false; - m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); - - Q_EMIT modified(); -} - -void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) -{ - NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); - std::string formName; - arr->getFormName( formName, NULL ); - - int newSize = value.toInt(); - int oldSize = arr->Elements.size(); - - if( newSize == oldSize ) - return; - - if( newSize < oldSize ) - { - for( int i = newSize; i < oldSize; i++ ) - { - delete arr->Elements[ i ].Element; - } - - arr->Elements.resize( newSize ); - } - else - { - arr->Elements.resize( newSize ); - - - const NLGEORGES::CFormDfn *parentDfn; - const NLGEORGES::CFormDfn *nodeDfn; - uint indexDfn; - const NLGEORGES::CType *type; - NLGEORGES::UFormDfn::TEntryType entryType; - NLGEORGES::CFormElm *node; - bool created; - bool isArray; - - QString idx; - - for( int i = oldSize; i < newSize; i++ ) - { - idx.clear(); - idx += "["; - idx += QString::number( i ); - idx += "]"; - - bool b; - b = arr->createNodeByName( idx.toUtf8().constData(), &parentDfn, indexDfn, &nodeDfn, &type, &node, entryType, isArray, created ); - } - } - - QString name = formName.c_str(); - Q_EMIT arrayResized( name, newSize ); - Q_EMIT modified(); -} - -void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) -{ - if( m_currentNode == NULL ) - return; - - if( m_currentNode->isStruct() ) - onStructValueChanged( p, value ); - else - if( m_currentNode->isArray() ) - onArrayValueChanged( p, value ); -} - - + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + + if( elm.Element == NULL ) + { + NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); + if( entry.getArrayFlag() ) + continue; + } + + setupAtom( elm ); + } +} + +void BrowserCtrlPvt::setupNode( NLGEORGES::UFormElm *node ) +{ + if( node->isStruct() ) + setupStruct( node ); + else + if( node->isArray() ) + setupArray( node ); + else + return; + + m_currentNode = node; + m_browser->setFactoryForManager( mgr, factory ); +} + +void BrowserCtrlPvt::clear() +{ + m_browser->clear(); + m_currentNode = NULL; +} + + +void BrowserCtrlPvt::onStructValueChanged( QtProperty *p, const QVariant &value ) +{ + std::string k = p->propertyName().toUtf8().constData(); + std::string v = value.toString().toUtf8().constData(); + + bool created = false; + m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); + + Q_EMIT modified(); +} + +void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) +{ + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); + std::string formName; + arr->getFormName( formName, NULL ); + + int newSize = value.toInt(); + int oldSize = arr->Elements.size(); + + if( newSize == oldSize ) + return; + + if( newSize < oldSize ) + { + for( int i = newSize; i < oldSize; i++ ) + { + delete arr->Elements[ i ].Element; + } + + arr->Elements.resize( newSize ); + } + else + { + arr->Elements.resize( newSize ); + + + const NLGEORGES::CFormDfn *parentDfn; + const NLGEORGES::CFormDfn *nodeDfn; + uint indexDfn; + const NLGEORGES::CType *type; + NLGEORGES::UFormDfn::TEntryType entryType; + NLGEORGES::CFormElm *node; + bool created; + bool isArray; + + QString idx; + + for( int i = oldSize; i < newSize; i++ ) + { + idx.clear(); + idx += "["; + idx += QString::number( i ); + idx += "]"; + + bool b; + b = arr->createNodeByName( idx.toUtf8().constData(), &parentDfn, indexDfn, &nodeDfn, &type, &node, entryType, isArray, created ); + } + } + + QString name = formName.c_str(); + Q_EMIT arrayResized( name, newSize ); + Q_EMIT modified(); +} + +void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) +{ + if( m_currentNode == NULL ) + return; + + if( m_currentNode->isStruct() ) + onStructValueChanged( p, value ); + else + if( m_currentNode->isArray() ) + onArrayValueChanged( p, value ); +} + + diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.h b/code/studio/src/plugins/georges_editor/georgesform_model.h index 4ca91398b..d133b5ec6 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.h +++ b/code/studio/src/plugins/georges_editor/georgesform_model.h @@ -70,9 +70,9 @@ namespace GeorgesQt CFormItem *addArray(CFormItem *parent, NLGEORGES::CFormElmArray *array, NLGEORGES::CFormDfn *rootDfn, const char *name, uint structId, const char *formName, uint slot); - void emitDataChanged(const QModelIndex &index) - { - Q_EMIT dataChanged(index, index); + void emitDataChanged(const QModelIndex &index) + { + Q_EMIT dataChanged(index, index); } void arrayResized( const QString &name, int size ); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp index 33a617cc1..b10eb6074 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp @@ -1,78 +1,78 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "tile_editor_plugin.h" -#include "tile_editor_main_window.h" -#include "../core/icore.h" -#include "../core/menu_manager.h" -#include "../core/core_constants.h" - -// Qt includes -#include -#include -#include -#include -#include -#include - -// NeL includes -#include "nel/misc/debug.h" - -using namespace TileEditorPluginQt; - -TileEditorPlugin::~TileEditorPlugin() -{ - Q_FOREACH(QObject *obj, m_autoReleaseObjects) - { - m_plugMan->removeObject(obj); - } - qDeleteAll(m_autoReleaseObjects); - m_autoReleaseObjects.clear(); - +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "tile_editor_plugin.h" +#include "tile_editor_main_window.h" +#include "../core/icore.h" +#include "../core/menu_manager.h" +#include "../core/core_constants.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +// NeL includes +#include "nel/misc/debug.h" + +using namespace TileEditorPluginQt; + +TileEditorPlugin::~TileEditorPlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); + delete m_LibContext; - m_LibContext = NULL; -} - -bool TileEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) -{ - Q_UNUSED(errorString); - m_plugMan = pluginManager; - addAutoReleasedObject(new TileEditorContext()); - return true; -} - -void TileEditorPlugin::extensionsInitialized() -{ -} - -void TileEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) -{ -#ifdef NL_OS_WINDOWS - // Ensure that a context doesn't exist yet. - // This only applies to platforms without PIC, e.g. Windows. - nlassert(!NLMISC::INelContext::isContextInitialised()); -#endif // NL_OS_WINDOWS - m_LibContext = new NLMISC::CLibraryContext(*nelContext); -} - -void TileEditorPlugin::addAutoReleasedObject(QObject *obj) -{ - m_plugMan->addObject(obj); - m_autoReleaseObjects.prepend(obj); -} - -Q_EXPORT_PLUGIN(TileEditorPlugin) + m_LibContext = NULL; +} + +bool TileEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + addAutoReleasedObject(new TileEditorContext()); + return true; +} + +void TileEditorPlugin::extensionsInitialized() +{ +} + +void TileEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_LibContext = new NLMISC::CLibraryContext(*nelContext); +} + +void TileEditorPlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +Q_EXPORT_PLUGIN(TileEditorPlugin) From 573fb44088b259cbf7fc6eb6cb33814f85f6af0d Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 25 Aug 2014 14:56:29 +0200 Subject: [PATCH 282/282] Link group_wheel.cpp, ref #176 --- code/nel/src/gui/group_wheel.cpp | 2 ++ code/nel/src/gui/link_hack.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/code/nel/src/gui/group_wheel.cpp b/code/nel/src/gui/group_wheel.cpp index 6f4c96484..e242a98e7 100644 --- a/code/nel/src/gui/group_wheel.cpp +++ b/code/nel/src/gui/group_wheel.cpp @@ -24,6 +24,8 @@ NLMISC_REGISTER_OBJECT(CViewBase, CInterfaceGroupWheel, std::string, "group_whee namespace NLGUI { + void force_link_group_wheel_cpp() { } + // ***************************************************************************************************************** CInterfaceGroupWheel::CInterfaceGroupWheel(const TCtorParam ¶m) : CInterfaceGroup(param) { diff --git a/code/nel/src/gui/link_hack.cpp b/code/nel/src/gui/link_hack.cpp index 1492012e1..06a8c23e8 100644 --- a/code/nel/src/gui/link_hack.cpp +++ b/code/nel/src/gui/link_hack.cpp @@ -26,6 +26,7 @@ namespace NLGUI void ifexprufct_forcelink(); void force_link_dbgroup_select_number_cpp(); void force_link_dbgroup_combo_box_cpp(); + void force_link_group_wheel_cpp(); /// Necessary so the linker doesn't drop the code of these classes from the library void LinkHack() @@ -37,5 +38,6 @@ namespace NLGUI ifexprufct_forcelink(); force_link_dbgroup_select_number_cpp(); force_link_dbgroup_combo_box_cpp(); + force_link_group_wheel_cpp(); } } \ No newline at end of file