00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "lists.h"
00019
00020 #include "object_constructor.h"
00021 #include "guiaction.h"
00022 #include "object_hierarchy.h"
00023 #include "../kig/kig_part.h"
00024
00025 #include <klocale.h>
00026 #include <kmessagebox.h>
00027 #include <qfile.h>
00028 #include <qtextstream.h>
00029 #include <qdom.h>
00030 #include <qregexp.h>
00031 #include <algorithm>
00032 using namespace std;
00033
00034 template<typename T>
00035 void vect_remove( std::vector<T>& v, const T& t )
00036 {
00037 typename std::vector<T>::iterator new_end = std::remove( v.begin(), v.end(), t );
00038 v.erase( new_end, v.end() );
00039 }
00040
00041 GUIActionList* GUIActionList::instance()
00042 {
00043 static GUIActionList l;
00044 return &l;
00045 }
00046
00047 GUIActionList::~GUIActionList()
00048 {
00049 for ( avectype::iterator i = mactions.begin(); i != mactions.end(); ++i )
00050 delete *i;
00051 }
00052
00053 GUIActionList::GUIActionList()
00054 {
00055 }
00056
00057 void GUIActionList::regDoc( KigPart* d )
00058 {
00059 mdocs.insert( d );
00060 }
00061
00062 void GUIActionList::unregDoc( KigPart* d )
00063 {
00064 mdocs.erase( d );
00065 }
00066
00067 void GUIActionList::add( const std::vector<GUIAction*>& a )
00068 {
00069 copy( a.begin(), a.end(), inserter( mactions, mactions.begin() ) );
00070 for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i )
00071 {
00072 KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate();
00073 for ( uint j = 0; j < a.size(); ++j )
00074 (*i)->actionAdded( a[j], t );
00075 (*i)->endGUIActionUpdate( t );
00076 };
00077 }
00078
00079 void GUIActionList::add( GUIAction* a )
00080 {
00081 mactions.insert( a );
00082 for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i )
00083 {
00084 KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate();
00085 (*i)->actionAdded( a, t );
00086 (*i)->endGUIActionUpdate( t );
00087 };
00088 }
00089
00090 void GUIActionList::remove( const std::vector<GUIAction*>& a )
00091 {
00092 for ( uint i = 0; i < a.size(); ++i )
00093 {
00094 mactions.erase( a[i] );
00095 };
00096 for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i )
00097 {
00098 KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate();
00099 for ( uint j = 0; j < a.size(); ++j )
00100 (*i)->actionRemoved( a[j], t );
00101 (*i)->endGUIActionUpdate( t );
00102 };
00103 delete_all( a.begin(), a.end() );
00104 }
00105
00106 void GUIActionList::remove( GUIAction* a )
00107 {
00108 mactions.erase( a );
00109 for ( dvectype::iterator i = mdocs.begin(); i != mdocs.end(); ++i )
00110 {
00111 KigPart::GUIUpdateToken t = (*i)->startGUIActionUpdate();
00112 (*i)->actionRemoved( a, t );
00113 (*i)->endGUIActionUpdate( t );
00114 };
00115 delete a;
00116 }
00117
00118 ObjectConstructorList::ObjectConstructorList()
00119 {
00120 }
00121
00122 ObjectConstructorList::~ObjectConstructorList()
00123 {
00124 for ( vectype::iterator i = mctors.begin(); i != mctors.end(); ++i )
00125 delete *i;
00126 }
00127
00128 ObjectConstructorList* ObjectConstructorList::instance()
00129 {
00130 static ObjectConstructorList s;
00131 return &s;
00132 }
00133
00134 ObjectConstructorList::vectype ObjectConstructorList::ctorsThatWantArgs(
00135 const std::vector<ObjectCalcer*>& os, const KigDocument& d,
00136 const KigWidget& w, bool co ) const
00137 {
00138 vectype ret;
00139 for ( vectype::const_iterator i = mctors.begin(); i != mctors.end(); ++i )
00140 {
00141 int r = (*i)->wantArgs( os, d, w );
00142 if ( r == ArgsParser::Complete || ( !co && r == ArgsParser::Valid ) )
00143 ret.push_back( *i );
00144 };
00145 return ret;
00146 }
00147
00148 void ObjectConstructorList::remove( ObjectConstructor* a )
00149 {
00150 vect_remove( mctors, a );
00151 delete a;
00152 }
00153
00154 void ObjectConstructorList::add( ObjectConstructor* a )
00155 {
00156 mctors.push_back( a );
00157 }
00158
00159 Macro::Macro( GUIAction* a, MacroConstructor* c )
00160 : action( a ), ctor( c )
00161 {
00162 }
00163
00164 bool operator==( const Macro& l, const Macro& r )
00165 {
00166 return ( l.action->descriptiveName() == r.action->descriptiveName() ) &&
00167 ( l.action->description() == r.action->description() ) &&
00168 ( l.action->iconFileName() == r.action->iconFileName() );
00169 }
00170
00171 MacroList::MacroList()
00172 {
00173 }
00174
00175 MacroList::~MacroList()
00176 {
00177 std::vector<GUIAction*> actions;
00178 std::vector<ObjectConstructor*> ctors;
00179 for ( vectype::iterator i = mdata.begin(); i != mdata.end(); ++i )
00180 {
00181 Macro* m = *i;
00182 GUIAction* a = m->action;
00183 actions.push_back( a );
00184 ObjectConstructor* c = m->ctor;
00185 ctors.push_back( c );
00186 delete m;
00187 };
00188 mdata.clear();
00189 GUIActionList::instance()->remove( actions );
00190 for ( uint i = 0; i < ctors.size(); ++i )
00191 ObjectConstructorList::instance()->remove( ctors[i] );
00192 }
00193
00194 MacroList* MacroList::instance()
00195 {
00196 static MacroList t;
00197 return &t;
00198 }
00199
00200 void MacroList::add( const std::vector<Macro*>& ms )
00201 {
00202 copy( ms.begin(), ms.end(), back_inserter( mdata ) );
00203 std::vector<GUIAction*> acts;
00204 for ( uint i = 0; i < ms.size(); ++i )
00205 {
00206 ObjectConstructorList::instance()->add( ms[i]->ctor );
00207 acts.push_back( ms[i]->action );
00208 };
00209 GUIActionList::instance()->add( acts );
00210 }
00211
00212 void MacroList::add( Macro* m )
00213 {
00214 mdata.push_back( m );
00215 ObjectConstructorList::instance()->add( m->ctor );
00216 GUIActionList::instance()->add( m->action );
00217 }
00218
00219 void MacroList::remove( Macro* m )
00220 {
00221 GUIAction* a = m->action;
00222 ObjectConstructor* c = m->ctor;
00223 mdata.erase( std::remove( mdata.begin(), mdata.end(), m ),
00224 mdata.end() );
00225 delete m;
00226 GUIActionList::instance()->remove( a );
00227 ObjectConstructorList::instance()->remove( c );
00228 }
00229
00230 const MacroList::vectype& MacroList::macros() const
00231 {
00232 return mdata;
00233 }
00234
00235 Macro::~Macro()
00236 {
00237 }
00238
00239 bool MacroList::save( Macro* m, const QString& f )
00240 {
00241 std::vector<Macro*> ms;
00242 ms.push_back( m );
00243 return save( ms, f );
00244 }
00245
00246 bool MacroList::save( const std::vector<Macro*>& ms, const QString& f )
00247 {
00248 QDomDocument doc( "KigMacroFile" );
00249
00250 QDomElement docelem = doc.createElement( "KigMacroFile" );
00251 docelem.setAttribute( "Version", KIGVERSION );
00252 docelem.setAttribute( "Number", static_cast<uint>( ms.size() ) );
00253
00254 for ( uint i = 0; i < ms.size(); ++i )
00255 {
00256 MacroConstructor* ctor = ms[i]->ctor;
00257
00258 QDomElement macroelem = doc.createElement( "Macro" );
00259
00260
00261 QDomElement nameelem = doc.createElement( "Name" );
00262 nameelem.appendChild( doc.createTextNode( ctor->descriptiveName() ) );
00263 macroelem.appendChild( nameelem );
00264
00265
00266 QDomElement descelem = doc.createElement( "Description" );
00267 descelem.appendChild( doc.createTextNode( ctor->description() ) );
00268 macroelem.appendChild( descelem );
00269
00270
00271 QByteArray icon = ctor->iconFileName( true );
00272 if ( !icon.isNull() )
00273 {
00274 QDomElement descelem = doc.createElement( "IconFileName" );
00275 descelem.appendChild( doc.createTextNode( icon ) );
00276 macroelem.appendChild( descelem );
00277 }
00278
00279
00280 QDomElement hierelem = doc.createElement( "Construction" );
00281 ctor->hierarchy().serialize( hierelem, doc );
00282 macroelem.appendChild( hierelem );
00283
00284 docelem.appendChild( macroelem );
00285 };
00286
00287 doc.appendChild( docelem );
00288
00289 QFile file( f );
00290 if ( ! file.open( QIODevice::WriteOnly ) )
00291 return false;
00292 QTextStream stream( &file );
00293 stream << doc.toByteArray();
00294 return true;
00295 }
00296
00297 bool MacroList::load( const QString& f, std::vector<Macro*>& ret, const KigPart& kdoc )
00298 {
00299 QFile file( f );
00300 if ( ! file.open( QIODevice::ReadOnly ) )
00301 {
00302 KMessageBox::sorry( 0, i18n( "Could not open macro file '%1'", f ) );
00303 return false;
00304 }
00305 QDomDocument doc( "KigMacroFile" );
00306 if ( !doc.setContent( &file ) )
00307 {
00308 KMessageBox::sorry( 0, i18n( "Could not open macro file '%1'", f ) );
00309 return false;
00310 }
00311 file.close();
00312 QDomElement main = doc.documentElement();
00313
00314 if ( main.tagName() == "KigMacroFile" )
00315 return loadNew( main, ret, kdoc );
00316 else
00317 {
00318 KMessageBox::detailedSorry(
00319 0, i18n( "Kig cannot open the macro file \"%1\".", f ),
00320 i18n( "This file was created by a very old Kig version (pre-0.4). "
00321 "Support for this format has been removed from recent Kig versions. "
00322 "You can try to import this macro using a previous Kig version "
00323 "(0.4 to 0.6) and then export it again in the new format." ),
00324 i18n( "Not Supported" ) );
00325 return false;
00326 }
00327 }
00328
00329 bool MacroList::loadNew( const QDomElement& docelem, std::vector<Macro*>& ret, const KigPart& )
00330 {
00331 bool sok = true;
00332
00333
00334 if ( ! sok ) return false;
00335
00336 QString version = docelem.attribute( "Version" );
00337
00338
00339
00340
00341
00342
00343
00344
00345 int unnamedindex = 1;
00346 QString tmp;
00347
00348 for ( QDomElement macroelem = docelem.firstChild().toElement();
00349 ! macroelem.isNull(); macroelem = macroelem.nextSibling().toElement() )
00350 {
00351 QString name, description;
00352 ObjectHierarchy* hierarchy = 0;
00353 QByteArray actionname;
00354 QByteArray iconfile( "system-run" );
00355 if ( macroelem.tagName() != "Macro" ) continue;
00356 for ( QDomElement dataelem = macroelem.firstChild().toElement();
00357 ! dataelem.isNull(); dataelem = dataelem.nextSibling().toElement() )
00358 {
00359 if ( dataelem.tagName() == "Name" )
00360 name = dataelem.text();
00361 else if ( dataelem.tagName() == "Description" )
00362 description = dataelem.text();
00363 else if ( dataelem.tagName() == "Construction" )
00364 hierarchy = ObjectHierarchy::buildSafeObjectHierarchy( dataelem, tmp );
00365 else if ( dataelem.tagName() == "ActionName" )
00366 actionname = dataelem.text().toLatin1();
00367 else if ( dataelem.tagName() == "IconFileName" )
00368 iconfile = dataelem.text().toLatin1();
00369 else continue;
00370 };
00371 assert( hierarchy );
00372
00373 bool name_i18ned = false;
00374 if ( name.isEmpty() )
00375 {
00376 name = i18n( "Unnamed Macro #%1", unnamedindex++ );
00377 name_i18ned = true;
00378 }
00379 MacroConstructor* ctor =
00380 new MacroConstructor( *hierarchy, name_i18ned ? name : i18n( name.toUtf8() ),
00381 description.isEmpty() ? QString() : i18n( description.toUtf8() ),
00382 iconfile );
00383 delete hierarchy;
00384 GUIAction* act = new ConstructibleAction( ctor, actionname );
00385 Macro* macro = new Macro( act, ctor );
00386 ret.push_back( macro );
00387 };
00388 return true;
00389 }
00390
00391 const ObjectConstructorList::vectype& ObjectConstructorList::constructors() const
00392 {
00393 return mctors;
00394 }