summaryrefslogtreecommitdiffstats
path: root/ktuberling
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitc90c389a8a8d9d8661e9772ec4144c5cf2039f23 (patch)
tree6d8391395bce9eaea4ad78958617edb20c6a7573 /ktuberling
downloadtdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.tar.gz
tdegames-c90c389a8a8d9d8661e9772ec4144c5cf2039f23.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'ktuberling')
-rw-r--r--ktuberling/Makefile.am38
-rw-r--r--ktuberling/TODO40
-rw-r--r--ktuberling/action.cpp20
-rw-r--r--ktuberling/action.h28
-rw-r--r--ktuberling/hi128-app-ktuberling.pngbin0 -> 23202 bytes
-rw-r--r--ktuberling/hi16-app-ktuberling.pngbin0 -> 938 bytes
-rw-r--r--ktuberling/hi22-app-ktuberling.pngbin0 -> 4254 bytes
-rw-r--r--ktuberling/hi32-app-ktuberling.pngbin0 -> 2761 bytes
-rw-r--r--ktuberling/hi48-app-ktuberling.pngbin0 -> 5398 bytes
-rw-r--r--ktuberling/hi64-app-ktuberling.pngbin0 -> 8366 bytes
-rw-r--r--ktuberling/ktuberling.desktop128
-rw-r--r--ktuberling/ktuberlingui.rc41
-rw-r--r--ktuberling/main.cpp60
-rw-r--r--ktuberling/museum/Makefile.am10
-rw-r--r--ktuberling/museum/businessman.tuberling28
-rw-r--r--ktuberling/museum/cool.tuberling8
-rw-r--r--ktuberling/museum/crazy.tuberling9
-rw-r--r--ktuberling/museum/cyclop.tuberling15
-rw-r--r--ktuberling/museum/dali.tuberling11
-rw-r--r--ktuberling/museum/einstein.tuberling10
-rw-r--r--ktuberling/museum/fly.tuberling8
-rw-r--r--ktuberling/museum/grandpa.tuberling9
-rw-r--r--ktuberling/museum/happy.tuberling13
-rw-r--r--ktuberling/museum/hippie.tuberling8
-rw-r--r--ktuberling/museum/idiot.tuberling10
-rw-r--r--ktuberling/museum/miss.tuberling11
-rw-r--r--ktuberling/museum/mouse.tuberling14
-rw-r--r--ktuberling/museum/picasso.tuberling10
-rw-r--r--ktuberling/museum/sea.tuberling18
-rw-r--r--ktuberling/museum/serious.tuberling13
-rw-r--r--ktuberling/pics/Makefile.am8
-rw-r--r--ktuberling/pics/aquarium-game.pngbin0 -> 179746 bytes
-rw-r--r--ktuberling/pics/aquarium-mask.pngbin0 -> 6150 bytes
-rw-r--r--ktuberling/pics/layout.i18n53
-rw-r--r--ktuberling/pics/layout.xml924
-rw-r--r--ktuberling/pics/penguin-game.pngbin0 -> 182537 bytes
-rw-r--r--ktuberling/pics/penguin-mask.pngbin0 -> 8016 bytes
-rw-r--r--ktuberling/pics/potato-game.pngbin0 -> 118385 bytes
-rw-r--r--ktuberling/pics/potato-mask.pngbin0 -> 11159 bytes
-rw-r--r--ktuberling/playground.cpp609
-rw-r--r--ktuberling/playground.h86
-rw-r--r--ktuberling/soundfactory.cpp148
-rw-r--r--ktuberling/soundfactory.h46
-rw-r--r--ktuberling/sounds/Makefile.am9
-rw-r--r--ktuberling/sounds/NO_TRANSLATIONS_HERE0
-rw-r--r--ktuberling/sounds/badge.wavbin0 -> 8908 bytes
-rw-r--r--ktuberling/sounds/bow.wavbin0 -> 6860 bytes
-rw-r--r--ktuberling/sounds/cigar.wavbin0 -> 10668 bytes
-rw-r--r--ktuberling/sounds/ear.wavbin0 -> 6732 bytes
-rw-r--r--ktuberling/sounds/earring.wavbin0 -> 8940 bytes
-rw-r--r--ktuberling/sounds/eye.wavbin0 -> 6156 bytes
-rw-r--r--ktuberling/sounds/eyebrow.wavbin0 -> 9708 bytes
-rw-r--r--ktuberling/sounds/hat.wavbin0 -> 7116 bytes
-rw-r--r--ktuberling/sounds/moustache.wavbin0 -> 13260 bytes
-rw-r--r--ktuberling/sounds/mouth.wavbin0 -> 7276 bytes
-rw-r--r--ktuberling/sounds/nose.wavbin0 -> 9068 bytes
-rw-r--r--ktuberling/sounds/spectacles.wavbin0 -> 11564 bytes
-rw-r--r--ktuberling/sounds/sunglasses.wavbin0 -> 13612 bytes
-rw-r--r--ktuberling/sounds/tuberling.wavbin0 -> 11212 bytes
-rw-r--r--ktuberling/sounds/watch.wavbin0 -> 8428 bytes
-rw-r--r--ktuberling/todraw.cpp90
-rw-r--r--ktuberling/todraw.h35
-rw-r--r--ktuberling/toplevel.cpp611
-rw-r--r--ktuberling/toplevel.h105
-rw-r--r--ktuberling/x-tuberling.desktop61
65 files changed, 3345 insertions, 0 deletions
diff --git a/ktuberling/Makefile.am b/ktuberling/Makefile.am
new file mode 100644
index 00000000..55ed363e
--- /dev/null
+++ b/ktuberling/Makefile.am
@@ -0,0 +1,38 @@
+# this 10 paths are KDE specific. Use them:
+# kde_htmldir Where your docs should go to. (contains lang subdirs)
+# kde_appsdir Where your application file (.desktop) should go to.
+# kde_icondir Where your icon should go to.
+# kde_sounddir Where system sounds should go to.
+# kde_datadir Where you install application data. (Use a subdir)
+# kde_locale Where translation files should go to.(contains lang subdirs)
+# kde_cgidir Where cgi-bin executables should go to.
+# kde_confdir Where config files should go to.
+# kde_mimedir Where mimetypes should go to.
+# kde_toolbardir Where general toolbar icons should go to.
+# kde_wallpaperdir Where general wallpapers should go to.
+
+INCLUDES= -I$(top_srcdir)/libkdegames $(all_includes)
+SUBDIRS = . museum sounds pics
+
+bin_PROGRAMS = ktuberling
+
+ktuberling_SOURCES = action.cpp main.cpp toplevel.cpp playground.cpp todraw.cpp soundfactory.cpp
+
+ktuberling_METASOURCES = AUTO
+ktuberling_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+ktuberling_LDADD = $(LIB_KDEGAMES) $(LIB_KFILE) -lkdeprint
+ktuberling_DEPENDENCIES = $(LIB_KDEGAMES_DEP)
+
+KDE_ICON = ktuberling
+
+xdg_apps_DATA = ktuberling.desktop
+
+mimetypeapplicationdata_DATA = x-tuberling.desktop
+mimetypeapplicationdatadir = $(kde_mimedir)/application
+
+appsrc_DATA = ktuberlingui.rc
+appsrcdir = $(kde_datadir)/ktuberling
+
+messages: rc.cpp
+ $(XGETTEXT) rc.cpp $(ktuberling_SOURCES) pics/layout.i18n -o $(podir)/ktuberling.pot
+
diff --git a/ktuberling/TODO b/ktuberling/TODO
new file mode 100644
index 00000000..9bc83a70
--- /dev/null
+++ b/ktuberling/TODO
@@ -0,0 +1,40 @@
+- Allow point and click instead of drag and drop (KDE bug #68779)
+
+- Better format for .tuberling files (object names instead of numbers, XML)
+
+- Split layout.xml in two parts : layout and sounds. The sounds.xml part would
+ be distributed in the ktuberling-sounds package
+
+- Draw a small hand when grabbing objects
+
+- Write title of tuberling last opened / saved on top of the window
+
+- Choose the current language accordingly to locale settings
+
+- Add a "man" page for KTuberling
+
+- See what's wrong with wide cursors on old Tektronix X terminals and if
+ there's a workaround (KDE bug #68786)
+
+============= Things for which I need help from other people : ================
+
+- More and better localized sounds (German, Spanish, etc)
+
+- More and better colour gameboards and objects (KDE bug #63211)
+ For example : Farm with animals
+ Criminal identification portrait
+ Clown with accessories
+ Lizard
+ Dragon
+ Gogo (the animal)
+ Iguana (the animal)
+ Boy-Barbie
+ Girl-Barbie
+ Money (different kind of)
+ House
+ Dogs
+ Cats
+
+- Sounds in OGG Vorbis format (KDE bug #37251)
+
+- Text above, not below images (KDE bug #53402)
diff --git a/ktuberling/action.cpp b/ktuberling/action.cpp
new file mode 100644
index 00000000..a55deb04
--- /dev/null
+++ b/ktuberling/action.cpp
@@ -0,0 +1,20 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Action stored in the undo buffer
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+#include "action.h"
+
+// Constructor
+Action::Action
+ (const ToDraw *drawn1, int zOrder1,
+ const ToDraw *drawn2, int zOrder2)
+{
+ if (drawn1) drawnBefore = *drawn1;
+ zOrderBefore = zOrder1;
+
+ if (drawn2) drawnAfter = *drawn2;
+ zOrderAfter = zOrder2;
+}
+
diff --git a/ktuberling/action.h b/ktuberling/action.h
new file mode 100644
index 00000000..8fdfeb8e
--- /dev/null
+++ b/ktuberling/action.h
@@ -0,0 +1,28 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Action stored in the undo buffer
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+
+#ifndef _ACTION_H_
+#define _ACTION_H_
+
+#include "todraw.h"
+
+class Action
+{
+ public:
+ Action(const ToDraw *, int,
+ const ToDraw *, int);
+ inline const ToDraw &DrawnBefore() const {return drawnBefore;}
+ inline int ZOrderBefore() const {return zOrderBefore;}
+ inline const ToDraw &DrawnAfter() const {return drawnAfter;}
+ inline int ZOrderAfter() const {return zOrderAfter;}
+
+ private:
+ ToDraw drawnBefore, drawnAfter;
+ int zOrderBefore, zOrderAfter;
+};
+
+#endif
diff --git a/ktuberling/hi128-app-ktuberling.png b/ktuberling/hi128-app-ktuberling.png
new file mode 100644
index 00000000..1d679c0f
--- /dev/null
+++ b/ktuberling/hi128-app-ktuberling.png
Binary files differ
diff --git a/ktuberling/hi16-app-ktuberling.png b/ktuberling/hi16-app-ktuberling.png
new file mode 100644
index 00000000..16759609
--- /dev/null
+++ b/ktuberling/hi16-app-ktuberling.png
Binary files differ
diff --git a/ktuberling/hi22-app-ktuberling.png b/ktuberling/hi22-app-ktuberling.png
new file mode 100644
index 00000000..865bce26
--- /dev/null
+++ b/ktuberling/hi22-app-ktuberling.png
Binary files differ
diff --git a/ktuberling/hi32-app-ktuberling.png b/ktuberling/hi32-app-ktuberling.png
new file mode 100644
index 00000000..08dc6156
--- /dev/null
+++ b/ktuberling/hi32-app-ktuberling.png
Binary files differ
diff --git a/ktuberling/hi48-app-ktuberling.png b/ktuberling/hi48-app-ktuberling.png
new file mode 100644
index 00000000..140fab6e
--- /dev/null
+++ b/ktuberling/hi48-app-ktuberling.png
Binary files differ
diff --git a/ktuberling/hi64-app-ktuberling.png b/ktuberling/hi64-app-ktuberling.png
new file mode 100644
index 00000000..abe60536
--- /dev/null
+++ b/ktuberling/hi64-app-ktuberling.png
Binary files differ
diff --git a/ktuberling/ktuberling.desktop b/ktuberling/ktuberling.desktop
new file mode 100644
index 00000000..b6f8e709
--- /dev/null
+++ b/ktuberling/ktuberling.desktop
@@ -0,0 +1,128 @@
+[Desktop Entry]
+Exec=ktuberling %i %m -caption "%c" %u
+Name=Potato Guy
+Name[af]=Aartappel Man
+Name[ar]=لعبة رجل البطاطا
+Name[az]=Kartof Adam
+Name[be]=Бульбяш
+Name[bn]=পটেটো গাই
+Name[br]=Paotr ar patatez
+Name[cs]=Bramborový chlapík
+Name[da]=Kartoffelfyren
+Name[de]=Kartoffelknülch
+Name[eo]=Terpomulo
+Name[es]=Papá Patata
+Name[et]=Kartulimees
+Name[eu]=Patata jauna
+Name[fi]=Perunamies
+Name[fo]=Eplamaður
+Name[fr]=Monsieur patate
+Name[gl]=O Nacho Pataca
+Name[he]=מר תפוח אדמה
+Name[hi]=पोटैटो गाइ
+Name[hr]=Krumpirko
+Name[hu]=Krumpli bácsi
+Name[is]=Kartöflukall
+Name[it]=Uomo patata
+Name[ja]=福笑い
+Name[km]=មនុស្ស​ដំឡូង
+Name[lt]=Bulvinis Vyrukas
+Name[lv]=Kartupeļu vīrs
+Name[mk]=Компирко
+Name[nb]=Potetmannen
+Name[nds]=Kantüffelfips
+Name[ne]=पोटेटो गाई
+Name[nl]=Aardappelmannetje
+Name[nn]=Potetfyren
+Name[pa]=ਆਲੂ ਮੁੰਡਾ
+Name[pl]=Ziemniaczany facet
+Name[pt]=Homem Batata
+Name[pt_BR]=Homem-Batata
+Name[ro]=Domnul Cartof
+Name[se]=Buđetolmmái
+Name[sk]=Zemiakový chlapec
+Name[sl]=Krompirček
+Name[sv]=Potatismannen
+Name[ta]=உருளைகிழங்கு வீரர்
+Name[tg]=Писараки Картошкагин
+Name[th]=นายมันฝรั่ง - K
+Name[tr]=Patates Adam
+Name[uk]=Картопляний хлопець
+Name[ven]=Munna wa dabula
+Name[wa]=Monsieu Crompire
+Name[xh]=Umfana wetapile
+Name[zh_CN]=土豆小子
+Name[zh_TW]=馬鈴薯小子
+Name[zu]=I-Potato Guy
+GenericName=Game for Children
+GenericName[af]=Speletjie vir Kinders
+GenericName[ar]=لعبة للأطفال
+GenericName[be]=Гульня для дзяцей
+GenericName[bg]=Игра за деца
+GenericName[bn]=পোলাপানের খেলা
+GenericName[bs]=Igra za djecu
+GenericName[ca]=Joc per a la canalla
+GenericName[cs]=Hra pro děti
+GenericName[cy]=Gêm i Blant
+GenericName[da]=Spil for børn
+GenericName[de]=Spiel für Kinder
+GenericName[el]=Παιχνίδι για παιδιά
+GenericName[eo]=Infanludo
+GenericName[es]=Juego para niños
+GenericName[et]=Lastemäng
+GenericName[eu]=Umeentzako jokoa
+GenericName[fa]=بازی برای بچه‌‌‌ها
+GenericName[fi]=Peli lapsille
+GenericName[fo]=Barnaspæl
+GenericName[fr]=Jeu pour les enfants
+GenericName[ga]=Cluiche do phaistí
+GenericName[gl]=Xogo para Nenos
+GenericName[he]=משחק לילדים
+GenericName[hi]=बच्चों के लिए खेल
+GenericName[hr]=Igra za djecu
+GenericName[hu]=Gyermekjáték
+GenericName[is]=Leikur fyrir börn
+GenericName[it]=Gioco per i bambini
+GenericName[ja]=子供用ゲーム
+GenericName[km]=ល្បែង​សម្រាប់​ក្មេង
+GenericName[ko]=어린이를 위한 그림 게임
+GenericName[lt]=Žaidimas vaikams
+GenericName[lv]=Spēle bērniem
+GenericName[mk]=Игра за деца
+GenericName[nb]=Barnespill
+GenericName[nds]=Speel för Kinners
+GenericName[ne]=केटाकेटिका लागि खेल
+GenericName[nl]=Spel voor kinderen
+GenericName[nn]=Barnespel
+GenericName[pa]=ਜਵਾਕਾਂ ਲਈ ਖੇਡ
+GenericName[pl]=Gra dla dzieci
+GenericName[pt]=Jogo para Crianças
+GenericName[pt_BR]=Jogo para Crianças
+GenericName[ro]=Joc pentru copii
+GenericName[ru]=Клубень
+GenericName[se]=Mánáidspeallu
+GenericName[sk]=Hra pre deti
+GenericName[sl]=Igra za otroke
+GenericName[sr]=Игра за децу
+GenericName[sr@Latn]=Igra za decu
+GenericName[sv]=Spel för barn
+GenericName[ta]=குழந்தைகளுக்கான விளையாட்டு
+GenericName[tg]=Бозӣ барои бачаҳо
+GenericName[th]=เกมสำหรับเด็ก
+GenericName[tr]=Çocuklar için bir oyun
+GenericName[uk]=Гра для дітей
+GenericName[ven]=Mutambo wa Vhana
+GenericName[vi]=Game cho trẻ em
+GenericName[wa]=Djeu po ls efants
+GenericName[xh]=Umdlalo wabantwana
+GenericName[zh_CN]=孩子们的游戏
+GenericName[zh_TW]=小孩專屬遊戲
+GenericName[zu]=Umdlalo wabantwana
+Type=Application
+DocPath=ktuberling/index.html
+Terminal=false
+Icon=ktuberling
+MimeType=application/x-tuberling;
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Game;X-KDE-KidsGame;
diff --git a/ktuberling/ktuberlingui.rc b/ktuberling/ktuberlingui.rc
new file mode 100644
index 00000000..75bd3105
--- /dev/null
+++ b/ktuberling/ktuberlingui.rc
@@ -0,0 +1,41 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="ktuberling" version="1">
+<MenuBar>
+ <Menu name="game"><text>&amp;Game</text>
+ <Action name="game_save_picture" append="save_merge"/>
+ </Menu>
+ <Menu name="playground"><text>&amp;Playground</text>
+ <Action name="playground_potato_guy"/>
+ <Action name="playground_penguin"/>
+ <Action name="playground_aquarium"/>
+ </Menu>
+ <Menu name="speech"><text>&amp;Speech</text>
+ <Action name="speech_no_sound"/>
+ <Separator/>
+ <Action name="speech_danish"/>
+ <Action name="speech_german"/>
+ <Action name="speech_english"/>
+ <Action name="speech_spanish"/>
+ <Action name="speech_finnish"/>
+ <Action name="speech_french"/>
+ <Action name="speech_italian"/>
+ <Action name="speech_lowsaxon"/>
+ <Action name="speech_dutch"/>
+ <Action name="speech_portuguese"/>
+ <Action name="speech_romanian"/>
+ <Action name="speech_slovak"/>
+ <Action name="speech_slovenian"/>
+ <Action name="speech_swedish"/>
+ <Action name="speech_serbian"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text>
+ <Action name="game_new"/>
+ <Action name="game_load"/>
+ <Action name="game_save"/>
+ <Action name="game_print"/>
+ <Separator/>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+</ToolBar>
+</kpartgui>
diff --git a/ktuberling/main.cpp b/ktuberling/main.cpp
new file mode 100644
index 00000000..5e508e66
--- /dev/null
+++ b/ktuberling/main.cpp
@@ -0,0 +1,60 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Main program
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+#include <kapplication.h>
+#include <kimageio.h>
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+
+#include "toplevel.h"
+
+static KCmdLineOptions options[] = {
+ { "+<tuberling-file>", I18N_NOOP("Potato to open"), 0 },
+ KCmdLineLastOption
+};
+
+
+
+static const char description[] = I18N_NOOP("Potato game for kids");
+static const char text[] = I18N_NOOP("A program by Eric Bischoff <e.bischoff@noos.fr>\nand John Calhoun.\n\nThis program is dedicated to my daughter Sunniva.");
+
+static const char version[] = "0.4";
+
+// Main function
+int main(int argc, char *argv[])
+{
+
+ KAboutData aboutData( "ktuberling", I18N_NOOP("KTuberling"),
+ version, description, KAboutData::License_GPL,
+ "(c) 1999-2003, The KTuberling Developers", text);
+ aboutData.addAuthor("Eric Bischoff", I18N_NOOP("Developer"), "e.bischoff@noos.fr");
+ aboutData.addAuthor("John Calhoun", I18N_NOOP("Original concept and artwork"));
+ aboutData.addCredit("Agnieszka Czajkowska", I18N_NOOP("New artwork"), "agnieszka@imagegalaxy.de");
+ aboutData.addCredit("Bas Willems", I18N_NOOP("New artwork"), "cybersurfer@euronet.nl");
+ aboutData.addCredit("Roger Larsson", I18N_NOOP("Sounds tuning"), "roger.larsson@norran.net");
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KApplication app;
+ KGlobal::locale()->insertCatalogue("libkdegames");
+ KImageIO::registerFormats();
+
+ TopLevel *toplevel=0;
+
+ if (app.isRestored())
+ RESTORE(TopLevel)
+ else {
+ toplevel = new TopLevel();
+ toplevel->show();
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if (args->count())
+ toplevel->open(args->url(0));
+ args->clear();
+ }
+
+ return app.exec();
+}
diff --git a/ktuberling/museum/Makefile.am b/ktuberling/museum/Makefile.am
new file mode 100644
index 00000000..50c11c10
--- /dev/null
+++ b/ktuberling/museum/Makefile.am
@@ -0,0 +1,10 @@
+
+# add here all files
+ktuberling_DATA = businessman.tuberling cool.tuberling cyclop.tuberling dali.tuberling \
+ einstein.tuberling fly.tuberling grandpa.tuberling happy.tuberling \
+ idiot.tuberling miss.tuberling mouse.tuberling picasso.tuberling \
+ serious.tuberling \
+ crazy.tuberling hippie.tuberling \
+ sea.tuberling
+
+ktuberlingdir = $(kde_datadir)/ktuberling/museum
diff --git a/ktuberling/museum/businessman.tuberling b/ktuberling/museum/businessman.tuberling
new file mode 100644
index 00000000..fc26c97d
--- /dev/null
+++ b/ktuberling/museum/businessman.tuberling
@@ -0,0 +1,28 @@
+0
+22 103 62 152 124
+12 77 110 124 139
+35 3 67 31 88
+36 126 228 160 249
+3 129 44 170 76
+3 87 45 128 77
+13 57 11 104 40
+17 165 19 212 48
+17 158 15 205 44
+17 151 12 198 41
+17 146 9 193 38
+17 140 7 187 36
+17 134 5 181 34
+13 62 7 109 36
+13 67 5 114 34
+13 73 5 120 34
+13 79 4 126 33
+13 84 3 131 32
+17 129 3 176 32
+19 137 25 184 54
+12 70 25 117 54
+25 57 58 84 98
+26 176 58 203 98
+39 106 148 150 180
+16 131 111 178 140
+32 94 126 160 156
+37 90 46 170 78
diff --git a/ktuberling/museum/cool.tuberling b/ktuberling/museum/cool.tuberling
new file mode 100644
index 00000000..72ff5ec7
--- /dev/null
+++ b/ktuberling/museum/cool.tuberling
@@ -0,0 +1,8 @@
+0
+28 83 92 149 122
+35 66 95 94 116
+33 78 7 142 37
+3 75 41 116 73
+3 109 46 150 78
+24 150 54 177 94
+42 201 144 219 176
diff --git a/ktuberling/museum/crazy.tuberling b/ktuberling/museum/crazy.tuberling
new file mode 100644
index 00000000..f32c07eb
--- /dev/null
+++ b/ktuberling/museum/crazy.tuberling
@@ -0,0 +1,9 @@
+1
+11 102 28 147 87
+17 92 -20 155 43
+6 88 101 128 132
+4 109 100 149 131
+18 82 117 160 147
+8 81 149 176 268
+12 131 227 186 265
+13 84 244 138 282
diff --git a/ktuberling/museum/cyclop.tuberling b/ktuberling/museum/cyclop.tuberling
new file mode 100644
index 00000000..fdf7ee89
--- /dev/null
+++ b/ktuberling/museum/cyclop.tuberling
@@ -0,0 +1,15 @@
+0
+0 109 44 150 76
+2 110 27 151 59
+32 94 149 160 179
+20 103 84 152 146
+23 58 63 84 103
+24 178 59 204 99
+17 112 19 159 48
+13 97 19 144 48
+17 175 55 222 84
+17 169 43 216 72
+17 158 29 205 58
+13 41 55 88 84
+13 43 45 90 74
+13 47 33 94 62
diff --git a/ktuberling/museum/dali.tuberling b/ktuberling/museum/dali.tuberling
new file mode 100644
index 00000000..6b423c01
--- /dev/null
+++ b/ktuberling/museum/dali.tuberling
@@ -0,0 +1,11 @@
+0
+26 166 42 193 82
+0 82 32 123 64
+0 118 30 159 62
+15 72 72 119 101
+19 123 73 170 102
+17 168 26 215 55
+29 -3 69 63 99
+20 6 11 55 73
+6 -10 -4 31 28
+9 31 -4 72 28
diff --git a/ktuberling/museum/einstein.tuberling b/ktuberling/museum/einstein.tuberling
new file mode 100644
index 00000000..9e276b4b
--- /dev/null
+++ b/ktuberling/museum/einstein.tuberling
@@ -0,0 +1,10 @@
+0
+13 76 12 123 41
+17 140 12 187 41
+30 103 178 169 208
+34 103 163 167 185
+20 108 114 157 176
+4 143 77 184 109
+1 79 80 120 112
+24 179 80 206 120
+23 52 80 79 120
diff --git a/ktuberling/museum/fly.tuberling b/ktuberling/museum/fly.tuberling
new file mode 100644
index 00000000..56e2ab82
--- /dev/null
+++ b/ktuberling/museum/fly.tuberling
@@ -0,0 +1,8 @@
+0
+14 42 87 89 116
+14 44 49 91 78
+21 62 25 111 87
+18 173 88 220 117
+18 171 44 218 73
+21 153 20 202 82
+22 103 151 152 213
diff --git a/ktuberling/museum/grandpa.tuberling b/ktuberling/museum/grandpa.tuberling
new file mode 100644
index 00000000..81e15200
--- /dev/null
+++ b/ktuberling/museum/grandpa.tuberling
@@ -0,0 +1,9 @@
+0
+27 96 104 162 134
+34 99 93 163 115
+5 92 68 133 100
+5 130 70 171 102
+38 93 65 168 97
+35 4 67 32 88
+34 104 12 168 34
+33 87 4 151 34
diff --git a/ktuberling/museum/happy.tuberling b/ktuberling/museum/happy.tuberling
new file mode 100644
index 00000000..265633fe
--- /dev/null
+++ b/ktuberling/museum/happy.tuberling
@@ -0,0 +1,13 @@
+0
+21 107 76 156 138
+24 174 25 201 65
+23 59 28 86 68
+2 88 59 129 91
+2 141 59 182 91
+5 92 66 133 98
+5 137 64 178 96
+39 109 152 153 184
+13 76 49 123 78
+17 141 49 188 78
+27 99 130 165 160
+33 0 67 64 97
diff --git a/ktuberling/museum/hippie.tuberling b/ktuberling/museum/hippie.tuberling
new file mode 100644
index 00000000..bc0d761f
--- /dev/null
+++ b/ktuberling/museum/hippie.tuberling
@@ -0,0 +1,8 @@
+1
+10 75 43 173 102
+14 64 176 197 206
+15 61 168 194 198
+20 85 82 194 112
+1 89 106 129 136
+3 118 107 158 137
+18 152 107 230 137
diff --git a/ktuberling/museum/idiot.tuberling b/ktuberling/museum/idiot.tuberling
new file mode 100644
index 00000000..9be66e14
--- /dev/null
+++ b/ktuberling/museum/idiot.tuberling
@@ -0,0 +1,10 @@
+0
+30 97 169 163 199
+22 105 62 154 124
+34 98 8 162 30
+21 4 40 53 102
+3 146 67 187 99
+0 74 67 115 99
+24 178 75 205 115
+23 52 77 79 117
+35 42 94 70 115
diff --git a/ktuberling/museum/miss.tuberling b/ktuberling/museum/miss.tuberling
new file mode 100644
index 00000000..339b236a
--- /dev/null
+++ b/ktuberling/museum/miss.tuberling
@@ -0,0 +1,11 @@
+0
+6 76 45 117 77
+9 145 47 186 79
+12 70 27 117 56
+16 144 24 191 53
+39 109 181 153 213
+42 203 145 221 177
+29 93 83 159 113
+40 68 79 83 111
+40 176 82 191 114
+36 10 113 44 134
diff --git a/ktuberling/museum/mouse.tuberling b/ktuberling/museum/mouse.tuberling
new file mode 100644
index 00000000..3264c291
--- /dev/null
+++ b/ktuberling/museum/mouse.tuberling
@@ -0,0 +1,14 @@
+0
+13 76 49 123 78
+17 141 49 188 78
+41 95 58 122 90
+41 146 57 173 89
+19 96 113 143 142
+15 117 112 164 141
+5 112 84 153 116
+39 111 144 155 176
+5 88 59 129 91
+5 139 58 180 90
+24 175 28 201 68
+23 61 28 87 68
+15 56 189 103 218
diff --git a/ktuberling/museum/picasso.tuberling b/ktuberling/museum/picasso.tuberling
new file mode 100644
index 00000000..56940ba9
--- /dev/null
+++ b/ktuberling/museum/picasso.tuberling
@@ -0,0 +1,10 @@
+0
+29 102 58 168 88
+24 179 92 206 132
+35 143 125 171 146
+41 104 91 131 123
+4 91 132 132 164
+23 66 145 93 185
+1 80 12 121 44
+13 89 39 136 68
+20 145 51 194 113
diff --git a/ktuberling/museum/sea.tuberling b/ktuberling/museum/sea.tuberling
new file mode 100644
index 00000000..eea3ef51
--- /dev/null
+++ b/ktuberling/museum/sea.tuberling
@@ -0,0 +1,18 @@
+2
+11 -2 90 54 165
+1 119 27 182 74
+9 173 125 226 190
+9 197 130 250 195
+7 248 121 283 175
+1 96 23 159 70
+1 74 -1 137 46
+1 55 20 118 67
+1 70 40 133 87
+4 115 245 205 307
+1 48 -10 111 37
+1 39 -1 102 46
+1 28 44 91 91
+1 -31 6 32 53
+1 72 13 135 60
+1 104 5 167 52
+1 177 -2 240 45
diff --git a/ktuberling/museum/serious.tuberling b/ktuberling/museum/serious.tuberling
new file mode 100644
index 00000000..4b5ffff3
--- /dev/null
+++ b/ktuberling/museum/serious.tuberling
@@ -0,0 +1,13 @@
+0
+23 75 74 102 114
+24 168 74 195 114
+32 104 154 170 184
+33 87 7 151 37
+41 135 185 162 217
+7 96 81 137 113
+10 133 83 174 115
+20 110 89 159 151
+14 85 66 132 95
+18 141 65 188 94
+35 5 72 33 93
+42 203 144 221 176
diff --git a/ktuberling/pics/Makefile.am b/ktuberling/pics/Makefile.am
new file mode 100644
index 00000000..5e70846a
--- /dev/null
+++ b/ktuberling/pics/Makefile.am
@@ -0,0 +1,8 @@
+
+# add here all files
+pics_DATA = penguin-game.png penguin-mask.png \
+ potato-game.png potato-mask.png \
+ aquarium-game.png aquarium-mask.png \
+ layout.xml
+
+picsdir = $(kde_datadir)/ktuberling/pics
diff --git a/ktuberling/pics/aquarium-game.png b/ktuberling/pics/aquarium-game.png
new file mode 100644
index 00000000..089bdf7c
--- /dev/null
+++ b/ktuberling/pics/aquarium-game.png
Binary files differ
diff --git a/ktuberling/pics/aquarium-mask.png b/ktuberling/pics/aquarium-mask.png
new file mode 100644
index 00000000..929d11be
--- /dev/null
+++ b/ktuberling/pics/aquarium-mask.png
Binary files differ
diff --git a/ktuberling/pics/layout.i18n b/ktuberling/pics/layout.i18n
new file mode 100644
index 00000000..373203cb
--- /dev/null
+++ b/ktuberling/pics/layout.i18n
@@ -0,0 +1,53 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ List of strings in layout.xml that are translatable
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+i18n("Potato &Guy");
+
+i18n("Eyes");
+i18n("Eyebrows");
+i18n("Noses");
+i18n("Ears");
+i18n("Mouths");
+i18n("Goodies");
+
+i18n("&Penguin");
+
+i18n("Eyes");
+i18n("Tie");
+i18n("Hair");
+i18n("Necklaces");
+i18n("Hats");
+i18n("Glasses");
+i18n("Scarf");
+
+i18n("&Aquarium");
+
+i18n("Fishes");
+i18n("Others");
+
+i18n("&Danish");
+i18n("&German");
+i18n("&English");
+i18n("Sp&anish");
+i18n("Fi&nnish");
+i18n("&French");
+i18n("&Italian");
+i18n("Low Sa&xon");
+i18n("D&utch");
+i18n("&Portuguese");
+i18n("&Romanian");
+i18n("&Slovak");
+i18n("S&lovenian");
+i18n("S&wedish");
+i18n("Ser&bian");
+
+i18n("NOTE_TO_THE_TRANSLATORS",
+"The translators have the opportunity to translate the\n"
+"sounds spoken in the game.\n"
+"See the technical reference section in ktuberling's\n"
+"documentation for more information on how to do that.\n"
+"(translate this message as \"DONE\" when you have translated\n"
+"the sounds; otherwise leave it untranslated as a reminder)");
diff --git a/ktuberling/pics/layout.xml b/ktuberling/pics/layout.xml
new file mode 100644
index 00000000..c5b02fb8
--- /dev/null
+++ b/ktuberling/pics/layout.xml
@@ -0,0 +1,924 @@
+<!--
+ KDE Tuberling
+ Description of the playgrounds
+ mailto:e.bischoff@noos.fr
+
+ Modify this file if you want to add new playgrounds, new sounds,
+ or modify existing ones. If you do that, don't forget to update:
+ - layout.i18n (strings that might be translated)
+ - ktuberlingui.rc (actions associated with menu items).
+-->
+
+<ktuberling>
+
+ <playground gameboard="potato-game.png" masks="potato-mask.png">
+
+ <menuitem action="playground_potato_guy">
+ <label>Potato &amp;Guy</label>
+ </menuitem>
+
+ <editablearea>
+ <position left=" 0" top=" 0" right="240" bottom="320" />
+ <sound ref="tuberling" />
+ </editablearea>
+
+ <category>
+ <position left="241" top="101" right="413" bottom="115" />
+ <label>Eyes</label>
+ </category>
+
+ <category>
+ <position left="415" top="123" right="511" bottom="137" />
+ <label>Eyebrows</label>
+ </category>
+
+ <category>
+ <position left="241" top="179" right="394" bottom="193" />
+ <label>Noses</label>
+ </category>
+
+ <category>
+ <position left="395" top="179" right="511" bottom="193" />
+ <label>Ears</label>
+ </category>
+
+ <category>
+ <position left="241" top="259" right="445" bottom="273" />
+ <label>Mouths</label>
+ </category>
+
+ <category>
+ <position left="241" top="307" right="511" bottom="321" />
+ <label>Goodies</label>
+ </category>
+
+ <object>
+ <position left="242" top=" 0" right="283" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="242" top=" 34" right="283" bottom=" 66" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="242" top=" 68" right="283" bottom="100" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="285" top=" 0" right="326" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="285" top=" 34" right="326" bottom=" 66" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="285" top=" 68" right="326" bottom="100" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="328" top=" 0" right="369" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="328" top=" 34" right="369" bottom=" 66" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="328" top=" 68" right="369" bottom="100" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="371" top=" 0" right="412" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="371" top=" 34" right="412" bottom=" 66" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="371" top=" 68" right="412" bottom="100" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="415" top=" 0" right="462" bottom=" 29" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="415" top=" 31" right="462" bottom=" 60" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="415" top=" 62" right="462" bottom=" 91" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="415" top=" 93" right="462" bottom="122" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="464" top=" 0" right="511" bottom=" 29" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="464" top=" 31" right="511" bottom=" 60" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="464" top=" 62" right="511" bottom=" 91" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="464" top=" 93" right="511" bottom="122" />
+ <sound ref="eyebrow" />
+ </object>
+
+ <object>
+ <position left="242" top="116" right="291" bottom="178" />
+ <sound ref="nose" />
+ </object>
+
+ <object>
+ <position left="293" top="116" right="342" bottom="178" />
+ <sound ref="nose" />
+ </object>
+
+ <object>
+ <position left="344" top="116" right="393" bottom="178" />
+ <sound ref="nose" />
+ </object>
+
+ <object>
+ <position left="397" top="138" right="423" bottom="178" />
+ <sound ref="ear" />
+ </object>
+
+ <object>
+ <position left="426" top="138" right="452" bottom="178" />
+ <sound ref="ear" />
+ </object>
+
+ <object>
+ <position left="455" top="138" right="481" bottom="178" />
+ <sound ref="ear" />
+ </object>
+
+ <object>
+ <position left="484" top="138" right="510" bottom="178" />
+ <sound ref="ear" />
+ </object>
+
+ <object>
+ <position left="242" top="195" right="308" bottom="225" />
+ <sound ref="mouth" />
+ </object>
+
+ <object>
+ <position left="242" top="227" right="308" bottom="257" />
+ <sound ref="mouth" />
+ </object>
+
+ <object>
+ <position left="310" top="195" right="376" bottom="225" />
+ <sound ref="mouth" />
+ </object>
+
+ <object>
+ <position left="310" top="227" right="376" bottom="257" />
+ <sound ref="mouth" />
+ </object>
+
+ <object>
+ <position left="378" top="195" right="444" bottom="225" />
+ <sound ref="mouth" />
+ </object>
+
+ <object>
+ <position left="378" top="227" right="444" bottom="257" />
+ <sound ref="mouth" />
+ </object>
+
+ <object>
+ <position left="447" top="195" right="511" bottom="225" />
+ <sound ref="hat" />
+ </object>
+
+ <object>
+ <position left="447" top="227" right="511" bottom="249" />
+ <sound ref="moustache" />
+ </object>
+
+ <object>
+ <position left="447" top="251" right="475" bottom="272" />
+ <sound ref="cigar" />
+ </object>
+
+ <object>
+ <position left="477" top="251" right="511" bottom="272" />
+ <sound ref="bow" />
+ </object>
+
+ <object>
+ <position left="242" top="274" right="322" bottom="306" />
+ <sound ref="sunglasses" />
+ </object>
+
+ <object>
+ <position left="324" top="274" right="399" bottom="306" />
+ <sound ref="spectacles" />
+ </object>
+
+ <object>
+ <position left="401" top="274" right="445" bottom="306" />
+ <sound ref="bow" />
+ </object>
+
+ <object>
+ <position left="447" top="274" right="462" bottom="306" />
+ <sound ref="earring" />
+ </object>
+
+ <object>
+ <position left="464" top="274" right="491" bottom="306" />
+ <sound ref="badge" />
+ </object>
+
+ <object>
+ <position left="493" top="274" right="511" bottom="306" />
+ <sound ref="watch" />
+ </object>
+
+ </playground>
+
+ <playground gameboard="penguin-game.png" masks="penguin-mask.png">
+
+ <menuitem action="playground_penguin">
+ <label>&amp;Penguin</label>
+ </menuitem>
+
+ <editablearea>
+ <position left=" 0" top=" 0" right="240" bottom="320" />
+ <sound ref="penguin" />
+ </editablearea>
+
+ <category>
+ <position left="241" top=" 66" right="413" bottom=" 80" />
+ <label>Eyes</label>
+ </category>
+
+ <category>
+ <position left="415" top="123" right="511" bottom="137" />
+ <label>Tie</label>
+ </category>
+
+ <category>
+ <position left="241" top="180" right="511" bottom="194" />
+ <label>Hair</label>
+ </category>
+
+ <category>
+ <position left="241" top="259" right="377" bottom="273" />
+ <label>Necklaces</label>
+ </category>
+
+ <category>
+ <position left="379" top="259" right="511" bottom="273" />
+ <label>Hats</label>
+ </category>
+
+ <category>
+ <position left="241" top="307" right="400" bottom="321" />
+ <label>Glasses</label>
+ </category>
+
+ <category>
+ <position left="402" top="307" right="511" bottom="321" />
+ <label>Scarf</label>
+ </category>
+
+ <object>
+ <position left="243" top=" 1" right="283" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="243" top=" 35" right="283" bottom=" 65" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="286" top=" 1" right="326" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="286" top=" 35" right="326" bottom=" 65" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="329" top=" 1" right="369" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="329" top=" 35" right="369" bottom=" 65" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="372" top=" 1" right="412" bottom=" 32" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="372" top=" 35" right="412" bottom=" 65" />
+ <sound ref="eye" />
+ </object>
+
+ <object>
+ <position left="416" top=" 1" right="511" bottom="120" />
+ <sound ref="tie" />
+ </object>
+
+ <object>
+ <position left="244" top=" 81" right="390" bottom="116" />
+ <sound ref="hat" />
+ </object>
+
+ <object>
+ <position left="243" top="119" right="341" bottom="178" />
+ <sound ref="hair" />
+ </object>
+
+ <object>
+ <position left="345" top="119" right="390" bottom="178" />
+ <sound ref="hair" />
+ </object>
+
+ <object>
+ <position left="397" top="140" right="452" bottom="178" />
+ <sound ref="horn" />
+ </object>
+
+ <object>
+ <position left="455" top="140" right="509" bottom="178" />
+ <sound ref="horn" />
+ </object>
+
+ <object>
+ <position left="243" top="195" right="376" bottom="225" />
+ <sound ref="necklace" />
+ </object>
+
+ <object>
+ <position left="243" top="228" right="376" bottom="258" />
+ <sound ref="necklace" />
+ </object>
+
+ <object>
+ <position left="379" top="195" right="444" bottom="258" />
+ <sound ref="hat" />
+ </object>
+
+ <object>
+ <position left="448" top="195" right="511" bottom="258" />
+ <sound ref="hat" />
+ </object>
+
+ <object>
+ <position left="244" top="275" right="322" bottom="305" />
+ <sound ref="spectacles" />
+ </object>
+
+ <object>
+ <position left="325" top="275" right="398" bottom="305" />
+ <sound ref="sunglasses" />
+ </object>
+
+ <object>
+ <position left="402" top="275" right="511" bottom="305" />
+ <sound ref="scarf" />
+ </object>
+
+ </playground>
+
+ <playground gameboard="aquarium-game.png" masks="aquarium-mask.png">
+
+ <menuitem action="playground_aquarium">
+ <label>&amp;Aquarium</label>
+ </menuitem>
+
+ <editablearea>
+ <position left=" 0" top=" 0" right="320" bottom="320" />
+ <sound ref="aquarium" />
+ </editablearea>
+
+ <category>
+ <position left=" 92" top=" 46" right="736" bottom="359" />
+ <label>Fishes</label>
+ </category>
+
+ <category>
+ <position left=" 92" top=" 46" right="736" bottom="559" />
+ <label>Others</label>
+ </category>
+
+ <object>
+ <position left=" 92" top=" 46" right="236" bottom=" 32" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="325" top=" 5" right="388" bottom=" 52" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="395" top=" 5" right="444" bottom=" 52" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="454" top=" 5" right="501" bottom=" 52" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="325" top=" 62" right="415" bottom="124" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="423" top=" 62" right="511" bottom="124" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="330" top="130" right="357" bottom="184" />
+ <sound ref="seahorse" />
+ </object>
+
+ <object>
+ <position left="370" top="130" right="405" bottom="184" />
+ <sound ref="seahorse" />
+ </object>
+
+ <object>
+ <position left="410" top="130" right="500" bottom="184" />
+ <sound ref="fish" />
+ </object>
+
+ <object>
+ <position left="325" top="225" right="378" bottom="290" />
+ <sound ref="jellyfish" />
+ </object>
+
+ <object>
+ <position left="386" top="215" right="439" bottom="290" />
+ <sound ref="helmet" />
+ </object>
+
+ <object>
+ <position left="452" top="215" right="508" bottom="290" />
+ <sound ref="treasure" />
+ </object>
+
+ </playground>
+
+ <language code="da">
+
+ <menuitem action="speech_danish">
+ <label>&amp;Danish</label>
+ </menuitem>
+
+ <sound name="tuberling" file="da/kartoffelfyr.wav" />
+ <sound name="eye" file="da/oeje.wav" />
+ <sound name="eyebrow" file="da/oejenbryn.wav" />
+ <sound name="nose" file="da/naese.wav" />
+ <sound name="ear" file="da/oere.wav" />
+ <sound name="mouth" file="da/mund.wav" />
+ <sound name="hat" file="da/hat.wav" />
+ <sound name="moustache" file="da/overskaeg.wav" />
+ <sound name="cigar" file="da/cigar.wav" />
+ <sound name="bow" file="da/sloejfe.wav" />
+ <sound name="sunglasses" file="da/solbriller.wav" />
+ <sound name="spectacles" file="da/briller.wav" />
+ <sound name="earring" file="da/oerering.wav" />
+ <sound name="badge" file="da/politiskilt.wav" />
+ <sound name="watch" file="da/ur.wav" />
+ <sound name="penguin" file="da/pingvin.wav" />
+ <sound name="tie" file="da/slips.wav" />
+ <sound name="hair" file="da/haar.wav" />
+ <sound name="horn" file="da/horn.wav" />
+ <sound name="necklace" file="da/halsbaand.wav" />
+ <sound name="scarf" file="da/halstoerklaede.wav" />
+
+ </language>
+
+ <language code="de">
+
+ <menuitem action="speech_german">
+ <label>&amp;German</label>
+ </menuitem>
+
+ <sound name="eye" file="de/auge.wav" />
+ <sound name="eyebrow" file="de/augenbraue.wav" />
+ <sound name="ear" file="de/ohr.wav" />
+ <sound name="hat" file="de/hut.wav" />
+ <sound name="moustache" file="de/schnurrbart.wav" />
+ <sound name="bow" file="de/fliege.wav" />
+ <sound name="spectacles" file="de/brille.wav" />
+ <sound name="earring" file="de/ohrring.wav" />
+ <sound name="badge" file="de/abzeichen.wav" />
+ <sound name="watch" file="de/uhr.wav" />
+ <sound name="hair" file="de/haare.wav" />
+
+ </language>
+
+ <language code="en">
+
+ <menuitem action="speech_english">
+ <label>&amp;English</label>
+ </menuitem>
+
+ <sound name="tuberling" file="en/tuberling.wav" />
+ <sound name="eye" file="en/eye.wav" />
+ <sound name="eyebrow" file="en/eyebrow.wav" />
+ <sound name="nose" file="en/nose.wav" />
+ <sound name="ear" file="en/ear.wav" />
+ <sound name="mouth" file="en/mouth.wav" />
+ <sound name="hat" file="en/hat.wav" />
+ <sound name="moustache" file="en/moustache.wav" />
+ <sound name="cigar" file="en/cigar.wav" />
+ <sound name="bow" file="en/bow.wav" />
+ <sound name="sunglasses" file="en/sunglasses.wav" />
+ <sound name="spectacles" file="en/spectacles.wav" />
+ <sound name="earring" file="en/earring.wav" />
+ <sound name="badge" file="en/badge.wav" />
+ <sound name="watch" file="en/watch.wav" />
+
+ </language>
+
+ <language code="es">
+
+ <menuitem action="speech_spanish">
+ <label>Sp&amp;anish</label>
+ </menuitem>
+
+ <sound name="tuberling" file="es/eltipodelapatata.wav" />
+ <sound name="eye" file="es/ojo.wav" />
+ <sound name="eyebrow" file="es/ceja.wav" />
+ <sound name="nose" file="es/nariz.wav" />
+ <sound name="ear" file="es/oreja.wav" />
+ <sound name="mouth" file="es/boca.wav" />
+ <sound name="hat" file="es/sombrero.wav" />
+ <sound name="moustache" file="es/bigote.wav" />
+ <sound name="cigar" file="es/cigarro.wav" />
+ <sound name="bow" file="es/lazo.wav" />
+ <sound name="sunglasses" file="es/gafasdesol.wav" />
+ <sound name="spectacles" file="es/anteojos.wav" />
+ <sound name="earring" file="es/pendiente.wav" />
+ <sound name="badge" file="es/insignia.wav" />
+ <sound name="watch" file="es/reloj.wav" />
+
+ </language>
+
+ <language code="fi">
+
+ <menuitem action="speech_finnish">
+ <label>Fi&amp;nnish</label>
+ </menuitem>
+
+ <sound name="tuberling" file="fi/perunamies.wav" />
+ <sound name="eye" file="fi/silma.wav" />
+ <sound name="eyebrow" file="fi/kulmakarva.wav" />
+ <sound name="nose" file="fi/nena.wav" />
+ <sound name="ear" file="fi/korva.wav" />
+ <sound name="mouth" file="fi/suu.wav" />
+ <sound name="hat" file="fi/hattu.wav" />
+ <sound name="moustache" file="fi/viikset.wav" />
+ <sound name="cigar" file="fi/sikari.wav" />
+ <sound name="bow" file="fi/rusetti.wav" />
+ <sound name="sunglasses" file="fi/aurinkolasit.wav" />
+ <sound name="spectacles" file="fi/silmalasit.wav" />
+ <sound name="earring" file="fi/korvakoru.wav" />
+ <sound name="badge" file="fi/merkki.wav" />
+ <sound name="watch" file="fi/kello.wav" />
+
+ </language>
+
+ <language code="fr">
+
+ <menuitem action="speech_french">
+ <label>&amp;French</label>
+ </menuitem>
+
+ <sound name="tuberling" file="fr/monsieur-patate.wav" />
+ <sound name="eye" file="fr/oeil.wav" />
+ <sound name="eyebrow" file="fr/sourcil.wav" />
+ <sound name="nose" file="fr/nez.wav" />
+ <sound name="ear" file="fr/oreille.wav" />
+ <sound name="mouth" file="fr/bouche.wav" />
+ <sound name="hat" file="fr/chapeau.wav" />
+ <sound name="moustache" file="fr/moustache.wav" />
+ <sound name="cigar" file="fr/cigare.wav" />
+ <sound name="bow" file="fr/noeud-papillon.wav" />
+ <sound name="sunglasses" file="fr/lunettes-de-soleil.wav" />
+ <sound name="spectacles" file="fr/lunettes.wav" />
+ <sound name="earring" file="fr/boucle-d-oreille.wav" />
+ <sound name="badge" file="fr/medaille.wav" />
+ <sound name="watch" file="fr/montre.wav" />
+ <sound name="penguin" file="fr/pingouin.wav" />
+ <sound name="tie" file="fr/cravate.wav" />
+ <sound name="hair" file="fr/cheveux.wav" />
+ <sound name="horn" file="fr/corne.wav" />
+ <sound name="necklace" file="fr/collier.wav" />
+ <sound name="scarf" file="fr/foulard.wav" />
+
+ </language>
+
+ <language code="it">
+
+ <menuitem action="speech_italian">
+ <label>&amp;Italian</label>
+ </menuitem>
+
+ <sound name="tuberling" file="it/patatone.wav" />
+ <sound name="eye" file="it/occhio.wav" />
+ <sound name="eyebrow" file="it/sopracciglio.wav" />
+ <sound name="nose" file="it/naso.wav" />
+ <sound name="ear" file="it/orecchio.wav" />
+ <sound name="mouth" file="it/bocca.wav" />
+ <sound name="hat" file="it/cappello.wav" />
+ <sound name="moustache" file="it/baffi.wav" />
+ <sound name="cigar" file="it/sigaro.wav" />
+ <sound name="bow" file="it/cravattino.wav" />
+ <sound name="sunglasses" file="it/occhialidasole.wav" />
+ <sound name="spectacles" file="it/occhiali.wav" />
+ <sound name="earring" file="it/orecchino.wav" />
+ <sound name="badge" file="it/distintivo.wav" />
+ <sound name="watch" file="it/orologio.wav" />
+ <sound name="penguin" file="it/pinguino.wav" />
+ <sound name="tie" file="it/cravatta.wav" />
+ <sound name="hair" file="it/capelli.wav" />
+ <sound name="horn" file="it/corno.wav" />
+ <sound name="necklace" file="it/collana.wav" />
+ <sound name="scarf" file="it/sciarpina.wav" />
+
+ </language>
+
+ <language code="nds">
+
+ <menuitem action="speech_lowsaxon">
+ <label>Low Sa&amp;xon</label>
+ </menuitem>
+
+ <sound name="tuberling" file="nds/kantueffel.wav" />
+ <sound name="eye" file="nds/oog.wav" />
+ <sound name="eyebrow" file="nds/oogbro.wav" />
+ <sound name="nose" file="nds/nees.wav" />
+ <sound name="ear" file="nds/ohr.wav" />
+ <sound name="mouth" file="nds/mund.wav" />
+ <sound name="hat" file="nds/hoot.wav" />
+ <sound name="moustache" file="nds/neesboort.wav" />
+ <sound name="cigar" file="nds/zigarr.wav" />
+ <sound name="bow" file="nds/fleeg.wav" />
+ <sound name="sunglasses" file="nds/suennbrill.wav" />
+ <sound name="spectacles" file="nds/brill.wav" />
+ <sound name="earring" file="nds/ohrring.wav" />
+ <sound name="badge" file="nds/afteken.wav" />
+ <sound name="watch" file="nds/klock.wav" />
+ <sound name="penguin" file="nds/penguin.wav" />
+ <sound name="tie" file="nds/slips.wav" />
+ <sound name="hair" file="nds/hoor.wav" />
+ <sound name="horn" file="nds/hoorn.wav" />
+ <sound name="necklace" file="nds/halskeed.wav" />
+ <sound name="scarf" file="nds/schaal.wav" />
+ <sound name="fish" file="nds/fisch.wav" />
+ <sound name="jellyfish" file="nds/quall.wav" />
+ <sound name="seahorse" file="nds/seepeerd.wav" />
+ <sound name="aquarium" file="nds/aquarium.wav" />
+ <sound name="helmet" file="nds/duekerhoot.wav" />
+ <sound name="treasure" file="nds/schatz.wav" />
+
+ </language>
+
+ <language code="nl">
+
+ <menuitem action="speech_dutch">
+ <label>D&amp;utch</label>
+ </menuitem>
+
+ <sound name="tuberling" file="nl/aardappelmannetje.wav" />
+ <sound name="eye" file="nl/oog.wav" />
+ <sound name="eyebrow" file="nl/wenkbrauw.wav" />
+ <sound name="nose" file="nl/neus.wav" />
+ <sound name="ear" file="nl/oor.wav" />
+ <sound name="mouth" file="nl/mond.wav" />
+ <sound name="hat" file="nl/hoed.wav" />
+ <sound name="moustache" file="nl/snor.wav" />
+ <sound name="cigar" file="nl/sigaar.wav" />
+ <sound name="bow" file="nl/strik.wav" />
+ <sound name="sunglasses" file="nl/zonnebril.wav" />
+ <sound name="spectacles" file="nl/bril.wav" />
+ <sound name="earring" file="nl/oorbel.wav" />
+ <sound name="badge" file="nl/ster.wav" />
+ <sound name="watch" file="nl/horloge.wav" />
+ <sound name="penguin" file="nl/pinguin.wav" />
+ <sound name="tie" file="nl/stropdas.wav" />
+ <sound name="hair" file="nl/haar.wav" />
+ <sound name="horn" file="nl/horens.wav" />
+ <sound name="necklace" file="nl/ketting.wav" />
+ <sound name="scarf" file="nl/sjaal.wav" />
+
+ </language>
+
+ <language code="pt">
+
+ <menuitem action="speech_portuguese">
+ <label>&amp;Portuguese</label>
+ </menuitem>
+
+ <sound name="tuberling" file="pt/senhor-batata.wav" />
+ <sound name="eye" file="pt/olho.wav" />
+ <sound name="eyebrow" file="pt/sobrancelha.wav" />
+ <sound name="nose" file="pt/nariz.wav" />
+ <sound name="ear" file="pt/orelha.wav" />
+ <sound name="mouth" file="pt/boca.wav" />
+ <sound name="hat" file="pt/chapeu.wav" />
+ <sound name="moustache" file="pt/bigode.wav" />
+ <sound name="cigar" file="pt/cigarro.wav" />
+ <sound name="bow" file="pt/laco.wav" />
+ <sound name="sunglasses" file="pt/oculos-de-sol.wav" />
+ <sound name="spectacles" file="pt/oculos.wav" />
+ <sound name="earring" file="pt/brincos.wav" />
+ <sound name="badge" file="pt/medalha.wav" />
+ <sound name="watch" file="pt/relogio.wav" />
+ <sound name="penguin" file="pt/pinguim.wav" />
+ <sound name="tie" file="pt/gravata.wav" />
+ <sound name="hair" file="pt/cabelo.wav" />
+ <sound name="horn" file="pt/corno.wav" />
+ <sound name="necklace" file="pt/colares.wav" />
+ <sound name="scarf" file="pt/lenco.wav" />
+
+ </language>
+
+ <language code="ro">
+
+ <menuitem action="speech_romanian">
+ <label>&amp;Romanian</label>
+ </menuitem>
+
+ <sound name="tuberling" file="ro/domnul-cartof.wav" />
+ <sound name="eye" file="ro/ochi.wav" />
+ <sound name="eyebrow" file="ro/sprinceana.wav" />
+ <sound name="nose" file="ro/nas.wav" />
+ <sound name="ear" file="ro/ureche.wav" />
+ <sound name="mouth" file="ro/gura.wav" />
+ <sound name="hat" file="ro/palarie.wav" />
+ <sound name="moustache" file="ro/mustata.wav" />
+ <sound name="cigar" file="ro/tigara.wav" />
+ <sound name="bow" file="ro/papion.wav" />
+ <sound name="sunglasses" file="ro/ochelari-de-soare.wav" />
+ <sound name="spectacles" file="ro/ochelari.wav" />
+ <sound name="earring" file="ro/cercel.wav" />
+ <sound name="badge" file="ro/insigna.wav" />
+ <sound name="watch" file="ro/ceas.wav" />
+ <sound name="penguin" file="ro/pinguin.wav" />
+ <sound name="tie" file="ro/cravata.wav" />
+ <sound name="hair" file="ro/par.wav" />
+ <sound name="horn" file="ro/corn.wav" />
+ <sound name="necklace" file="ro/colier.wav" />
+ <sound name="scarf" file="ro/fular.wav" />
+
+ </language>
+
+ <language code="sk">
+
+ <menuitem action="speech_slovak">
+ <label>&amp;Slovak</label>
+ </menuitem>
+
+ <sound name="tuberling" file="sk/zemiacik.wav" />
+ <sound name="eye" file="sk/oko.wav" />
+ <sound name="eyebrow" file="sk/obocie.wav" />
+ <sound name="nose" file="sk/nos.wav" />
+ <sound name="ear" file="sk/ucho.wav" />
+ <sound name="mouth" file="sk/usta.wav" />
+ <sound name="hat" file="sk/klobuk.wav" />
+ <sound name="moustache" file="sk/fuzy.wav" />
+ <sound name="cigar" file="sk/cigara.wav" />
+ <sound name="bow" file="sk/kravata.wav" />
+ <sound name="sunglasses" file="sk/slnecneokuliare.wav" />
+ <sound name="spectacles" file="sk/okuliare.wav" />
+ <sound name="earring" file="sk/nausnica.wav" />
+ <sound name="badge" file="sk/odznak.wav" />
+ <sound name="watch" file="sk/hodinky.wav" />
+
+ </language>
+
+ <language code="sl">
+
+ <menuitem action="speech_slovenian">
+ <label>S&amp;lovenian</label>
+ </menuitem>
+
+ <sound name="tuberling" file="sl/krompircek.wav" />
+ <sound name="eye" file="sl/oko.wav" />
+ <sound name="eyebrow" file="sl/obrvi.wav" />
+ <sound name="nose" file="sl/nos.wav" />
+ <sound name="ear" file="sl/uho.wav" />
+ <sound name="mouth" file="sl/usta.wav" />
+ <sound name="hat" file="sl/klobuk.wav" />
+ <sound name="moustache" file="sl/brki.wav" />
+ <sound name="cigar" file="sl/cigara.wav" />
+ <sound name="bow" file="sl/metuljcek.wav" />
+ <sound name="sunglasses" file="sl/soncna_ocala.wav" />
+ <sound name="spectacles" file="sl/naocniki.wav" />
+ <sound name="earring" file="sl/uhan.wav" />
+ <sound name="badge" file="sl/znacka.wav" />
+ <sound name="watch" file="sl/ura.wav" />
+ <sound name="penguin" file="sl/pingvin.wav" />
+ <sound name="tie" file="sl/kravata.wav" />
+ <sound name="hair" file="sl/lasje.wav" />
+ <sound name="horn" file="sl/rog.wav" />
+ <sound name="necklace" file="sl/naocniki.wav" />
+ <sound name="scarf" file="sl/sal.wav" />
+
+ </language>
+
+ <language code="sv">
+
+ <menuitem action="speech_swedish">
+ <label>S&amp;wedish</label>
+ </menuitem>
+
+ <sound name="tuberling" file="sv/potatismannen.wav" />
+ <sound name="eye" file="sv/oga.wav" />
+ <sound name="eyebrow" file="sv/ogonbryn.wav" />
+ <sound name="nose" file="sv/nasa.wav" />
+ <sound name="ear" file="sv/ora.wav" />
+ <sound name="mouth" file="sv/mun.wav" />
+ <sound name="hat" file="sv/hatt.wav" />
+ <sound name="moustache" file="sv/mustasch.wav" />
+ <sound name="cigar" file="sv/cigarr.wav" />
+ <sound name="bow" file="sv/rosett.wav" />
+ <sound name="sunglasses" file="sv/solglasogon.wav" />
+ <sound name="spectacles" file="sv/glasogon.wav" />
+ <sound name="earring" file="sv/orhange.wav" />
+ <sound name="badge" file="sv/brosch.wav" />
+ <sound name="watch" file="sv/klocka.wav" />
+ <sound name="penguin" file="sv/pingvin.wav" />
+ <sound name="tie" file="sv/slips.wav" />
+ <sound name="hair" file="sv/har.wav" />
+ <sound name="horn" file="sv/horn.wav" />
+ <sound name="necklace" file="sv/halsband.wav" />
+ <sound name="scarf" file="sv/halsduk.wav" />
+
+ </language>
+
+ <language code="sr">
+
+ <menuitem action="speech_serbian">
+ <label>Ser&amp;bian</label>
+ </menuitem>
+
+ <sound name="tuberling" file="sr/krompirko.wav" />
+ <sound name="eye" file="sr/oko.wav" />
+ <sound name="eyebrow" file="sr/obrva.wav" />
+ <sound name="nose" file="sr/nos.wav" />
+ <sound name="ear" file="sr/uvo.wav" />
+ <sound name="mouth" file="sr/usta.wav" />
+ <sound name="hat" file="sr/sesir.wav" />
+ <sound name="moustache" file="sr/brkovi.wav" />
+ <sound name="cigar" file="sr/cigara.wav" />
+ <sound name="bow" file="sr/masna.wav" />-->
+ <sound name="sunglasses" file="sr/naocare_za_sunce.wav" />
+ <sound name="spectacles" file="sr/naocare.wav" />
+ <sound name="earring" file="sr/mindjusa.wav" />
+ <sound name="badge" file="sr/znacka.wav" />
+ <sound name="watch" file="sr/sat.wav" />
+
+ </language>
+
+</ktuberling>
diff --git a/ktuberling/pics/penguin-game.png b/ktuberling/pics/penguin-game.png
new file mode 100644
index 00000000..6bbdfe74
--- /dev/null
+++ b/ktuberling/pics/penguin-game.png
Binary files differ
diff --git a/ktuberling/pics/penguin-mask.png b/ktuberling/pics/penguin-mask.png
new file mode 100644
index 00000000..efaf0654
--- /dev/null
+++ b/ktuberling/pics/penguin-mask.png
Binary files differ
diff --git a/ktuberling/pics/potato-game.png b/ktuberling/pics/potato-game.png
new file mode 100644
index 00000000..10132333
--- /dev/null
+++ b/ktuberling/pics/potato-game.png
Binary files differ
diff --git a/ktuberling/pics/potato-mask.png b/ktuberling/pics/potato-mask.png
new file mode 100644
index 00000000..838865d3
--- /dev/null
+++ b/ktuberling/pics/potato-mask.png
Binary files differ
diff --git a/ktuberling/playground.cpp b/ktuberling/playground.cpp
new file mode 100644
index 00000000..367c407c
--- /dev/null
+++ b/ktuberling/playground.cpp
@@ -0,0 +1,609 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Play ground widget
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+#include <stdlib.h>
+
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kprinter.h>
+
+#include <qfile.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <qcursor.h>
+#include <qdom.h>
+
+#include "playground.moc"
+#include "toplevel.h"
+
+#define XMARGIN 5
+#define YMARGIN 5
+
+// Constructor
+PlayGround::PlayGround(TopLevel *parent, const char *name, uint selectedGameboard)
+ : QWidget(parent, name)
+{
+ topLevel = parent;
+
+ textsLayout = objectsLayout = 0;
+ textsList = soundsList = 0;
+ draggedCursor = 0;
+
+ toDraw.setAutoDelete(true);
+ history.setAutoDelete(true);
+
+ setBackgroundColor(white);
+
+ QDomDocument layoutsDocument;
+ bool ok = topLevel->loadLayout(layoutsDocument);
+ if (ok) ok = registerPlayGrounds(layoutsDocument);
+ if (ok) ok = loadPlayGround(layoutsDocument, selectedGameboard);
+ if (!ok) loadFailure();
+
+ currentAction = 0;
+ setupGeometry();
+}
+
+// Destructor
+PlayGround::~PlayGround()
+{
+ delete [] textsLayout;
+ delete [] objectsLayout;
+
+ delete [] textsList;
+ delete [] soundsList;
+
+ delete draggedCursor;
+}
+
+// Reset the play ground
+void PlayGround::reset()
+{
+ toDraw.clear();
+ history.clear();
+ currentAction = 0;
+}
+
+// Change the gameboard
+void PlayGround::change(uint selectedGameboard)
+{
+ QDomDocument layoutsDocument;
+ bool ok = topLevel->loadLayout(layoutsDocument);
+ if (ok) ok = loadPlayGround(layoutsDocument, selectedGameboard);
+ if (!ok) loadFailure();
+
+ toDraw.clear();
+ history.clear();
+ currentAction = 0;
+
+ setupGeometry();
+
+ update();
+}
+
+// Repaint all the editable area
+void PlayGround::repaintAll()
+{
+ QRect dirtyArea
+ (editableArea.left() - 10,
+ editableArea.top() - 10,
+ editableArea.width() + 20,
+ editableArea.height() + 20);
+
+ repaint(dirtyArea, false);
+}
+
+// Undo last action
+// Returns true if everything went fine
+bool PlayGround::undo()
+{
+ ToDraw *newObject;
+ Action *undone;
+ int zOrder;
+
+ if (!(undone = history.at(--currentAction)))
+ return false;
+
+ zOrder = undone->ZOrderAfter();
+ if (zOrder != -1)
+ {
+ // Undo an "add" or a "move" action
+ if (!toDraw.remove(zOrder)) return false;
+ }
+
+ zOrder = undone->ZOrderBefore();
+ if (zOrder != -1)
+ {
+ // Undo a "delete" or a "move" action
+ newObject = new ToDraw(undone->DrawnBefore());
+ if (!toDraw.insert(zOrder, newObject))
+ return false;
+ }
+
+ return true;
+}
+
+// Redo next action
+// Returns true if everything went fine
+bool PlayGround::redo()
+{
+ ToDraw *newObject;
+ Action *undone;
+ int zOrder;
+
+ if (!(undone = history.at(currentAction++)))
+ return false;
+
+ zOrder = undone->ZOrderBefore();
+ if (zOrder != -1)
+ {
+ // Redo a "delete" or a "move" action
+ if (!toDraw.remove(zOrder)) return false;
+ }
+
+ zOrder = undone->ZOrderAfter();
+ if (zOrder != -1)
+ {
+ // Redo an "add" or a "move" action
+ newObject = new ToDraw(undone->DrawnAfter());
+ if (!toDraw.insert(zOrder, newObject))
+ return false;
+ }
+
+ return true;
+}
+
+// Save objects laid down on the editable area
+bool PlayGround::saveAs(const QString & name)
+{
+ FILE *fp;
+ const ToDraw *currentObject;
+
+ if (!(fp = fopen((const char *) QFile::encodeName(name), "w"))) return false;
+
+ fprintf(fp, "%d\n", topLevel->getSelectedGameboard());
+ for (currentObject = toDraw.first(); currentObject; currentObject = toDraw.next())
+ currentObject->save(fp);
+
+ return !fclose(fp);
+}
+
+// Print gameboard's picture
+bool PlayGround::printPicture(KPrinter &printer) const
+{
+ QPainter artist;
+ QPixmap picture(getPicture());
+
+ if (!artist.begin(&printer)) return false;
+ artist.drawPixmap(QPoint(32, 32), picture);
+ if (!artist.end()) return false;
+ return true;
+}
+
+// Get a pixmap containing the current picture
+QPixmap PlayGround::getPicture() const
+{
+ QPixmap result(editableArea.size());
+ QPainter artist(&result);
+ QRect transEditableArea(editableArea);
+
+ transEditableArea.moveBy(-XMARGIN, -YMARGIN);
+ artist.translate(XMARGIN - editableArea.left(),
+ YMARGIN - editableArea.top());
+ drawGameboard(artist, transEditableArea);
+ return result;
+}
+
+// Draw some text
+void PlayGround::drawText(QPainter &artist, QRect &area, QString &textId) const
+{
+ QString label;
+
+ label=i18n(textId.latin1());
+
+ artist.drawText(area, AlignCenter, label);
+}
+
+// Paint the current picture to the given device
+void PlayGround::drawGameboard( QPainter &artist, const QRect &area ) const
+{
+ artist.drawPixmap(area.topLeft(), gameboard, area);
+
+ artist.setPen(white);
+ for (int text = 0; text < texts; text++)
+ drawText(artist, textsLayout[text], textsList[text]);
+
+ artist.setPen(black);
+ for (QPtrListIterator<ToDraw> currentObject(toDraw);
+ currentObject.current();
+ ++currentObject)
+ currentObject.current()->draw(artist, area, objectsLayout, &gameboard, &masks);
+}
+
+// Painting event
+void PlayGround::paintEvent( QPaintEvent *event )
+{
+ QPoint destination(event->rect().topLeft()),
+ position(destination.x() - XMARGIN,
+ destination.y() - YMARGIN);
+ QRect area(position, QSize(event->rect().size()));
+ QPixmap cache(gameboard.size());
+ QPainter artist(&cache);
+
+ if (destination.x() < XMARGIN) destination.setX(XMARGIN);
+ if (destination.y() < YMARGIN) destination.setY(YMARGIN);
+ area = QRect(0, 0, gameboard.width(), gameboard.height()).intersect(area);
+ if (area.isEmpty()) return;
+
+ drawGameboard(artist, area);
+
+ bitBlt(this, destination, &cache, area, Qt::CopyROP);
+}
+
+// Mouse pressed event
+void PlayGround::mousePressEvent( QMouseEvent *event )
+{
+ if (draggedCursor) return;
+
+ QPoint position(event->x() - XMARGIN,
+ event->y() - YMARGIN);
+ if (!zone(position)) return;
+
+ int draggedNumber = draggedObject.getNumber();
+ QPixmap object(objectsLayout[draggedNumber].size());
+ QBitmap shape(objectsLayout[draggedNumber].size());
+ bitBlt(&object, QPoint(0, 0), &gameboard, objectsLayout[draggedNumber], Qt::CopyROP);
+ bitBlt(&shape, QPoint(0, 0), &masks, objectsLayout[draggedNumber], Qt::CopyROP);
+ object.setMask(shape);
+
+ draggedCursor = new QCursor(object, position.x(), position.y());
+ setCursor(*draggedCursor);
+
+ topLevel->playSound(soundsList[draggedNumber]);
+}
+
+// Mouse released event
+void PlayGround::mouseReleaseEvent( QMouseEvent *event )
+{
+ // If we are not dragging an object, ignore the event
+ if (!draggedCursor) return;
+
+ QCursor arrow;
+ int draggedNumber = draggedObject.getNumber();
+ QRect position(
+ event->x() - XMARGIN - draggedCursor->hotSpot().x(),
+ event->y() - YMARGIN - draggedCursor->hotSpot().y(),
+ objectsLayout[draggedNumber].width(),
+ objectsLayout[draggedNumber].height());
+ QRect dirtyArea
+ (editableArea.left() - 10,
+ editableArea.top() - 10,
+ editableArea.width() + 20,
+ editableArea.height() + 20);
+ ToDraw *newObject;
+ Action *newAction;
+
+ // We are not anymore dragging an object
+ delete draggedCursor;
+ draggedCursor = 0;
+ setCursor(arrow);
+
+ // If we are not moving the object to the editable area
+ if (!dirtyArea.contains(event->pos()))
+ {
+ // ... then register its deletion (if coming from the editable area), and return
+ if (draggedZOrder == -1) return;
+
+ while (history.count() > currentAction) history.removeLast();
+ newAction = new Action(&draggedObject, draggedZOrder, 0, -1);
+ history.append(newAction);
+ currentAction++;
+ topLevel->enableUndo(true);
+
+ return;
+ }
+
+ // Register that we have one more object to draw
+ newObject = new ToDraw(draggedNumber, position);
+ toDraw.append(newObject);
+
+ // Forget all subsequent actions in the undo buffer, and register object's addition (or its move)
+ while (history.count() > currentAction) history.removeLast();
+ newAction = new Action(&draggedObject, draggedZOrder, newObject, toDraw.count()-1);
+ history.append(newAction);
+ currentAction++;
+ topLevel->enableUndo(true);
+
+ // Repaint the editable area
+ position.moveBy(XMARGIN, YMARGIN);
+ repaint(position, false);
+
+}
+
+// Register the various playgrounds
+bool PlayGround::registerPlayGrounds(QDomDocument &layoutDocument)
+{
+ QDomNodeList playGroundsList, menuItemsList, labelsList;
+ QDomElement playGroundElement, menuItemElement, labelElement;
+ QDomAttr actionAttribute;
+
+ playGroundsList = layoutDocument.elementsByTagName("playground");
+ if (playGroundsList.count() < 1)
+ return false;
+
+ for (uint i = 0; i < playGroundsList.count(); i++)
+ {
+ playGroundElement = (const QDomElement &) playGroundsList.item(i).toElement();
+
+ menuItemsList = playGroundElement.elementsByTagName("menuitem");
+ if (menuItemsList.count() != 1)
+ return false;
+
+ menuItemElement = (const QDomElement &) menuItemsList.item(0).toElement();
+
+ labelsList = menuItemElement.elementsByTagName("label");
+ if (labelsList.count() != 1)
+ return false;
+
+ labelElement = (const QDomElement &) labelsList.item(0).toElement();
+ actionAttribute = menuItemElement.attributeNode("action");
+ topLevel->registerGameboard(labelElement.text(), actionAttribute.value().latin1());
+ }
+
+ return true;
+}
+
+// Load background and draggable objects masks
+bool PlayGround::loadPlayGround(QDomDocument &layoutDocument, uint toLoad)
+{
+ QDomNodeList playGroundsList,
+ editableAreasList, categoriesList, objectsList,
+ gameAreasList, maskAreasList, soundNamesList, labelsList;
+ QDomElement playGroundElement,
+ editableAreaElement, categoryElement, objectElement,
+ gameAreaElement, maskAreaElement, soundNameElement, labelElement;
+ QDomAttr gameboardAttribute, masksAttribute,
+ leftAttribute, topAttribute, rightAttribute, bottomAttribute,
+ refAttribute;
+
+ playGroundsList = layoutDocument.elementsByTagName("playground");
+ if (toLoad >= playGroundsList.count())
+ return false;
+
+ playGroundElement = (const QDomElement &) playGroundsList.item(toLoad).toElement();
+
+ gameboardAttribute = playGroundElement.attributeNode("gameboard");
+ if (!gameboard.load(locate("data", "ktuberling/pics/" + gameboardAttribute.value())))
+ return false;
+
+ masksAttribute = playGroundElement.attributeNode("masks");
+ if (!masks.load(locate("data", "ktuberling/pics/" + masksAttribute.value())))
+ return false;
+
+ editableAreasList = playGroundElement.elementsByTagName("editablearea");
+ if (editableAreasList.count() != 1)
+ return false;
+
+ editableAreaElement = (const QDomElement &) editableAreasList.item(0).toElement();
+
+ gameAreasList = editableAreaElement.elementsByTagName("position");
+ if (gameAreasList.count() != 1)
+ return false;
+
+ gameAreaElement = (const QDomElement &) gameAreasList.item(0).toElement();
+ leftAttribute = gameAreaElement.attributeNode("left");
+ topAttribute = gameAreaElement.attributeNode("top");
+ rightAttribute = gameAreaElement.attributeNode("right");
+ bottomAttribute = gameAreaElement.attributeNode("bottom");
+
+ editableArea.setCoords
+ (XMARGIN + leftAttribute.value().toInt(),
+ YMARGIN + topAttribute.value().toInt(),
+ XMARGIN + rightAttribute.value().toInt(),
+ YMARGIN + bottomAttribute.value().toInt());
+
+ soundNamesList = editableAreaElement.elementsByTagName("sound");
+ if (soundNamesList.count() != 1)
+ return false;
+
+ soundNameElement = (const QDomElement &) soundNamesList.item(0).toElement();
+ refAttribute = soundNameElement.attributeNode("ref");
+
+ editableSound = refAttribute.value();
+
+ categoriesList = playGroundElement.elementsByTagName("category");
+ texts = categoriesList.count();
+ if (texts < 1)
+ return false;
+
+ delete[] textsLayout;
+ textsLayout = new QRect[texts];
+ delete[] textsList;
+ textsList = new QString[texts];
+
+ for (int text = 0; text < texts; text++)
+ {
+ categoryElement = (const QDomElement &) categoriesList.item(text).toElement();
+
+ gameAreasList = categoryElement.elementsByTagName("position");
+ if (gameAreasList.count() != 1)
+ return false;
+
+ gameAreaElement = (const QDomElement &) gameAreasList.item(0).toElement();
+ leftAttribute = gameAreaElement.attributeNode("left");
+ topAttribute = gameAreaElement.attributeNode("top");
+ rightAttribute = gameAreaElement.attributeNode("right");
+ bottomAttribute = gameAreaElement.attributeNode("bottom");
+
+ textsLayout[text].setCoords
+ (leftAttribute.value().toInt(),
+ topAttribute.value().toInt(),
+ rightAttribute.value().toInt(),
+ bottomAttribute.value().toInt());
+
+ labelsList = categoryElement.elementsByTagName("label");
+ if (labelsList.count() != 1)
+ return false;
+
+ labelElement = (const QDomElement &) labelsList.item(0).toElement();
+
+ textsList[text] = labelElement.text();
+ }
+
+ objectsList = playGroundElement.elementsByTagName("object");
+ decorations = objectsList.count();
+ if (decorations < 1)
+ return false;
+
+ delete[] objectsLayout;
+ objectsLayout = new QRect[decorations];
+ delete[] soundsList;
+ soundsList = new QString[decorations];
+
+ for (int decoration = 0; decoration < decorations; decoration++)
+ {
+ objectElement = (const QDomElement &) objectsList.item(decoration).toElement();
+
+ gameAreasList = objectElement.elementsByTagName("position");
+ if (gameAreasList.count() != 1)
+ return false;
+
+ gameAreaElement = (const QDomElement &) gameAreasList.item(0).toElement();
+ leftAttribute = gameAreaElement.attributeNode("left");
+ topAttribute = gameAreaElement.attributeNode("top");
+ rightAttribute = gameAreaElement.attributeNode("right");
+ bottomAttribute = gameAreaElement.attributeNode("bottom");
+
+ objectsLayout[decoration].setCoords
+ (leftAttribute.value().toInt(),
+ topAttribute.value().toInt(),
+ rightAttribute.value().toInt(),
+ bottomAttribute.value().toInt());
+
+ soundNamesList = objectElement.elementsByTagName("sound");
+ if (soundNamesList.count() != 1)
+ return false;
+
+ soundNameElement = (const QDomElement &) soundNamesList.item(0).toElement();
+
+ refAttribute = soundNameElement.attributeNode("ref");
+
+ soundsList[decoration] = refAttribute.value();
+ }
+
+ return true;
+}
+
+// Report a load failure
+void PlayGround::loadFailure()
+{
+ KMessageBox::error(topLevel, i18n("Fatal error:\n"
+ "Unable to load the pictures, aborting."));
+ exit(-1);
+}
+
+// Set up play ground's geometry
+void PlayGround::setupGeometry()
+{
+ int width = gameboard.width() + 2 * XMARGIN,
+ height = gameboard.height() + 2 * YMARGIN;
+ setFixedWidth(width);
+ setFixedHeight(height);
+}
+
+// In which decorative object are we?
+// On return, the position is the location of the cursor's hot spot
+// Returns false if we aren't in any zone
+bool PlayGround::zone(QPoint &position)
+{
+ // Scan all available decorative objects on right side because we may be adding one
+ int draggedNumber;
+ for (draggedNumber = 0;
+ draggedNumber < decorations;
+ draggedNumber++) if (objectsLayout[draggedNumber].contains(position))
+ {
+ position.setX(position.x() - objectsLayout[draggedNumber].x());
+ position.setY(position.y() - objectsLayout[draggedNumber].y());
+
+ draggedObject.setNumber(draggedNumber);
+ draggedZOrder = -1;
+
+ return true;
+ }
+
+ // Scan all decorative objects already layed down on editable are because we may be moving or removing one
+ const ToDraw *currentObject;
+
+ for (draggedZOrder = toDraw.count()-1; draggedZOrder >= 0; draggedZOrder--)
+ {
+ currentObject = toDraw.at(draggedZOrder);
+ if (!currentObject->getPosition().contains(position)) continue;
+
+ QRect toUpdate(currentObject->getPosition());
+ draggedObject = *currentObject;
+ draggedNumber = draggedObject.getNumber();
+
+ QBitmap shape(objectsLayout[draggedNumber].size());
+ QPoint relative(position.x() - toUpdate.x(),
+ position.y() - toUpdate.y());
+ bitBlt(&shape, QPoint(0, 0), &masks, objectsLayout[draggedNumber], Qt::CopyROP);
+ if (!shape.convertToImage().pixelIndex(relative.x(), relative.y())) continue;
+
+ toDraw.remove(draggedZOrder);
+ toUpdate.moveBy(XMARGIN, YMARGIN);
+ repaint(toUpdate, false);
+
+ position = relative;
+
+ return true;
+ }
+
+ // If we are on the gameboard itself, then play "tuberling" sound
+ if (editableArea.contains(position))
+ topLevel->playSound(editableSound);
+
+ return false;
+}
+
+// Load objects and lay them down on the editable area
+bool PlayGround::loadFrom(const QString &name)
+{
+ FILE *fp;
+ bool eof = false;
+ ToDraw readObject, *newObject;
+ Action *newAction;
+
+ if (!(fp = fopen(QFile::encodeName(name), "r"))) return false;
+
+ uint newGameboard;
+ int nitems = fscanf(fp, "%u\n", &newGameboard);
+ if (nitems == EOF)
+ {
+ fclose(fp);
+ return false;
+ }
+ topLevel->changeGameboard(newGameboard);
+
+ for (;;)
+ {
+ if (!readObject.load(fp, decorations, eof))
+ {
+ fclose(fp);
+ return false;
+ }
+ if (eof)
+ {
+ return !fclose(fp);
+ }
+ newObject = new ToDraw(readObject);
+ toDraw.append(newObject);
+ newAction = new Action(0, -1, newObject, toDraw.count()-1);
+ history.append(newAction);
+ currentAction++;
+
+ }
+}
diff --git a/ktuberling/playground.h b/ktuberling/playground.h
new file mode 100644
index 00000000..ee1a9a51
--- /dev/null
+++ b/ktuberling/playground.h
@@ -0,0 +1,86 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Play ground widget
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+
+#ifndef _PLAYGROUND_H_
+#define _PLAYGROUND_H_
+
+#include <kprinter.h>
+
+#include <qwidget.h>
+#include <qbitmap.h>
+#include <qptrlist.h>
+
+#include "todraw.h"
+#include "action.h"
+
+class QDomDocument;
+class TopLevel;
+
+class PlayGround : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ PlayGround(TopLevel *parent, const char *name, uint selectedGameboard);
+ ~PlayGround();
+
+ void reset();
+ void change(uint selectedGameboard);
+ void repaintAll();
+ bool undo();
+ bool redo();
+ bool loadFrom(const QString &name);
+ bool saveAs(const QString &name);
+ bool printPicture(KPrinter &printer) const;
+ QPixmap getPicture() const;
+
+ inline bool isFirstAction() const { return currentAction == 0; }
+ inline bool isLastAction() const { return currentAction >= history.count(); }
+
+protected:
+
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+
+private:
+
+ bool registerPlayGrounds(QDomDocument &layoutDocument);
+ bool loadPlayGround(QDomDocument &layoutDocument, uint toLoad);
+ void loadFailure();
+ void setupGeometry();
+ bool zone(QPoint &position);
+ void drawText(QPainter &artist, QRect &area, QString &textId) const;
+ void drawGameboard(QPainter &artist, const QRect &area) const;
+
+private:
+
+ QPixmap gameboard; // Picture of the game board
+ QBitmap masks; // Pictures of the objects' shapes
+ QRect editableArea; // Part of the gameboard where the player can lay down objects
+ QString menuItem, // Menu item describing describing this gameboard
+ editableSound; // Sound associated with this area
+ int texts, // Number of categories of objects names
+ decorations; // Number of draggable objects on the right side of the gameboard
+ QRect *textsLayout, // Positions of the categories names
+ *objectsLayout; // Position of the draggable objects on right side of the gameboard
+ QString *textsList, // List of the message numbers associated with categories
+ *soundsList; // List of sounds associated with each object
+
+ QCursor *draggedCursor; // Cursor's shape for currently dragged object
+ ToDraw draggedObject; // Object currently dragged
+ int draggedZOrder; // Z-order (in to-draw buffer) of this object
+
+ QPtrList<ToDraw> toDraw; // List of objects in z-order
+ QPtrList<Action> history; // List of actions in chronological order
+ unsigned int currentAction; // Number of current action (not the last one if used "undo" button!)
+
+ TopLevel *topLevel; // Top-level window
+};
+
+#endif
diff --git a/ktuberling/soundfactory.cpp b/ktuberling/soundfactory.cpp
new file mode 100644
index 00000000..d9bdf48d
--- /dev/null
+++ b/ktuberling/soundfactory.cpp
@@ -0,0 +1,148 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Play ground widget
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+#include <stdlib.h>
+
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kaudioplayer.h>
+
+#include <qdom.h>
+
+#include "soundfactory.h"
+#include "soundfactory.moc"
+#include "toplevel.h"
+
+// Constructor
+SoundFactory::SoundFactory(TopLevel *parent, const char *name, uint selectedLanguage)
+ : QObject(parent, name)
+{
+ topLevel = parent;
+
+ namesList = filesList = 0;
+
+ QDomDocument layoutsDocument;
+ bool ok = topLevel->loadLayout(layoutsDocument);
+ if (ok) ok = registerLanguages(layoutsDocument);
+ if (ok) ok = loadLanguage(layoutsDocument, selectedLanguage);
+ if (!ok) loadFailure();
+}
+
+// Destructor
+SoundFactory::~SoundFactory()
+{
+ if (namesList) delete [] namesList;
+ if (filesList) delete [] filesList;
+}
+
+// Change the language
+void SoundFactory::change(uint selectedLanguage)
+{
+ QDomDocument layoutsDocument;
+ bool ok = topLevel->loadLayout(layoutsDocument);
+ if (ok) ok = loadLanguage(layoutsDocument, selectedLanguage);
+ if (!ok) loadFailure();
+}
+
+// Play some sound
+void SoundFactory::playSound(const QString &soundRef) const
+{
+ int sound;
+ QString soundFile;
+
+ if (!topLevel->isSoundEnabled()) return;
+
+ for (sound = 0; sound < sounds; sound++)
+ if (!namesList[sound].compare(soundRef)) break;
+ if (sound == sounds) return;
+
+ soundFile = locate("data", "ktuberling/sounds/" + filesList[sound]);
+ if (soundFile == 0) return;
+
+//printf("%s\n", (const char *) soundFile);
+ KAudioPlayer::play(soundFile);
+}
+
+// Report a load failure
+void SoundFactory::loadFailure()
+{
+ KMessageBox::error(topLevel, i18n("Error while loading the sound names."));
+}
+
+// Register the various languages
+bool SoundFactory::registerLanguages(QDomDocument &layoutDocument)
+{
+ QDomNodeList languagesList, menuItemsList, labelsList;
+ QDomElement languageElement, menuItemElement, labelElement;
+ QDomAttr codeAttribute, actionAttribute;
+ bool enabled;
+
+ languagesList = layoutDocument.elementsByTagName("language");
+ if (languagesList.count() < 1)
+ return false;
+
+ for (uint i = 0; i < languagesList.count(); i++)
+ {
+ languageElement = (const QDomElement &) languagesList.item(i).toElement();
+ codeAttribute = languageElement.attributeNode("code");
+ enabled = locate("data", "ktuberling/sounds/" + codeAttribute.value() + "/") != 0;
+
+ menuItemsList = languageElement.elementsByTagName("menuitem");
+ if (menuItemsList.count() != 1)
+ return false;
+
+ menuItemElement = (const QDomElement &) menuItemsList.item(0).toElement();
+
+ labelsList = menuItemElement.elementsByTagName("label");
+ if (labelsList.count() != 1)
+ return false;
+
+ labelElement = (const QDomElement &) labelsList.item(0).toElement();
+ actionAttribute = menuItemElement.attributeNode("action");
+ topLevel->registerLanguage(labelElement.text(), actionAttribute.value().latin1(), enabled);
+ }
+
+ return true;
+}
+
+// Load the sounds of one given language
+bool SoundFactory::loadLanguage(QDomDocument &layoutDocument, uint toLoad)
+{
+ QDomNodeList languagesList,
+ soundNamesList;
+ QDomElement languageElement,
+ soundNameElement;
+ QDomAttr nameAttribute, fileAttribute;
+
+ languagesList = layoutDocument.elementsByTagName("language");
+ if (toLoad >= languagesList.count())
+ return false;
+
+ languageElement = (const QDomElement &) languagesList.item(toLoad).toElement();
+
+ soundNamesList = languageElement.elementsByTagName("sound");
+ sounds = soundNamesList.count();
+ if (sounds < 1)
+ return false;
+
+ if (!(namesList = new QString[sounds]))
+ return false;
+ if (!(filesList = new QString[sounds]))
+ return false;
+
+ for (uint sound = 0; sound < sounds; sound++)
+ {
+ soundNameElement = (const QDomElement &) soundNamesList.item(sound).toElement();
+
+ nameAttribute = soundNameElement.attributeNode("name");
+ namesList[sound] = nameAttribute.value();
+ fileAttribute = soundNameElement.attributeNode("file");
+ filesList[sound] = fileAttribute.value();
+ }
+ return true;
+}
+
diff --git a/ktuberling/soundfactory.h b/ktuberling/soundfactory.h
new file mode 100644
index 00000000..1eb0abd5
--- /dev/null
+++ b/ktuberling/soundfactory.h
@@ -0,0 +1,46 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Sound factory
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+
+#ifndef _SOUNDFACTORY_H_
+#define _SOUNDFACTORY_H_
+
+#include "qobject.h"
+
+class QDomDocument;
+class TopLevel;
+
+class SoundFactory : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ SoundFactory(TopLevel *parent, const char *name, uint selectedLanguage);
+ ~SoundFactory();
+
+ void change(uint selectedLanguage);
+ void playSound(const QString &soundRef) const;
+
+protected:
+
+ bool registerLanguages(QDomDocument &layoutDocument);
+ bool loadLanguage(QDomDocument &layoutDocument, uint toLoad);
+
+private:
+
+ void loadFailure();
+
+private:
+
+ int sounds; // Number of sounds
+ QString *namesList, // List of sound names
+ *filesList; // List of sound files associated with each sound name
+
+ TopLevel *topLevel; // Top-level window
+};
+
+#endif
diff --git a/ktuberling/sounds/Makefile.am b/ktuberling/sounds/Makefile.am
new file mode 100644
index 00000000..3f0d46b7
--- /dev/null
+++ b/ktuberling/sounds/Makefile.am
@@ -0,0 +1,9 @@
+
+# add here all files
+sound_DATA = badge.wav bow.wav cigar.wav ear.wav earring.wav eye.wav eyebrow.wav\
+ hat.wav moustache.wav mouth.wav nose.wav spectacles.wav \
+ sunglasses.wav tuberling.wav watch.wav
+
+sounddir = $(kde_datadir)/ktuberling/sounds/en
+
+# DONT ADD TRANSLATIONS HERE
diff --git a/ktuberling/sounds/NO_TRANSLATIONS_HERE b/ktuberling/sounds/NO_TRANSLATIONS_HERE
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ktuberling/sounds/NO_TRANSLATIONS_HERE
diff --git a/ktuberling/sounds/badge.wav b/ktuberling/sounds/badge.wav
new file mode 100644
index 00000000..2e436e3a
--- /dev/null
+++ b/ktuberling/sounds/badge.wav
Binary files differ
diff --git a/ktuberling/sounds/bow.wav b/ktuberling/sounds/bow.wav
new file mode 100644
index 00000000..28703029
--- /dev/null
+++ b/ktuberling/sounds/bow.wav
Binary files differ
diff --git a/ktuberling/sounds/cigar.wav b/ktuberling/sounds/cigar.wav
new file mode 100644
index 00000000..dbc72e25
--- /dev/null
+++ b/ktuberling/sounds/cigar.wav
Binary files differ
diff --git a/ktuberling/sounds/ear.wav b/ktuberling/sounds/ear.wav
new file mode 100644
index 00000000..901bac74
--- /dev/null
+++ b/ktuberling/sounds/ear.wav
Binary files differ
diff --git a/ktuberling/sounds/earring.wav b/ktuberling/sounds/earring.wav
new file mode 100644
index 00000000..e708caaf
--- /dev/null
+++ b/ktuberling/sounds/earring.wav
Binary files differ
diff --git a/ktuberling/sounds/eye.wav b/ktuberling/sounds/eye.wav
new file mode 100644
index 00000000..b596d4c6
--- /dev/null
+++ b/ktuberling/sounds/eye.wav
Binary files differ
diff --git a/ktuberling/sounds/eyebrow.wav b/ktuberling/sounds/eyebrow.wav
new file mode 100644
index 00000000..d3c1b3b4
--- /dev/null
+++ b/ktuberling/sounds/eyebrow.wav
Binary files differ
diff --git a/ktuberling/sounds/hat.wav b/ktuberling/sounds/hat.wav
new file mode 100644
index 00000000..b6d92e5a
--- /dev/null
+++ b/ktuberling/sounds/hat.wav
Binary files differ
diff --git a/ktuberling/sounds/moustache.wav b/ktuberling/sounds/moustache.wav
new file mode 100644
index 00000000..e671f1c8
--- /dev/null
+++ b/ktuberling/sounds/moustache.wav
Binary files differ
diff --git a/ktuberling/sounds/mouth.wav b/ktuberling/sounds/mouth.wav
new file mode 100644
index 00000000..90613e9c
--- /dev/null
+++ b/ktuberling/sounds/mouth.wav
Binary files differ
diff --git a/ktuberling/sounds/nose.wav b/ktuberling/sounds/nose.wav
new file mode 100644
index 00000000..058e718f
--- /dev/null
+++ b/ktuberling/sounds/nose.wav
Binary files differ
diff --git a/ktuberling/sounds/spectacles.wav b/ktuberling/sounds/spectacles.wav
new file mode 100644
index 00000000..bf0802ae
--- /dev/null
+++ b/ktuberling/sounds/spectacles.wav
Binary files differ
diff --git a/ktuberling/sounds/sunglasses.wav b/ktuberling/sounds/sunglasses.wav
new file mode 100644
index 00000000..0b8f8c6d
--- /dev/null
+++ b/ktuberling/sounds/sunglasses.wav
Binary files differ
diff --git a/ktuberling/sounds/tuberling.wav b/ktuberling/sounds/tuberling.wav
new file mode 100644
index 00000000..c85418b1
--- /dev/null
+++ b/ktuberling/sounds/tuberling.wav
Binary files differ
diff --git a/ktuberling/sounds/watch.wav b/ktuberling/sounds/watch.wav
new file mode 100644
index 00000000..87c03278
--- /dev/null
+++ b/ktuberling/sounds/watch.wav
Binary files differ
diff --git a/ktuberling/todraw.cpp b/ktuberling/todraw.cpp
new file mode 100644
index 00000000..e12c9e1b
--- /dev/null
+++ b/ktuberling/todraw.cpp
@@ -0,0 +1,90 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Object to draw on the game board
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+#include <qbitmap.h>
+#include <qpainter.h>
+
+#include "todraw.h"
+
+// Constructor with no arguments
+ToDraw::ToDraw()
+ : position()
+{
+ number = -1;
+}
+
+// Copy constructor
+ToDraw::ToDraw(const ToDraw &model)
+ : position(model.position)
+{
+ number = model.number;
+}
+
+// Constructor with arguments
+ToDraw::ToDraw(int declaredNumber, const QRect &declaredPosition)
+ : position(declaredPosition)
+{
+ number = declaredNumber;
+}
+
+// Affectation operator
+ToDraw &ToDraw::operator=(const ToDraw &model)
+{
+ if (&model == this) return *this;
+
+ position = model.position;
+ number = model.number;
+
+ return *this;
+}
+
+// Draw an object previously laid down on the game board
+void ToDraw::draw(QPainter &artist, const QRect &area,
+ const QRect *objectsLayout,
+ const QPixmap *gameboard, const QBitmap *masks) const
+{
+ if (!position.intersects(area)) return;
+
+ QPixmap objectPixmap(objectsLayout[number].size());
+ QBitmap shapeBitmap(objectsLayout[number].size());
+
+ bitBlt(&objectPixmap, QPoint(0, 0), gameboard, objectsLayout[number], Qt::CopyROP);
+ bitBlt(&shapeBitmap, QPoint(0, 0), masks, objectsLayout[number], Qt::CopyROP);
+ objectPixmap.setMask(shapeBitmap);
+ artist.drawPixmap(position.topLeft(), objectPixmap);
+}
+
+// Load an object from a file
+bool ToDraw::load(FILE *fp, int decorations, bool &eof)
+{
+ int nitems;
+ int pl, pt, pr, pb;
+
+ nitems = fscanf(fp, "%d\t%d %d %d %d\n", &number, &pl, &pt, &pr, &pb);
+
+ if (nitems == EOF)
+ {
+ eof = true;
+ return true;
+ }
+ eof = false;
+ if (nitems != 5) return false;
+
+ if (number < 0 || number >= decorations) return false;
+
+ position.setCoords(pl, pt, pr, pb);
+
+ return true;
+}
+
+// Save an object to a file
+void ToDraw::save(FILE *fp) const
+{
+ fprintf(fp, "%d\t%d %d %d %d\n",
+ number,
+ position.left(), position.top(), position.right(), position.bottom());
+}
+
diff --git a/ktuberling/todraw.h b/ktuberling/todraw.h
new file mode 100644
index 00000000..4e46200a
--- /dev/null
+++ b/ktuberling/todraw.h
@@ -0,0 +1,35 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Object to draw on the game board
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+
+#ifndef _TODRAW_H_
+#define _TODRAW_H_
+
+#include <qrect.h>
+
+#include <stdio.h>
+
+class ToDraw
+{
+ public:
+ ToDraw();
+ ToDraw(const ToDraw &);
+ ToDraw(int, const QRect &);
+ ToDraw &operator=(const ToDraw &);
+ void draw(QPainter &, const QRect &, const QRect *, const QPixmap *, const QBitmap *) const;
+ void save(FILE *) const;
+ bool load(FILE *, int, bool &);
+
+ inline int getNumber() const { return number; }
+ inline void setNumber(int newValue) { number = newValue; }
+ inline const QRect &getPosition() const { return position; }
+
+ private:
+ int number;
+ QRect position;
+};
+
+#endif
diff --git a/ktuberling/toplevel.cpp b/ktuberling/toplevel.cpp
new file mode 100644
index 00000000..d4ad647c
--- /dev/null
+++ b/ktuberling/toplevel.cpp
@@ -0,0 +1,611 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Top level window
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kio/netaccess.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kstdgameaction.h>
+
+#include <kprinter.h>
+#include <qclipboard.h>
+
+#include "toplevel.moc"
+#include "playground.h"
+#include "soundfactory.h"
+
+// Constructor
+TopLevel::TopLevel()
+ : KMainWindow(0)
+{
+ readOptions();
+
+ gameboards = 0;
+ languages = 0;
+ playGround = new PlayGround(this, "playground", selectedGameboard);
+ soundFactory = new SoundFactory(this, "sounds", selectedLanguage);
+
+ setCentralWidget(playGround);
+
+ setupKAction();
+}
+
+// Destructor
+TopLevel::~TopLevel()
+{
+}
+
+// Enable or disable "undo" button and menu item
+void TopLevel::enableUndo(bool enable) const
+{
+ actionCollection()->action(KStdAction::stdName(KStdAction::Undo))->setEnabled(enable);
+}
+
+// Enable or disable "redo" button and menu item
+void TopLevel::enableRedo(bool enable) const
+{
+ actionCollection()->action(KStdAction::stdName(KStdAction::Redo))->setEnabled(enable);
+}
+
+// Register an available gameboard
+void TopLevel::registerGameboard(const QString &menuItem, const char *actionId)
+{
+ KToggleAction *t = 0;
+
+ switch (gameboards)
+ {
+ case 0: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard0()), actionCollection(), actionId);
+ break;
+ case 1: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard1()), actionCollection(), actionId);
+ break;
+ case 2: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard2()), actionCollection(), actionId);
+ break;
+ case 3: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard3()), actionCollection(), actionId);
+ break;
+ case 4: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard4()), actionCollection(), actionId);
+ break;
+ case 5: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard5()), actionCollection(), actionId);
+ break;
+ case 6: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard6()), actionCollection(), actionId);
+ break;
+ case 7: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(gameboard7()), actionCollection(), actionId);
+ break;
+ }
+
+ if( t ) {
+ if (gameboards == selectedGameboard) t->setChecked(true);
+ gameboardActions[gameboards] = actionId;
+ gameboards++;
+ }
+}
+
+// Register an available language
+void TopLevel::registerLanguage(const QString &menuItem, const char *actionId, bool enabled)
+{
+ KToggleAction *t = 0;
+
+ switch (languages)
+ {
+ case 0: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language0()), actionCollection(), actionId);
+ break;
+ case 1: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language1()), actionCollection(), actionId);
+ break;
+ case 2: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language2()), actionCollection(), actionId);
+ break;
+ case 3: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language3()), actionCollection(), actionId);
+ break;
+ case 4: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language4()), actionCollection(), actionId);
+ break;
+ case 5: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language5()), actionCollection(), actionId);
+ break;
+ case 6: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language6()), actionCollection(), actionId);
+ break;
+ case 7: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language7()), actionCollection(), actionId);
+ break;
+ case 8: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language8()), actionCollection(), actionId);
+ break;
+ case 9: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language9()), actionCollection(), actionId);
+ break;
+ case 10: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language10()), actionCollection(), actionId);
+ break;
+ case 11: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language11()), actionCollection(), actionId);
+ break;
+ case 12: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language12()), actionCollection(), actionId);
+ break;
+ case 13: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language13()), actionCollection(), actionId);
+ break;
+ case 14: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language14()), actionCollection(), actionId);
+ break;
+ case 15: t = new KToggleAction(i18n(menuItem.latin1()), 0, this, SLOT(language15()), actionCollection(), actionId);
+ break;
+ }
+
+ if( t ) {
+ if (languages == selectedLanguage) t->setChecked(true);
+ t->setEnabled(enabled);
+ languageActions[languages] = actionId;
+ languages++;
+ }
+}
+
+// Switch to another gameboard
+void TopLevel::changeGameboard(uint newGameboard)
+{
+ // Do not accept to switch to same gameboard
+ if (newGameboard == selectedGameboard) {
+ // select this gameboard again
+ ((KToggleAction*) actionCollection()->action(gameboardActions[newGameboard].latin1()))->setChecked(true);
+ return;
+ }
+
+ // Unselect preceding gameboard
+ ((KToggleAction*) actionCollection()->action(gameboardActions[selectedGameboard].latin1()))->setChecked(false);
+
+ // Change gameboard in the remembered options
+ selectedGameboard = newGameboard;
+ writeOptions();
+
+ if( !((KToggleAction*) actionCollection()->action(gameboardActions[selectedGameboard].latin1()))->isChecked() )
+ ((KToggleAction*) actionCollection()->action(gameboardActions[selectedGameboard].latin1()))->setChecked(true);
+
+ // Change gameboard effectively
+ playGround->change(newGameboard);
+
+ // Disable undo and redo actions
+ enableUndo(false);
+ enableRedo(false);
+}
+
+// Switch to another language
+void TopLevel::changeLanguage(uint newLanguage)
+{
+ // Do not accept to switch to same language
+ if (newLanguage == selectedLanguage && soundEnabled) {
+ // newLanguage should stay checked
+ ((KToggleAction*) actionCollection()->action(languageActions[newLanguage].latin1()))->setChecked(true);
+ return;
+ }
+
+ // Unselect preceding language
+ if (!soundEnabled) ((KToggleAction*) actionCollection()->action("speech_no_sound"))->setChecked(false);
+ ((KToggleAction*) actionCollection()->action(languageActions[selectedLanguage].latin1()))->setChecked(false);
+
+ // Change language in the remembered options
+ soundEnabled = true;
+ selectedLanguage = newLanguage;
+ writeOptions();
+
+ // Change language effectively
+ soundFactory->change(newLanguage);
+}
+
+// Load the layouts file
+bool TopLevel::loadLayout(QDomDocument &layoutDocument)
+{
+ QFile layoutFile(QFile::encodeName(locate("data", "ktuberling/pics/layout.xml")));
+ if (!layoutFile.open(IO_ReadOnly))
+ return false;
+
+ if (!layoutDocument.setContent(&layoutFile))
+ {
+ layoutFile.close();
+ return false;
+ }
+ layoutFile.close();
+
+ return true;
+}
+
+// Play a sound
+void TopLevel::playSound(const QString &ref) const
+{
+ soundFactory->playSound(ref);
+}
+
+// Read options from preferences file
+void TopLevel::readOptions()
+{
+ KConfig *config;
+ QString option;
+
+ config = KApplication::kApplication()->config();
+
+ config->setGroup("General");
+ option = config->readEntry("Sound", "on");
+ soundEnabled = option.find("on") == 0;
+
+ option = config->readEntry("GameboardNumber", "0");
+ selectedGameboard = option.toInt();
+ if (selectedGameboard <= 0) selectedGameboard = 0;
+ if (selectedGameboard > 7) selectedGameboard = 7;
+
+ option = config->readEntry("LanguageNumber", "2");
+ selectedLanguage = option.toInt();
+ if (selectedLanguage <= 0) selectedLanguage = 0;
+ if (selectedLanguage > 15) selectedLanguage = 15;
+
+}
+
+// Write options to preferences file
+void TopLevel::writeOptions()
+{
+ KConfig *config;
+
+ config = KApplication::kApplication()->config();
+
+ config->setGroup("General");
+ config->writeEntry("Sound", soundEnabled? "on": "off");
+
+ config->writeEntry("GameboardNumber", selectedGameboard);
+
+ config->writeEntry("LanguageNumber", selectedLanguage);
+
+ config->sync();
+}
+
+// KAction initialization (aka menubar + toolbar init)
+void TopLevel::setupKAction()
+{
+//Game
+ KStdGameAction::gameNew(this, SLOT(fileNew()), actionCollection());
+ KStdGameAction::load(this, SLOT(fileOpen()), actionCollection());
+ KStdGameAction::save(this, SLOT(fileSave()), actionCollection());
+ KStdGameAction::print(this, SLOT(filePrint()), actionCollection());
+ KStdGameAction::quit(kapp, SLOT(quit()), actionCollection());
+ (void) new KAction(i18n("Save &as Picture..."), 0, this, SLOT(filePicture()), actionCollection(), "game_save_picture");
+
+//Edit
+ KStdAction::copy(this, SLOT(editCopy()), actionCollection());
+ KStdAction::undo(this, SLOT(editUndo()), actionCollection());
+ KStdAction::redo(this, SLOT(editRedo()), actionCollection());
+ enableUndo(false);
+ enableRedo(false);
+
+//Speech
+ KToggleAction* t = new KToggleAction(i18n("&No Sound"), 0, this, SLOT(soundOff()), actionCollection(), "speech_no_sound");
+ if (!soundEnabled) t->setChecked(true);
+
+ setupGUI();
+}
+
+// Reset gameboard
+void TopLevel::fileNew()
+{
+ playGround->reset();
+
+ enableUndo(false);
+ enableRedo(false);
+
+ playGround->repaintAll();
+}
+
+// Load gameboard
+void TopLevel::fileOpen()
+{
+ QString dir = locate("data", "ktuberling/museum/miss.tuberling");
+ dir.truncate(dir.findRev('/') + 1);
+
+ KURL url = KFileDialog::getOpenURL(dir, "*.tuberling");
+
+ open(url);
+}
+
+void TopLevel::open(const KURL &url)
+{
+ if (url.isEmpty())
+ return;
+
+ QString name;
+
+ KIO::NetAccess::download(url, name, this);
+
+ playGround->reset();
+
+ if (!playGround->loadFrom(name))
+ KMessageBox::error(this, i18n("Could not load file."));
+
+ enableUndo(!playGround->isFirstAction());
+ enableRedo(false);
+
+ playGround->repaintAll();
+
+ KIO::NetAccess::removeTempFile( name );
+}
+
+// Save gameboard
+void TopLevel::fileSave()
+{
+ KURL url = KFileDialog::getSaveURL
+ ( QString::null,
+ "*.tuberling");
+
+ if (url.isEmpty())
+ return;
+
+ if( !url.isLocalFile() )
+ {
+ KMessageBox::sorry(this,
+ i18n("Only saving to local files is currently "
+ "supported."));
+ return;
+ }
+
+ QString name = url.path();
+ int suffix;
+
+ suffix = name.findRev('.');
+ if (suffix == -1)
+ {
+ name += ".tuberling";
+ }
+
+ if( !playGround->saveAs( name ) )
+ KMessageBox::error(this, i18n("Could not save file."));
+}
+
+// Save gameboard as picture
+void TopLevel::filePicture()
+{
+ QPixmap picture(playGround->getPicture());
+
+ KURL url = KFileDialog::getSaveURL
+ ( QString::null,
+ i18n( "*.xpm|UNIX Pixmaps (*.xpm)\n"
+ "*.jpg|JPEG Compressed Files (*.jpg)\n"
+ "*.png|Next Generation Pictures (*.png)\n"
+ "*.bmp|Windows Bitmaps (*.bmp)\n"
+ "*|All Picture Formats"));
+
+ if( url.isEmpty() )
+ return;
+
+ if( !url.isLocalFile() )
+ {
+ KMessageBox::sorry(this,
+ i18n("Only saving to local files is currently "
+ "supported."));
+ return;
+ }
+
+ QString name = url.path();
+ const char *format;
+ int suffix;
+ QString end;
+
+ suffix = name.findRev('.');
+ if (suffix == -1)
+ {
+ name += ".xpm";
+ end = "xpm";
+ }
+ else end = name.mid(suffix + 1, name.length());
+
+ if (end == "xpm") format = "XPM";
+ else if (end == "jpg") format = "JPEG";
+ else if (end == "png") format = "PNG";
+ else if (end == "bmp") format = "BMP";
+ else
+ {
+ KMessageBox::error(this, i18n("Unknown picture format."));
+ return;
+ }
+
+ if (!picture.save(name, format))
+ KMessageBox::error
+ (this, i18n("Could not save file."));
+}
+
+// Save gameboard as picture
+void TopLevel::filePrint()
+{
+ KPrinter printer;
+ bool ok;
+
+ ok = printer.setup(this, i18n("Print %1").arg(actionCollection()->action(gameboardActions[selectedGameboard].latin1())->plainText()));
+ if (!ok) return;
+ playGround->repaint(true);
+ if (!playGround->printPicture(printer))
+ KMessageBox::error(this,
+ i18n("Could not print picture."));
+ else
+ KMessageBox::information(this,
+ i18n("Picture successfully printed."));
+}
+
+// Copy modified area to clipboard
+void TopLevel::editCopy()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ QPixmap picture(playGround->getPicture());
+
+ clipboard->setPixmap(picture);
+}
+
+// Undo last action
+void TopLevel::editUndo()
+{
+ if (playGround->isFirstAction()) return;
+
+ if (!playGround->undo()) return;
+
+ if (playGround->isFirstAction()) enableUndo(false);
+ enableRedo(true);
+
+ playGround->repaintAll();
+}
+
+// Redo last action
+void TopLevel::editRedo()
+{
+ if (playGround->isLastAction()) return;
+
+ if (!playGround->redo()) return;
+
+ if (playGround->isLastAction()) enableRedo(false);
+ enableUndo(true);
+
+ playGround->repaintAll();
+}
+
+// Switch to gameboard #0
+void TopLevel::gameboard0()
+{
+ changeGameboard(0);
+}
+
+// Switch to gameboard #1
+void TopLevel::gameboard1()
+{
+ changeGameboard(1);
+}
+
+// Switch to gameboard #2
+void TopLevel::gameboard2()
+{
+ changeGameboard(2);
+}
+
+// Switch to gameboard #3
+void TopLevel::gameboard3()
+{
+ changeGameboard(3);
+}
+
+// Switch to gameboard #4
+void TopLevel::gameboard4()
+{
+ changeGameboard(4);
+}
+
+// Switch to gameboard #5
+void TopLevel::gameboard5()
+{
+ changeGameboard(5);
+}
+
+// Switch to gameboard #6
+void TopLevel::gameboard6()
+{
+ changeGameboard(6);
+}
+
+// Switch to gameboard #7
+void TopLevel::gameboard7()
+{
+ changeGameboard(7);
+}
+
+// Toggle sound off
+void TopLevel::soundOff()
+{
+ if (!soundEnabled) return;
+
+ soundEnabled = false;
+ ((KToggleAction*) actionCollection()->action(languageActions[selectedLanguage].latin1()))->setChecked(false);
+ ((KToggleAction*) actionCollection()->action("speech_no_sound"))->setChecked(true);
+
+ writeOptions();
+}
+
+// Switch to language #0
+void TopLevel::language0()
+{
+ changeLanguage(0);
+}
+
+// Switch to language #1
+void TopLevel::language1()
+{
+ changeLanguage(1);
+}
+
+// Switch to language #2
+void TopLevel::language2()
+{
+ changeLanguage(2);
+}
+
+// Switch to language #3
+void TopLevel::language3()
+{
+ changeLanguage(3);
+}
+
+// Switch to language #4
+void TopLevel::language4()
+{
+ changeLanguage(4);
+}
+
+// Switch to language #5
+void TopLevel::language5()
+{
+ changeLanguage(5);
+}
+
+// Switch to language #6
+void TopLevel::language6()
+{
+ changeLanguage(6);
+}
+
+// Switch to language #7
+void TopLevel::language7()
+{
+ changeLanguage(7);
+}
+
+// Switch to language #8
+void TopLevel::language8()
+{
+ changeLanguage(8);
+}
+
+// Switch to language #9
+void TopLevel::language9()
+{
+ changeLanguage(9);
+}
+
+// Switch to language #10
+void TopLevel::language10()
+{
+ changeLanguage(10);
+}
+
+// Switch to language #11
+void TopLevel::language11()
+{
+ changeLanguage(11);
+}
+
+// Switch to language #12
+void TopLevel::language12()
+{
+ changeLanguage(12);
+}
+
+// Switch to language #13
+void TopLevel::language13()
+{
+ changeLanguage(13);
+}
+
+// Switch to language #14
+void TopLevel::language14()
+{
+ changeLanguage(14);
+}
+
+// Switch to language #15
+void TopLevel::language15()
+{
+ changeLanguage(15);
+}
diff --git a/ktuberling/toplevel.h b/ktuberling/toplevel.h
new file mode 100644
index 00000000..8d67a252
--- /dev/null
+++ b/ktuberling/toplevel.h
@@ -0,0 +1,105 @@
+/* -------------------------------------------------------------
+ KDE Tuberling
+ Top level window
+ mailto:e.bischoff@noos.fr
+ ------------------------------------------------------------- */
+
+
+#ifndef _TOPLEVEL_H_
+#define _TOPLEVEL_H_
+
+#include <kmainwindow.h>
+#include <kurl.h>
+
+class QDomDocument;
+class PlayGround;
+class SoundFactory;
+
+class TopLevel : public KMainWindow
+{
+ Q_OBJECT
+
+public:
+
+ TopLevel();
+ ~TopLevel();
+
+ void open(const KURL &url);
+ void enableUndo(bool enable) const;
+ void enableRedo(bool enable) const;
+ void registerGameboard(const QString &menuItem, const char *actionId);
+ void registerLanguage(const QString &menuItem, const char *actionId, bool enabled);
+ void changeGameboard(uint newGameboard);
+ void changeLanguage(uint newLanguage);
+ bool loadLayout(QDomDocument &layoutDocument);
+ void playSound(const QString &ref) const;
+
+ inline bool isSoundEnabled() const {return soundEnabled;}
+ inline uint getSelectedGameboard() const {return selectedGameboard;}
+
+protected:
+
+ void readOptions();
+ void writeOptions();
+ void setupKAction();
+
+private slots:
+
+ void fileNew();
+ void fileOpen();
+ void fileSave();
+ void filePicture();
+ void filePrint();
+ void editCopy();
+ void editUndo();
+ void editRedo();
+ void gameboard0();
+ void gameboard1();
+ void gameboard2();
+ void gameboard3();
+ void gameboard4();
+ void gameboard5();
+ void gameboard6();
+ void gameboard7();
+ void soundOff();
+ void language0();
+ void language1();
+ void language2();
+ void language3();
+ void language4();
+ void language5();
+ void language6();
+ void language7();
+ void language8();
+ void language9();
+ void language10();
+ void language11();
+ void language12();
+ void language13();
+ void language14();
+ void language15();
+
+private:
+
+ int // Menu items identificators
+ newID, openID, saveID, pictureID, printID, quitID,
+ copyID, undoID, redoID,
+ gameboardID, speechID;
+ enum { // Tool bar buttons identificators
+ ID_NEW, ID_OPEN, ID_SAVE, ID_PRINT,
+ ID_UNDO, ID_REDO,
+ ID_HELP };
+
+ bool soundEnabled; // True if the sound is enabled by user, even if there is no audio server
+ uint selectedGameboard, // Number of currently selected gameboard
+ gameboards; // Total number of gameboards
+ uint selectedLanguage, // Number of selected language
+ languages; // Total number of languages
+ QString gameboardActions[8], // Name of actions for registered gameboards
+ languageActions[16]; // Name of actions for registered languages
+
+ PlayGround *playGround; // Play ground central widget
+ SoundFactory *soundFactory; // Speech organ
+};
+
+#endif
diff --git a/ktuberling/x-tuberling.desktop b/ktuberling/x-tuberling.desktop
new file mode 100644
index 00000000..9d62b1ab
--- /dev/null
+++ b/ktuberling/x-tuberling.desktop
@@ -0,0 +1,61 @@
+# KDE Config File
+[Desktop Entry]
+MimeType=application/x-tuberling
+Comment=Potato
+Comment[ar]=بطاطا
+Comment[be]=Клубень
+Comment[bg]=Картоф
+Comment[bn]=আলু
+Comment[br]=Patatez
+Comment[bs]=Krompir
+Comment[cs]=Brambora
+Comment[da]=Kartoffel
+Comment[de]=Kartoffel
+Comment[el]=Πατάτα
+Comment[eo]=Terpomo
+Comment[es]=Papá Patata
+Comment[et]=Kartulimees
+Comment[eu]=Patata
+Comment[fa]=سیب‌زمینی
+Comment[fi]=Peruna
+Comment[fr]=Patate
+Comment[ga]=Práta
+Comment[gl]=Pataca
+Comment[he]=תפוח אדמה
+Comment[hi]=पोटैटो
+Comment[hr]=Krumpirko
+Comment[hu]=Krumpli
+Comment[is]=Kartafla
+Comment[it]=Patata
+Comment[ja]=ポテト
+Comment[km]=ដំឡូង
+Comment[lt]=Bulvė
+Comment[lv]=Kartupelis
+Comment[mk]=Компир
+Comment[nb]=Potet
+Comment[nds]=Kantüffel
+Comment[ne]=पोटेटो
+Comment[nl]=Aardappel
+Comment[nn]=Potet
+Comment[pa]=ਆਲੂ
+Comment[pl]=Ziemniak
+Comment[pt]=Batata
+Comment[pt_BR]=Batata
+Comment[se]=Buđet
+Comment[sk]=Zemiak
+Comment[sl]=Krompirček
+Comment[sv]=Potatis
+Comment[ta]=உருளைகிழங்கு
+Comment[tg]=Картошка
+Comment[tr]=Patates
+Comment[uk]=Картопля
+Comment[wa]=Crompire
+Comment[zh_CN]=土豆
+Comment[zh_TW]=馬鈴薯
+Icon=ktuberling
+Type=MimeType
+Patterns=*.tuberling;
+X-KDE-AutoEmbed=false
+[Property::X-KDE-NativeExtension]
+Type=QString
+Value=.tuberling