2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
17 #include <KConfigGroup>
18 #include <KDesktopFile>
19 #include <KStandardDirs>
22 #include "loader/image.h"
23 #include "luaapi/imaging.h"
24 #include "luaapi/loader.h"
25 #include "luaapi/options.h"
26 #include "themeinfo.h"
30 const luaL_Reg
Loader::lualibs
[] = {
32 {LUA_LOADLIBNAME
, luaopen_package
},
33 {LUA_TABLIBNAME
, luaopen_table
},
34 {LUA_IOLIBNAME
, luaopen_io
},
35 {LUA_OSLIBNAME
, luaopen_os
},
36 {LUA_STRLIBNAME
, luaopen_string
},
37 {LUA_MATHLIBNAME
, luaopen_math
},
38 {LUA_DBLIBNAME
, luaopen_debug
},
39 {LUA_FUNCLIBNAME
, luaopen_func
},
40 {LUA_COLLECTLIBNAME
, luaopen_collect
},
48 lua_newtable(m_state
);
49 lua_setglobal(m_state
, "theme");
52 Loader::Loader(::Loader::Context
*ctx
, const ThemeInfo
& theme
)
58 void Loader::addMetaData(const ThemeInfo
& theme
) {
59 lua_State
* const l
= m_state
;
63 #define ADD_FIELD_AUX(FIELD_NAME, FIELD) \
64 lua_pushstring(l, FIELD_NAME); \
65 lua_pushstring(l, qPrintable(theme.FIELD)); \
67 #define ADD_FIELD(FIELD) ADD_FIELD_AUX(#FIELD, FIELD)
70 ADD_FIELD(description
);
71 ADD_FIELD_AUX("desktop_file", desktopFile
);
73 lua_pushstring(l
, "variants");
75 for (int i
= 0; i
< theme
.variants
.size(); i
++) {
77 lua_pushstring(l
, qPrintable(theme
.variants
[i
]));
85 lua_setglobal(l
, "theme");
88 void Loader::initialize(::Loader::Context
*ctx
) {
89 lua_State
* l
= lua_open();
92 for (const luaL_Reg
*lib
= lualibs
; lib
->func
; lib
++) {
93 lua_pushcfunction(l
, lib
->func
);
94 lua_pushstring(l
, lib
->name
);
98 Wrapper
<QRectF
>::register_class(l
);
99 Wrapper
<QPointF
>::register_class(l
);
100 Wrapper
<QColor
>::register_class(l
);
101 Wrapper
<QLinearGradient
>::register_class(l
);
102 Wrapper
<QRadialGradient
>::register_class(l
);
103 Wrapper
<QConicalGradient
>::register_class(l
);
104 Wrapper
<QBrush
>::register_class(l
);
105 Wrapper
<QFont
>::register_class(l
);
106 Wrapper
< ::Loader::Image
>::register_class(l
);
107 Wrapper
< ::Loader::Glyph
>::register_class(l
);
109 Wrapper
<OptList
>::register_class(l
);
110 Wrapper
<BoolOptList
>::register_class(l
);
111 Wrapper
<BoolOptPtr
>::register_class(l
);
112 Wrapper
<IntOptPtr
>::register_class(l
);
113 Wrapper
<StringOptPtr
>::register_class(l
);
114 Wrapper
<UrlOptPtr
>::register_class(l
);
115 Wrapper
<ColorOptPtr
>::register_class(l
);
116 Wrapper
<FontOptPtr
>::register_class(l
);
117 Wrapper
<ComboOptPtr
>::register_class(l
);
118 Wrapper
<SelectOptPtr
>::register_class(l
);
120 lua_pushlightuserdata(l
, ctx
);
121 lua_setfield(l
, LUA_REGISTRYINDEX
, LOADING_CONTEXT
);
123 lua_pushlightuserdata(l
, this);
124 lua_setfield(l
, LUA_REGISTRYINDEX
, API_LOADER
);
126 lua_pushlightuserdata(m_state
, &m_curr_dir
);
127 lua_setfield(m_state
, LUA_REGISTRYINDEX
, CURRENT_DIRECTORY
);
129 lua_pushcfunction(l
, import_func
);
130 lua_setglobal(l
, "import");
137 bool Loader::runFile(const QString
& file
, bool setdir
) {
139 QString path
= QDir::cleanPath(
140 QDir::isAbsolutePath(file
) ? file
: m_curr_dir
.filePath(file
) );
141 if (!QFile::exists(path
)) {
142 // find it in the scripts dir
143 path
= KStandardDirs::locate("appdata", "scripts/" + file
);
145 if (!QFile::exists(path
)) {
151 QFileInfo
f_info( path
);
152 m_curr_dir
= f_info
.dir();
156 if(luaL_loadfile(m_state
, path
.toAscii().constData()) == 0) {
157 if(lua_pcall(m_state
, 0, LUA_MULTRET
, 0) != 0)
167 m_error_string
= QString(lua_tostring(m_state
, -1));
175 struct Loader::create_value_data
{
178 const LuaValueMap
* args
;
181 create_value_data(const QString
& _key
, int _size
, const LuaValueMap
* _args
, bool _allow_nil
)
185 , allow_nil(_allow_nil
) {
190 T
Loader::getValue(const QString
& key
, int size
, const LuaValueMap
* args
, bool allow_nil
) {
191 StackCheck
s(m_state
);
193 create_value_data
<T
> data(key
, size
, args
, allow_nil
);
194 if(lua_cpcall(m_state
, create_value_func
<T
>, &data
) != 0) {
196 m_error_string
= QString(lua_tostring(m_state
, -1))+"\nsearched key was: "+key
;
203 template ::Loader::Glyph
Loader::getValue
< ::Loader::Glyph
>(const QString
&, int, const LuaValueMap
*, bool);
204 template OptList
Loader::getValue
<OptList
>(const QString
&, int, const LuaValueMap
*, bool);
205 template QString
Loader::getValue
<QString
>(const QString
&, int, const LuaValueMap
*, bool);
206 template QStringList
Loader::getValue
<QStringList
>(const QString
&, int, const LuaValueMap
*, bool);
207 template QImage
Loader::getValue
<QImage
>(const QString
&, int, const LuaValueMap
*, bool);
208 template ImageOrMap
Loader::getValue
<ImageOrMap
>(const QString
&, int, const LuaValueMap
*, bool);
209 template double Loader::getValue
<double>(const QString
&, int, const LuaValueMap
*, bool);
210 template QPointF
Loader::getValue
<QPointF
>(const QString
&, int, const LuaValueMap
*, bool);
211 template QRectF
Loader::getValue
<QRectF
>(const QString
&, int, const LuaValueMap
*, bool);
212 template QColor
Loader::getValue
<QColor
>(const QString
&, int, const LuaValueMap
*, bool);
213 template QBrush
Loader::getValue
<QBrush
>(const QString
&, int, const LuaValueMap
*, bool);
214 template QFont
Loader::getValue
<QFont
>(const QString
&, int, const LuaValueMap
*, bool);
215 template LuaValueMap
Loader::getValue
<LuaValueMap
>(const QString
&, int, const LuaValueMap
*, bool);
218 void Loader::retrieve(create_value_data
<T
>* d
, lua_State
*l
, int pos
) {
219 d
->out
= *Wrapper
<T
>::retrieve(l
, pos
, AssertOk
);
223 void Loader::retrieve
<double>(create_value_data
<double>* d
, lua_State
*l
, int pos
) {
224 d
->out
= lua_tonumber(l
, pos
);
228 void Loader::retrieve
<QString
>(create_value_data
<QString
>* d
, lua_State
*l
, int pos
) {
229 d
->out
= lua_tostring(l
, pos
);
233 void Loader::retrieve
<QColor
>(create_value_data
<QColor
>* d
, lua_State
*l
, int pos
) {
234 d
->out
= Wrapper
<QColor
>::get(l
, pos
);
238 void Loader::retrieve
<QBrush
>(create_value_data
<QBrush
>* d
, lua_State
*l
, int pos
) {
239 d
->out
= Wrapper
<QBrush
>::get(l
, pos
);
243 void Loader::retrieve
<QStringList
>(create_value_data
<QStringList
>* d
, lua_State
*l
, int pos
) {
244 if(lua_isstring(l
, pos
))
245 d
->out
<< QString(lua_tostring(l
, -1));
246 else if(lua_istable(l
, pos
)) {
248 while (lua_next(l
, pos
<0 ? pos
-1 : pos
) != 0) {
249 d
->out
<< QString(lua_tostring(l
, -1));
254 luaL_error(l
, "Can't convert to a QStringList (not string nor table)");
258 void Loader::retrieve
<LuaValueMap
>(create_value_data
<LuaValueMap
>* d
, lua_State
*l
, int pos
) {
259 if(lua_istable(l
, pos
)) {
261 while (lua_next(l
, pos
<0 ? pos
-1 : pos
) != 0) {
262 QString key
= lua_tostring(l
, -2);
263 if(QPointF
*res
= Wrapper
<QPointF
>::retrieve(l
, -1, Check
))
265 else if(QRectF
*res
= Wrapper
<QRectF
>::retrieve(l
, -1, Check
))
268 d
->out
[key
] = lua_tonumber(l
, -1);
273 luaL_error(l
, "Can't convert to a LuaValueMap (not table)");
277 void Loader::retrieve
<QImage
>(create_value_data
<QImage
>* d
, lua_State
*l
, int pos
) {
278 ::Loader::Image
*retv
= Wrapper
< ::Loader::Image
>::retrieve(l
, pos
, AssertOk
);
279 d
->out
= retv
->image();
283 void Loader::retrieve
<ImageOrMap
>(create_value_data
<ImageOrMap
>* d
, lua_State
*l
, int pos
) {
284 if(::Loader::Image
*img
= Wrapper
< ::Loader::Image
>::retrieve(l
, pos
))
285 d
->out
= img
->image();
286 else if(lua_istable(l
, pos
)) {
288 //collect the images in this way to avoid leaking memory if Wrapper::retrieve raises an exception
290 ImageMap
& out
= boost::get
<ImageMap
>(d
->out
);
293 while (lua_next(l
, pos
<0 ? pos
-1 : pos
) != 0) {
294 QRectF
*rect
= Wrapper
<QRectF
>::retrieve(l
, -2, AssertOk
);
295 ::Loader::Image
*img
= Wrapper
< ::Loader::Image
>::retrieve(l
, -1, AssertOk
);
297 QRect r
= rect
->toRect();
298 out
[rect
->toRect()] = img
->image();
304 luaL_error(l
, "Can't convert to a ImageOrMap (not image nor table)");
308 int Loader::create_value_func(lua_State
*l
) {
310 create_value_data
<T
>* data
= reinterpret_cast<create_value_data
<T
>*>(lua_touserdata(l
, -1));
313 lua_getglobal(l
, "theme");
314 lua_getfield(l
, -1, data
->key
.toAscii().constData());
317 // If it is a function, call it
318 if(lua_isfunction(l
, -1)) {
321 lua_pushnumber(l
, data
->size
);
325 lua_pushvaluemap(l
, data
->args
);
328 lua_call(l
, nparams
, 1);
332 if (!lua_isnil(l
, -1)) {
333 retrieve
<T
>(data
, l
, -1);
335 else if (!data
->allow_nil
) {
336 luaL_error(l
, "No such entry: %s", data
->key
.toAscii().constData());
345 int Loader::import_func(lua_State
*l
) {
346 lua_getfield(l
, LUA_REGISTRYINDEX
, API_LOADER
);
347 Loader
* api
= reinterpret_cast<Loader
*>(lua_touserdata(l
, -1));
350 int n
= lua_gettop(l
);
352 luaL_error(l
, "Wrong argument count for \"import\"");
353 QString
file(lua_tostring(l
, 1));
356 if (!api
->runFile(file
, false)) {
357 luaL_error(l
, "Error importing \"%s\":\n%s", file
.toAscii().constData(),
358 api
->errorString().toAscii().constData() );
364 } // namespace LuaLoader