/* * main.cpp - initialization and profile/settings handling * Copyright (C) 2001-2003 Justin Karneges * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include"main.h" #include"psiapplication.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include"common.h" #include"profiles.h" #include"profiledlg.h" #include"xmpp.h" // need to remove this later #include"hash.h" #include"eventdlg.h" #include"chatdlg.h" #ifdef USE_CRASH # include"crash.h" #endif #ifdef Q_OS_WIN # include // for RegDeleteKey #endif using namespace XMPP; QTranslator *trans; QTranslator *qttrans; QString curLang = "en"; QString curLangName = QT_TR_NOOP("language_name"); void setLang(const QString &lang) { //printf("changing lang: [%s]\n", lang.latin1()); trans->clear(); qttrans->clear(); if(lang == "en") { curLang = lang; curLangName = "English"; return; } QStringList dirs; QString subdir = ""; dirs += "." + subdir; dirs += g.pathHome + subdir; dirs += g.pathBase + subdir; for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) { if(!QFile::exists(*it)) continue; if(trans->load("psi_" + lang, *it)) { // try to load qt library translation qttrans->load("qt_" + lang, *it); curLang = lang; return; } } } static void folderkeyRemove(QSettings &settings, const QString &d) { QStringList entries; QStringList::Iterator it; entries = settings.subkeyList(d); for(it = entries.begin(); it != entries.end(); ++it) { QString str = d + "/" + *it; folderkeyRemove(settings, str); } entries = settings.entryList(d); for(it = entries.begin(); it != entries.end(); ++it) { QString str = d + "/" + *it; settings.removeEntry(str); } settings.removeEntry(d); } PsiMain::PsiMain(QObject *par) :QObject(par) { pcon = 0; // detect available language packs langs.set("en", "English"); QStringList dirs; QString subdir = ""; dirs += "." + subdir; dirs += g.pathHome + subdir; dirs += g.pathBase + subdir; for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it) { if(!QFile::exists(*it)) continue; QDir d(*it); QStringList entries = d.entryList(); for(QStringList::Iterator it2 = entries.begin(); it2 != entries.end(); ++it2) { if(*it2 == "." || *it2 == "..") continue; QString str = *it2; // verify that it is a language file if(str.left(4) != "psi_") continue; int n = str.find('.', 4); if(n == -1) continue; if(str.mid(n) != ".qm") continue; QString lang = str.mid(4, n-4); //printf("found [%s], lang=[%s]\n", str.latin1(), lang.latin1()); // get the language_name QString name = QString("[") + str + "]"; QTranslator t(0); if(!t.load(str, *it)) continue; if(t.contains("@default", "language_name", 0)) { QString s = t.findMessage("@default", "language_name", 0).translation(); if(!s.isEmpty()) name = s; } langs.set(lang, name); } } // load simple registry settings QSettings *s = new QSettings; s->setPath("psi.affinix.com", "Psi", QSettings::User); // make Psi load all prefs from HKCU on Windows systems s->insertSearchPath(QSettings::Windows, "/Affinix"); s->insertSearchPath(QSettings::Unix, g.pathHome); lastProfile = s->readEntry("/psi/lastProfile"); lastLang = s->readEntry("/psi/lastLang",""); autoOpen = s->readBoolEntry("/psi/autoOpen", FALSE); delete s; // some of them are overridden afterwards by CLI profile/profiledir // but not saved if(lastLang.isEmpty()) { lastLang = QTextCodec::locale(); //printf("guessing locale: [%s]\n", lastLang.latin1()); } setLang(lastLang); // language detected // we can now check the validity of the CLI arguments and report bad usage if (argp->existsArg("profiledir") && g.pathHome=="") { QString errmsg; QMessageBox::critical(0, tr("Error"), tr("The specified profile (%1) does not exist.") .arg( QDir(argp->getString("profiledir")).dirName() ) ); QTimer::singleShot(0, this, SLOT(bail())); return; } if (argp->existsArg("profiledir") && argp->existsArg("datadir")) { QMessageBox::critical(0, tr("Error"), tr("You are not allowed to use \"--datadir\" and \"--profiledir\" at the same time.")); QTimer::singleShot(0, this, SLOT(bail())); return; } //start overriding loaded settings if (argp->existsArg("profiledir")) { QString dir=argp->getString("profiledir"); if (dir[dir.length()-1]==QDir::separator()) dir.remove(dir.length()-1,1); //remove trailing slash int p=dir.findRev(QDir::separator()); dir.remove(0,p+1); lastProfile=dir; autoOpen=true; //printf("Opening given profile named: %s\n",lastProfile.latin1()); } if (argp->existsArg("profile")) { // let's trick Psi think we use autoopen option // autoopen/lastprofile won't be modified on host machine // (we made sure settings are not saved when this cmd line param is used) autoOpen=true; lastProfile=argp->getString("profile"); } // standard profile loading procedure if(autoOpen && !lastProfile.isEmpty() && profileExists(lastProfile)) { // Auto-open the last profile activeProfile = lastProfile; QTimer::singleShot(0, this, SLOT(sessionStart())); } else { if (!lastProfile.isEmpty() && !getProfilesList().isEmpty()) { // Select a profile QTimer::singleShot(0, this, SLOT(chooseProfile())); } else { // Create & open the default profile if (!profileExists("default") && !profileNew("default")) { QMessageBox::critical(0, tr("Error"), tr("There was an error creating the default profile.")); QTimer::singleShot(0, this, SLOT(bail())); } else { lastProfile = activeProfile = "default"; autoOpen = true; QTimer::singleShot(0, this, SLOT(sessionStart())); } } } } PsiMain::~PsiMain() { delete pcon; if (!( argp->existsArg("profile") || argp->existsArg("profiledir") )) { // save settings on exit if profile or profiledir were not given as CLI arg // we do not want to mess up the settings on the current computer #ifdef Q_OS_WIN // remove Psi's settings from HKLM QSettings *rs = new QSettings; rs->setPath("Affinix", "psi", QSettings::Global); rs->removeEntry("/lastProfile"); rs->removeEntry("/lastLang"); rs->removeEntry("/autoOpen"); QString affinixKey = "Software\\Affinix"; #ifdef Q_OS_TEMP RegDeleteKeyW(HKEY_LOCAL_MACHINE, affinixKey.ucs2()); #else RegDeleteKeyA(HKEY_LOCAL_MACHINE, affinixKey.latin1()); #endif delete rs; #endif QSettings *s = new QSettings; s->setPath("psi.affinix.com", "Psi", QSettings::User); // make Psi load all prefs from HKCU on Windows systems s->insertSearchPath(QSettings::Windows, "/Affinix"); s->insertSearchPath(QSettings::Unix, g.pathHome); s->writeEntry("/psi/lastProfile", lastProfile); s->writeEntry("/psi/lastLang", lastLang); s->writeEntry("/psi/autoOpen", autoOpen); delete s; } //else // printf("We don't want to save settings!\n"); } static bool loadGlobal() { // set the paths g.pathBase = getResourcesDir(); if (argp->existsArg("profiledir")) { QString dir=argp->getString("profiledir"); if (dir[dir.length()-1]==QDir::separator()) dir.remove(dir.length()-1,1); //remove trailing slash QDir d(dir); if(!d.exists()) { // can't find profile dir g.pathHome=""; // we signal PsiMain to bail-out with an error by setting pathHome="" return TRUE; //we have to return true in order to reach PsiMain constuctor //where we return a translated error } g.pathHome=dir; int p=dir.findRev(QDir::separator()); g.pathProfiles=dir.left(p); return TRUE; } if (argp->existsArg("datadir")) { QString dir=argp->getString("datadir"); if (dir[dir.length()-1]==QDir::separator()) dir.remove(dir.length()-1,1); g.pathHome=dir; } else { // standard behaviour char *p = getenv("PSIDATADIR"); if(p) { g.pathHome = p; delete p; } else g.pathHome = getHomeDir(); } g.pathProfiles = g.pathHome + "/profiles"; QDir d(g.pathProfiles); if(!d.exists()) { QDir d(g.pathHome); d.mkdir("profiles"); } return TRUE; } void PsiMain::chooseProfile() { if(pcon) { delete pcon; pcon = 0; } QString str = ""; // dirty, dirty, dirty hack is = new PsiIconset; is->loadSystem(); while(1) { ProfileOpenDlg *w = new ProfileOpenDlg(lastProfile, langs, curLang); w->ck_auto->setChecked(autoOpen); int r = w->exec(); // lang change if(r == 10) { QString newLang = w->newLang; delete w; setLang(newLang); lastLang = curLang; continue; } else { if(r == QDialog::Accepted) str = w->cb_profile->currentText(); autoOpen = w->ck_auto->isChecked(); delete w; break; } } delete is; if(str.isEmpty()) { quit(); return; } // only set lastProfile if the user opened it lastProfile = str; activeProfile = str; sessionStart(); } void PsiMain::sessionStart() { // get a PsiCon pcon = new PsiCon(); if(!pcon->init()) { delete pcon; pcon = 0; quit(); return; } connect(pcon, SIGNAL(quit(int)), SLOT(sessionQuit(int))); } void PsiMain::sessionQuit(int x) { if(x == PsiCon::QuitProgram) { QTimer::singleShot(0, this, SLOT(bail())); } else if(x == PsiCon::QuitProfile) { QTimer::singleShot(0, this, SLOT(chooseProfile())); } } void PsiMain::bail() { if(pcon) { delete pcon; pcon = 0; } quit(); } int main(int argc, char *argv[]) { argp = new ArgumentParser(argc, argv); argp->addArgument("nocrash"); argp->addArgument("no-gpg"); argp->addArgument("no-gpg-agent"); argp->addArgument("linktest"); argp->addArgument("datadir","d",true); argp->addArgument("profile","p",true); argp->addArgument("profiledir","pd",true); argp->addArgument("gpg","",true); argp->addArgument("gpghome","",true); argp->parse(); // add library paths before creating QApplication if (!loadGlobal()) return 1; QApplication::addLibraryPath(g.pathHome); QApplication::addLibraryPath(getResourcesDir()); PsiApplication *app = new PsiApplication(argc, argv); #ifdef USE_CRASH useCrash = !argp->existsArg("nocrash"); if ( useCrash ) Crash::registerSigsegvHandler(argv[0]); #endif // seed the random number generator srand(time(NULL)); //dtcp_port = 8000; use_gpg = !argp->existsArg("no-gpg"); no_gpg_agent = argp->existsArg("no-gpg-agent"); // Note: inconsistent naming of variables (use_gpg, no_gpg_agent), // although consistent naming of arguments //link_test = argp->existsArg("linktest"); //if(link_test) // printf("Link test enabled\n"); // silly winsock workaround //QSocketDevice *d = new QSocketDevice; //delete d; // japanese trans = new QTranslator(0); app->installTranslator(trans); qttrans = new QTranslator(0); app->installTranslator(qttrans); // need SHA1 for Iconset sound if(!QCA::isSupported(QCA::CAP_SHA1)) QCA::insertProvider(XMPP::createProviderHash()); PsiMain *psi = new PsiMain; QObject::connect(psi, SIGNAL(quit()), app, SLOT(quit())); app->exec(); delete psi; app->removeTranslator(trans); delete trans; trans = 0; app->removeTranslator(qttrans); delete qttrans; qttrans = 0; delete argp; delete app; QCA::unloadAllPlugins(); return 0; }