00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "include.hpp"
00017 #include <boost/shared_ptr.hpp>
00018 #include <fstream>
00019 #include <iostream>
00020 #include <kaboutdata.h>
00021 #include <kapplication.h>
00022 #include <kcmdlineargs.h>
00023 #include <kiconloader.h>
00024 #include <kmessagebox.h>
00025 #include <ksplashscreen.h>
00026 #include <magic.h>
00027 #include <mysql/mysql.h>
00028 #include <qimage.h>
00029 #include <qtextcodec.h>
00030 #include <XPath/XPathInit.hpp>
00031 #include <util/PlatformUtils.hpp>
00032 #include "anyMeal.h"
00033 #include "mealMasterCompiler.hpp"
00034 #include "mysqlDatabase.hpp"
00035 #include "mysqlNetwork.hpp"
00036 #include "recoder.hpp"
00037 #include "mealMasterStoreErroneousHandler.hpp"
00038 #include "utils.hpp"
00039 #include "xslCompiler.hpp"
00040 #include "xsu.hpp"
00041
00042 using namespace boost;
00043 using namespace std;
00044
00045
00046 static const KCmdLineOptions options[] = {
00047 { "i", 0, 0 },
00048 { "input <file>", I18N_NOOP( "Input file name (default: standard input)." ),
00049 0 },
00050 { "o", 0, 0 },
00051 { "output <file>", I18N_NOOP( "Output file name (default: standard "
00052 "output)." ), 0 },
00053 { "x", 0, 0 },
00054 { "mm2xml", I18N_NOOP( "Select Mealmaster to anyMeal-XML compiler" ), 0 },
00055 { "e", 0, 0 },
00056 { "mm2xmlerr <file>", I18N_NOOP( "Specify name of file for appending "
00057 "erroneous Mealmaster recipes." ), 0 },
00058 { "z", 0, 0 },
00059 { "xsu", I18N_NOOP( "Select XML-SQL-utility as compiler." ), 0 },
00060 { "s", 0, 0 },
00061 { "server <name>", I18N_NOOP( "Server hosting database. [localhost]" ), 0 },
00062 { "d", 0, 0 },
00063 { "database <name>", I18N_NOOP( "Name of MySQL database." ), 0 },
00064 { "u", 0, 0 },
00065 { "user <name>", I18N_NOOP( "User account for accessing database. "
00066 "[$USER]" ), 0 },
00067 { "p", 0, 0 },
00068 { "password <password>", I18N_NOOP( "Password of database user. []" ), 0 },
00069 { "q", 0, 0 },
00070 { "sqlin", I18N_NOOP( "Select XSL script for converting XML-queries to "
00071 "SQL" ), 0 },
00072 { "r", 0, 0 },
00073 { "sqlout", I18N_NOOP( "Select XSL script for converting raw XML to "
00074 "anyMeal-XML" ), 0 },
00075 { "b", 0, 0 },
00076 { "docbook", I18N_NOOP( "Select XSL script for converting anyMeal-XML "
00077 "to Docbook" ), 0 },
00078 { "l", 0, 0 },
00079 { "recipeml", I18N_NOOP( "Select XSL script for converting anyMeal-XML "
00080 "to RecipeML" ), 0 },
00081 { "t", 0, 0 },
00082 { "html", I18N_NOOP( "Select XSL script for converting Docbook to HTML" ),
00083 0 },
00084 { "f", 0, 0 },
00085 { "fo", I18N_NOOP( "Select XSL script for converting Docbook to Formatted "
00086 "Objects XML" ), 0 },
00087 { "m", 0, 0 },
00088 { "xml2mm", I18N_NOOP( "Select XML to Mealmaster compiler" ), 0 },
00089 { "y", 0, 0 },
00090 { "rm2xml", I18N_NOOP( "Select RecipeML to anyMeal-XML compiler" ), 0 },
00091 { "+[input file]", I18N_NOOP("Input file name (default: standard input)."),
00092 0 },
00093 KCmdLineLastOption };
00094
00095 bool cli(void) throw (Error)
00096 {
00097 bool guiDisabled = false;
00098
00099 KCmdLineArgs::addCmdLineOptions( options );
00100
00101 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
00102
00103
00104 const char
00105 *inputFileName = ( args->count() > 0 ? args->arg( 0 ) :
00106 args->getOption( "input" ).data() ),
00107 *outputFileName = args->getOption( "output" ).data(),
00108 *parseErrorFileName = args->getOption( "mm2xmlerr" ).data(),
00109 *server = args->getOption( "server" ).data(),
00110 *database = args->getOption( "database" ).data(),
00111 *user = ( args->getOption( "user" ).isEmpty() ?
00112 getenv( "USER" ) :
00113 args->getOption( "user" ).data() ),
00114 *password = args->getOption( "password" ).data();
00115
00116
00117 enum { NONE, MM2AnyMeal, SQL2RAW, XML2SQL, RAW2AnyMeal, AnyMeal2Docbook,
00118 AnyMeal2RecipeML, Docbook2HTML, Docbook2FO, AnyMeal2MM,
00119 RecipeML2AnyMeal } compiler = NONE;
00120 if ( args->isSet( "mm2xml" ) ) compiler = MM2AnyMeal;
00121 if ( args->isSet( "xsu" ) ) compiler = SQL2RAW;
00122 if ( args->isSet( "sqlin" ) ) compiler = XML2SQL;
00123 if ( args->isSet( "sqlout" ) ) compiler = RAW2AnyMeal;
00124 if ( args->isSet( "docbook" ) ) compiler = AnyMeal2Docbook;
00125 if ( args->isSet( "recipeml" ) ) compiler = AnyMeal2RecipeML;
00126 if ( args->isSet( "html" ) ) compiler = Docbook2HTML;
00127 if ( args->isSet( "fo" ) ) compiler = Docbook2FO;
00128 if ( args->isSet( "xml2mm" ) ) compiler = AnyMeal2MM;
00129 if ( args->isSet( "rm2xml" ) ) compiler = RecipeML2AnyMeal;
00130
00131 if ( compiler != NONE || inputFileName != NULL ||
00132 outputFileName != NULL || parseErrorFileName != NULL ||
00133 server != NULL || database != NULL || password != NULL ||
00134 user != getenv( "USER" ) ) {
00135
00136 guiDisabled = true;
00137
00138
00139 KApplication app( true, false );
00140
00141
00142 QTextCodec::setCodecForCStrings
00143 ( QTextCodec::codecForName( "UTF-8" ) );
00144
00145 try {
00146
00147
00148
00149
00150
00151
00152 ERRORMACRO( args->count() <= args->getOption( "input" ).isNull() ? 1 : 0,
00153 Error, ,
00154 i18n( "Only one input file may be specified." ) );
00155
00156
00157 shared_ptr< ifstream > inputFile;
00158 istream *input = &cin;
00159 if ( inputFileName ) {
00160 inputFile = shared_ptr< ifstream >( new ifstream( inputFileName,
00161 ios::binary ) );
00162 input = inputFile.get();
00163 };
00164
00165
00166 shared_ptr< ofstream > outputFile;
00167 ostream *output = &cout;
00168 if ( outputFileName ) {
00169 outputFile = shared_ptr< ofstream >( new ofstream( outputFileName,
00170 ios::binary ) );
00171 output = outputFile.get();
00172 };
00173
00174 switch ( compiler ) {
00175 case MM2AnyMeal: {
00176 shared_ptr< ostream > stream;
00177 MealMasterParseErrorHandlerPtr parseErrorHandler;
00178
00179 if ( parseErrorFileName != NULL ) {
00180 stream = shared_ptr< ostream >
00181 ( new ofstream( parseErrorFileName, ios::binary ) );
00182 parseErrorHandler = MealMasterParseErrorHandlerPtr
00183 ( new MealMasterStoreErroneousHandler( stream.get(), parseErrorFileName ) );
00184 } else
00185 parseErrorHandler = MealMasterParseErrorHandlerPtr( new MealMasterParseErrorHandler );
00186
00187 MealMasterCompiler( -1, parseErrorHandler ).translate( *input, *output );
00188 break;}
00189 case SQL2RAW: {
00190 ERRORMACRO( database != NULL, Error, ,
00191 i18n( "No datasource selected." ) );
00192 assert( user != NULL );
00193 DatabasePtr
00194 connection( new MySQLDatabase
00195 ( MySQLServerPtr
00196 ( new MySQLNetwork
00197 ( user, password == NULL ? "" : password,
00198 server == NULL ? "localhost" : server,
00199 MYSQL_PORT ) ),
00200 database ) );
00201 XSU( connection ).translate( *input, *output );
00202 break;}
00203 case XML2SQL: {
00204
00205
00206 string fileName( findAnyMealFile( "appdata", "scripts/mysqlIn.xsl" ) );
00207 XSLCompiler( fileName,
00208 FormatterListener::OUTPUT_METHOD_TEXT, SQLENCODING, "" ).
00209 translate( *input, *output );
00210 break;}
00211 case RAW2AnyMeal: {
00212 string fileName( findAnyMealFile( "appdata", "scripts/mysqlOut.xsl" ) );
00213 XSLCompiler( fileName,
00214 FormatterListener::OUTPUT_METHOD_XML, "UTF-8", "" ).
00215 translate( *input, *output );
00216 break;}
00217 case AnyMeal2Docbook: {
00218 string fileName( findAnyMealFile( "appdata",
00219 "scripts/recipeToDocbook.xsl" ) );
00220 XSLCompiler compiler
00221 ( fileName,
00222 FormatterListener::OUTPUT_METHOD_XML, HTMLENCODING,
00223 findAnyMealFile( "appdata", "scripts/anymeal.xsd" ) );
00224
00225 compiler.setParam( "lfile", string( "\"file://" ) + dictionaryFile() +
00226 "\"" );
00227 compiler.setParam( "lname", string( "\"" ) + anyMealLanguage() +
00228 "\"" );
00229 compiler.translate( *input, *output );
00230 break;}
00231 case AnyMeal2RecipeML: {
00232 string fileName( findAnyMealFile( "appdata",
00233 "scripts/recipeToRecipeML.xsl" ) );
00234 XSLCompiler( fileName,
00235 FormatterListener::OUTPUT_METHOD_XML, HTMLENCODING,
00236 findAnyMealFile( "appdata", "scripts/anymeal.xsd" ) ).
00237 translate( *input, *output );
00238 break;};
00239 case Docbook2HTML: {
00240 XSLCompiler( DOCBOOK"/html/docbook.xsl",
00241 FormatterListener::OUTPUT_METHOD_HTML, HTMLENCODING, "" ).
00242 translate( *input, *output );
00243 break;}
00244 case Docbook2FO: {
00245 string fileName( findAnyMealFile( "appdata",
00246 "scripts/docbookToFo.xsl" ) );
00247 XSLCompiler compiler
00248 ( fileName,
00249 FormatterListener::OUTPUT_METHOD_XML, HTMLENCODING, "" );
00250 compiler.setParam( "paper.type", "\"A4\"" );
00251 compiler.translate( *input, *output );
00252 break;}
00253 case AnyMeal2MM: {
00254 string fileName( findAnyMealFile( "appdata",
00255 "scripts/recipeToMealMaster.xsl" ) );
00256 XSLCompiler compiler
00257 ( fileName,
00258 FormatterListener::OUTPUT_METHOD_TEXT, MMENCODING,
00259 findAnyMealFile( "appdata", "scripts/anymeal.xsd" ) );
00260 compiler.setParam( "mfile", string( "\"file://" ) +
00261 mealmasterMapFile() + "\"" );
00262 compiler.translate( *input, *output );
00263 break;}
00264 case RecipeML2AnyMeal: {
00265 string fileName( findAnyMealFile( "appdata",
00266 "scripts/recipeMLToRecipe.xsl" ) );
00267 XSLCompiler( fileName,
00268 FormatterListener::OUTPUT_METHOD_XML, "UTF-8",
00269 findAnyMealFile( "appdata", "scripts/recipeML.xsd" ) ).
00270 translate( *input, *output );
00271 break;}
00272 default:
00273 ERRORMACRO( false, Error, , i18n( "No compiler was selected." ) );
00274 };
00275
00276 } catch ( Error &e ) {
00277
00278 cerr << i18n( "Error: " ) << e.what() << endl;
00279
00280 };
00281
00282
00283
00284
00285
00286
00287
00288 };
00289
00290 return guiDisabled;
00291 }
00292
00293 class AnyMealIcons : public QMimeSourceFactory
00294 {
00295 public:
00296 AnyMealIcons(void) {}
00297 const QMimeSource* data( const QString& abs_name ) const {
00298 #ifndef NDEBUG
00299 cerr << "Request for icon \"" << abs_name << "\"." << endl;
00300 #endif
00301 const QMimeSource* d = QMimeSourceFactory::data( abs_name );
00302 if ( d || abs_name.isNull() ) return d;
00303 QPixmap pixmap( iconLoader.loadIcon( abs_name.left
00304 ( abs_name.length() - 4 ),
00305 KIcon::Toolbar, 32,
00306 KIcon::DefaultState, 0, true ) );
00307 if ( !pixmap.isNull() ) {
00308 ((QMimeSourceFactory *)this)->setPixmap( abs_name, pixmap );
00309 } else {
00310 #ifndef NDEBUG
00311 cerr << "Could not find icon \"" << abs_name
00312 << "\" in standard directory." << endl;
00313 #endif
00314 if ( pixmap.load( QString( "icons/hi32-action-" ) + abs_name ) )
00315 ((QMimeSourceFactory *)this)->setPixmap( abs_name, pixmap );
00316 else if ( pixmap.load( QString( "icons/hi32-app-" ) + abs_name ) )
00317 ((QMimeSourceFactory *)this)->setPixmap( abs_name, pixmap );
00318 };
00319 return QMimeSourceFactory::data( abs_name );
00320 };
00321 protected:
00322 KIconLoader iconLoader;
00323 };
00324
00325 magic_t magic = NULL;
00326
00327 shared_ptr< KSplashScreen > splash;
00328
00329 int gui(void)
00330 {
00331 int retVal;
00332
00333
00334 KApplication app( true, true );
00335
00336
00337
00338
00339 AnyMealIcons anyMealIcons;
00340 QMimeSourceFactory::defaultFactory()->addFactory( &anyMealIcons );
00341
00342
00343 QTextCodec::setCodecForCStrings
00344 ( QTextCodec::codecForName( "UTF-8" ) );
00345
00346
00347
00348
00349
00350 try {
00351
00352
00353 QPixmap pixmap( findAnyMealFile( "appdata", "pics/splash.jpg" ) );
00354 ERRORMACRO( !pixmap.isNull(), Error, ,
00355 "Could not load image \""
00356 << findAnyMealFile( "appdata", "pics/splash.jpg" ) << "\"." );
00357 splash = shared_ptr< KSplashScreen >( new KSplashScreen( pixmap ) );
00358 splash->show();
00359
00360
00361 splash->message( i18n( "Initialising recode-library ..." ) );
00362 Recoder::outer = recode_new_outer( false );
00363 ERRORMACRO( Recoder::outer != NULL, Error, ,
00364 "Failed to initialise recoder library." );
00365
00366
00367 splash->message( i18n( "Initialising magic-library ..." ) );
00368 magic = magic_open( MAGIC_NONE );
00369 ERRORMACRO( magic != NULL, Error, ,
00370 i18n( "Failed to initialise magic library." ) );
00371 ERRORMACRO( magic_load( magic, NULL ) == 0, Error, ,
00372 magic_error( magic ) );
00373
00374 splash->message( i18n( "Reading icons ..." ) );
00375 AnyMeal anyMeal( NULL, "anyMeal mainwindow" );
00376 splash->message( i18n( "Opening main window ..." ) );
00377 app.setMainWidget( &anyMeal );
00378 anyMeal.show();
00379 splash.reset();
00380 retVal = app.exec();
00381
00382 } catch ( Error &e ) {
00383
00384
00385 splash.reset();
00386
00387
00388 KMessageBox::error( NULL, e.what() );
00389 retVal = 1;
00390
00391 };
00392
00393
00394 if ( magic != NULL ) {
00395 magic_close( magic );
00396 magic = NULL;
00397 };
00398
00399
00400
00401
00402
00403
00404
00405 QMimeSourceFactory::defaultFactory()->removeFactory( &anyMealIcons );
00406
00407 return retVal;
00408 }
00409
00410 int main( int argc, char *argv[] )
00411 {
00412 int retVal = 0;
00413
00414
00415
00416
00417
00418 XMLPlatformUtils::Initialize();
00419
00420 XalanTransformer::initialize();
00421
00422 {
00423
00424
00425 XPathInit theXPathInit;
00426
00427
00428 KAboutData about
00429 ( "anymeal", I18N_NOOP( "AnyMeal" ), VERSION,
00430 I18N_NOOP( "recipe database application" ),
00431 KAboutData::License_GPL,
00432 I18N_NOOP( "Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, Jan Wedekind, "
00433 "Sheffield, United Kingdom" ),
00434 I18N_NOOP( "AnyMeal comes with ABSOLUTELY NO WARRANTY.\n"
00435 "This is free software, and you are welcome to "
00436 "redistribute it\n"
00437 "under certain conditions; see file 'COPYING' for "
00438 "details.\n"
00439 "See 'anymeal.lsm' file for contact information." ),
00440 "http://sourceforge.net/projects/anymeal/",
00441 "wedesoft@users.sourceforge.net" );
00442 about.addAuthor( "Jan Wedekind", I18N_NOOP( "Main developer" ),
00443 "jan@wedesoft.de",
00444 "http://www.wedesoft.de/" );
00445 about.addCredit( "Sandro Tosi",
00446 I18N_NOOP( "Debian-package and man-page." ),
00447 "matrixhasu@altervista.org",
00448 "http://matrixhasu.altervista.org/" );
00449 about.addCredit( "Scott Welliver",
00450 I18N_NOOP( "Project inspired from original "
00451 "Mealmaster-software." ),
00452 NULL,
00453 "http://episoft.home.comcast.net/" );
00454 about.addCredit( "Roland Jesse",
00455 I18N_NOOP( "Recipe-editor inspired from "
00456 "mango-software." ),
00457 "rjesse@users.sourceforge.net",
00458 "http://mango.sf.net/" );
00459 about.addCredit( "Wikibooks Cookbook",
00460 I18N_NOOP( "GFDL licensed photos." ),
00461 NULL,
00462 "http://en.wikibooks.org/wiki/Cookbook" );
00463 about.addCredit( "krecipes team",
00464 I18N_NOOP( "Database-wizard inspired from "
00465 "krecipes-software." ),
00466 NULL,
00467 "http://krecipes.sourceforge.net/" );
00468 about.addCredit( "Free Software Foundation",
00469 I18N_NOOP( "The GNU/Linux platform." ),
00470 "gnu@gnu.org",
00471 "http://www.gnu.org/gnu/the-gnu-project.html" );
00472 about.addCredit( "GCC team",
00473 I18N_NOOP( "The GNU-C++ compiler" ),
00474 "gcc@gnu.org",
00475 "http://www.gnu.org/software/gcc/" );
00476 about.addCredit( "Bram Moolenaar and others",
00477 I18N_NOOP( "The vi editor" ),
00478 NULL,
00479 "http://www.vim.org/" );
00480 about.addCredit( "Dimitri van Heesch",
00481 I18N_NOOP( "Doxygen documentation system" ),
00482 "dimitri@stack.nl",
00483 "http://www.stack.nl/~dimitri/doxygen/" );
00484 about.addCredit( "Apache Software Foundation",
00485 I18N_NOOP( "Xalan-C and Xerces-C XML-libraries." ),
00486 "apache@apache.org",
00487 "http://xml.apache.org/" );
00488 about.addCredit( "MySQL Developers",
00489 I18N_NOOP( "MySQL database software" ),
00490 NULL,
00491 "http://dev.mysql.com/" );
00492 about.addCredit( "Boost team",
00493 I18N_NOOP( "Boost C++ library" ),
00494 NULL,
00495 "http://www.boost.org/" );
00496 about.addCredit( "KDE team",
00497 I18N_NOOP( "KDE desktop" ),
00498 NULL,
00499 "http://www.kde.org/" );
00500 about.addCredit( "Matthias Kiefer",
00501 I18N_NOOP( "kbabel" ),
00502 "kiefer@kde.org",
00503 "http://i18n.kde.org/tools/kbabel/" );
00504 about.addCredit( "Dia team",
00505 I18N_NOOP( "Diagram editor Dia" ),
00506 NULL,
00507 "http://www.gnome.org/projects/dia/" );
00508 about.addCredit( "Graphviz team",
00509 I18N_NOOP( "Graph visualization software Graphviz" ),
00510 NULL,
00511 "http://www.graphviz.org/" );
00512 about.addCredit( "Docbook team",
00513 I18N_NOOP( "Docbook XSL stylesheets" ),
00514 NULL,
00515 "http://docbook.sourceforge.net/" );
00516 about.addCredit( "Nick Gorham",
00517 I18N_NOOP( "unixODBC software" ),
00518 "nick.gorham@easysoft.com",
00519 "http://www.unixodbc.org/" );
00520 about.addCredit( "Trolltech",
00521 I18N_NOOP( "Qt graphical user-interface library" ),
00522 "info@trolltech.com",
00523 "http://www.trolltech.com/" );
00524 about.addCredit( "Sourceforge",
00525 I18N_NOOP( "Hosting and advertising for AnyMeal" ),
00526 NULL,
00527 "http://sourceforge.net/" );
00528 about.addCredit( "Noah Levitt",
00529 I18N_NOOP( "GNOME Unicode character map" ),
00530 "nlevitt@columbia.edu",
00531 "http://gucharmap.sourceforge.net/" );
00532 about.addCredit( "Formatdata Company",
00533 I18N_NOOP( "This product is RecipeML compatible." ),
00534 "RecipeML@formatdata.com",
00535 "http://www.formatdata.com/recipeml/" );
00536 about.setTranslator( I18N_NOOP("_: NAME OF TRANSLATORS\nYour names"),
00537 I18N_NOOP("_: EMAIL OF TRANSLATORS\nYour emails") );
00538
00539 KCmdLineArgs::init( argc, argv, &about );
00540
00541 if ( !cli() ) retVal = gui();
00542
00543 };
00544
00545
00546 XalanTransformer::terminate();
00547
00548 XMLPlatformUtils::Terminate();
00549
00550
00551 return retVal;
00552 }