QTfrontend/hwform.cpp
branchflibqtfrontend
changeset 8304 620560c89284
parent 8280 734b069a418e
parent 8302 a7934cd12469
child 8363 0b4ac686fc44
equal deleted inserted replaced
8282:1f81bcce3ee6 8304:620560c89284
    94 #include "roomslistmodel.h"
    94 #include "roomslistmodel.h"
    95 #include "recorder.h"
    95 #include "recorder.h"
    96 #include "playerslistmodel.h"
    96 #include "playerslistmodel.h"
    97 
    97 
    98 #include "DataManager.h"
    98 #include "DataManager.h"
       
    99 #include "AutoUpdater.h"
    99 
   100 
   100 #ifdef __APPLE__
   101 #ifdef __APPLE__
   101 #include "M3Panel.h"
   102 #include "M3Panel.h"
   102 #ifdef SPARKLE_ENABLED
   103 #ifdef SPARKLE_ENABLED
   103 #include "SparkleAutoUpdater.h"
   104 #include "SparkleAutoUpdater.h"
   147     ui.pageVideos->init(config);
   148     ui.pageVideos->init(config);
   148     ui.pageOptions->setConfig(config);
   149     ui.pageOptions->setConfig(config);
   149 #endif
   150 #endif
   150 
   151 
   151 #ifdef __APPLE__
   152 #ifdef __APPLE__
       
   153     AutoUpdater* updater = NULL;
       
   154     if (config->isAutoUpdateEnabled())
       
   155     {
       
   156 #ifdef __APPLE__
       
   157 #ifdef SPARKLE_ENABLED
       
   158         updater = new SparkleAutoUpdater();
       
   159 #endif
       
   160 #endif
       
   161         if (updater)
       
   162         {
       
   163             updater->checkForUpdates();
       
   164             delete updater;
       
   165         }
       
   166     }
       
   167 #endif
       
   168 
       
   169 #ifdef __APPLE__
   152     panel = new M3Panel;
   170     panel = new M3Panel;
   153 
       
   154 #ifdef SPARKLE_ENABLED
       
   155     AutoUpdater* updater;
       
   156 
       
   157     updater = new SparkleAutoUpdater();
       
   158     if (updater && config->isAutoUpdateEnabled())
       
   159         updater->checkForUpdates();
       
   160 #endif
       
   161 
   171 
   162     QShortcut *hideFrontend = new QShortcut(QKeySequence("Ctrl+M"), this);
   172     QShortcut *hideFrontend = new QShortcut(QKeySequence("Ctrl+M"), this);
   163     connect (hideFrontend, SIGNAL(activated()), this, SLOT(showMinimized()));
   173     connect (hideFrontend, SIGNAL(activated()), this, SLOT(showMinimized()));
   164 #else
   174 #else
   165     // ctrl+q closes frontend for consistency
   175     // ctrl+q closes frontend for consistency
  1031 }
  1041 }
  1032 
  1042 
  1033 void HWForm::NetPassword(const QString & nick)
  1043 void HWForm::NetPassword(const QString & nick)
  1034 {
  1044 {
  1035     //Get hashes
  1045     //Get hashes
  1036     QString hash =  config->value("net/passwordhash", "").toString();
  1046     QString hash =  config->passwordHash();
  1037     QString temphash =  config->value("net/temppasswordhash", "").toString();
  1047     QString temphash =  config->tempHash();
  1038 
  1048 
  1039     //Check them
  1049     //Check them
  1040 
  1050 
  1041     if (temphash.isEmpty() && hash.isEmpty()) { //If the user enters a registered nick with no password, sends a bogus hash
  1051     if (temphash.isEmpty() && hash.isEmpty()) { //If the user enters a registered nick with no password, sends a bogus hash
  1042         hwnet->SendPasswordHash("THISISNOHASH");
  1052         hwnet->SendPasswordHash("THISISNOHASH");
  1047     else { //Send the hash
  1057     else { //Send the hash
  1048         hwnet->SendPasswordHash(temphash);
  1058         hwnet->SendPasswordHash(temphash);
  1049     }
  1059     }
  1050 
  1060 
  1051     //Remove temporary hash from config
  1061     //Remove temporary hash from config
  1052     QString key = "net/temppasswordhash";
  1062     config->clearTempHash();
  1053     config->setValue(key, "");
  1063 }
  1054     config->remove(key);
  1064 
       
  1065 void HWForm::NetNickRegistered(const QString & nick)
       
  1066 {
       
  1067     //Get hashes
       
  1068     QString hash =  config->passwordHash();
       
  1069     QString temphash =  config->tempHash();
       
  1070 
       
  1071     if (hash.isEmpty()) {
       
  1072         if (temphash.isEmpty()) { //If the user enters a registered nick with no password
       
  1073             QString suppliedpass;
       
  1074             while (suppliedpass.isEmpty()) {
       
  1075                 QInputDialog nickRegedDialog(this);
       
  1076                 nickRegedDialog.setWindowModality(Qt::WindowModal);
       
  1077                 nickRegedDialog.setInputMode(QInputDialog::TextInput);
       
  1078                 nickRegedDialog.setWindowTitle(tr("Hedgewars - Nick registered"));
       
  1079                 nickRegedDialog.setLabelText(tr("This nick is registered, and you haven't specified a password.\n\nIf this nick isn't yours, please register your own nick at www.hedgewars.org\n\nPassword:"));
       
  1080                 nickRegedDialog.setTextEchoMode(QLineEdit::Password);
       
  1081                 nickRegedDialog.exec();
       
  1082 
       
  1083                 suppliedpass = nickRegedDialog.textValue();
       
  1084 
       
  1085                 if (nickRegedDialog.result() == QDialog::Rejected) {
       
  1086                     config->clearPasswordHash();
       
  1087                     config->clearTempHash();
       
  1088                     GoBack();
       
  1089                     return;
       
  1090                 }
       
  1091                 temphash = QCryptographicHash::hash(suppliedpass.toUtf8(), QCryptographicHash::Md5).toHex();
       
  1092                 config->setTempHash(temphash);
       
  1093             }
       
  1094         }
       
  1095     }
       
  1096     NetPassword(nick);
       
  1097 }
       
  1098 
       
  1099 void HWForm::NetNickNotRegistered(const QString & nick)
       
  1100 {
       
  1101     QMessageBox noRegMsg(this);
       
  1102     noRegMsg.setIcon(QMessageBox::Information);
       
  1103     noRegMsg.setWindowTitle(QMessageBox::tr("Hedgewars - Nick not registered"));
       
  1104     noRegMsg.setWindowModality(Qt::WindowModal);
       
  1105     noRegMsg.setText(tr("Your nickname is not registered.\nTo prevent someone else from using it,\nplease register it at www.hedgewars.org"));
       
  1106 
       
  1107     if (!config->passwordHash().isEmpty())
       
  1108     {
       
  1109         config->clearPasswordHash();
       
  1110         noRegMsg.setText(noRegMsg.text()+tr("\n\nYour password wasn't saved either."));
       
  1111     }
       
  1112     if (!config->tempHash().isEmpty())
       
  1113     {
       
  1114         config->clearTempHash();
       
  1115     }
       
  1116     noRegMsg.exec();
  1055 }
  1117 }
  1056 
  1118 
  1057 void HWForm::NetNickTaken(const QString & nick)
  1119 void HWForm::NetNickTaken(const QString & nick)
  1058 {
  1120 {
  1059     bool ok = false;
  1121     bool ok = false;
  1060     QString newNick = QInputDialog::getText(this, tr("Nickname"), tr("Someone already uses your nickname %1 on the server.\nPlease pick another nickname:").arg(nick), QLineEdit::Normal, nick, &ok);
  1122     QString newNick = QInputDialog::getText(this, tr("Nickname"), tr("Someone already uses your nickname %1 on the server.\nPlease pick another nickname:").arg(nick), QLineEdit::Normal, nick, &ok);
  1061 
  1123 
  1062     if (!ok || newNick.isEmpty())
  1124     if (!ok || newNick.isEmpty())
  1063     {
  1125     {
  1064         ForcedDisconnect(tr("No nickname supplied."));
  1126         //ForcedDisconnect(tr("No nickname supplied."));
       
  1127 	bool retry = RetryDialog(tr("Hedgewars - Empty nickname"), tr("No nickname supplied."));
       
  1128 	GoBack();
       
  1129         if (retry) {
       
  1130        	   NetConnectOfficialServer();
       
  1131         }
  1065         return;
  1132         return;
  1066     }
  1133     }
  1067 
  1134 
  1068     hwnet->NewNick(newNick);
  1135     hwnet->NewNick(newNick);
  1069     config->setValue("net/nick", newNick);
  1136     config->setValue("net/nick", newNick);
  1074 }
  1141 }
  1075 
  1142 
  1076 void HWForm::NetAuthFailed()
  1143 void HWForm::NetAuthFailed()
  1077 {
  1144 {
  1078     // Set the password blank if case the user tries to join and enter his password again
  1145     // Set the password blank if case the user tries to join and enter his password again
  1079     config->setValue("net/passwordlength", 0);
  1146     config->clearTempHash();
  1080     config->setNetPasswordLength(0);
  1147 
       
  1148     //Try to login again
       
  1149     bool retry = RetryDialog(tr("Hedgewars - Wrong password"), tr("You entered a wrong password."));
       
  1150     GoBack();
       
  1151 
       
  1152     config->clearPasswordHash();
       
  1153     config->clearTempHash();
       
  1154     if (retry) {
       
  1155        NetConnectOfficialServer();
       
  1156     }
       
  1157 }
       
  1158 
       
  1159 bool HWForm::RetryDialog(const QString & title, const QString & label)
       
  1160 {
       
  1161     QMessageBox retryMsg(this);
       
  1162     retryMsg.setIcon(QMessageBox::Warning);
       
  1163     retryMsg.setWindowTitle(title);
       
  1164     retryMsg.setText(label);
       
  1165     retryMsg.setWindowModality(Qt::WindowModal);
       
  1166 
       
  1167     retryMsg.addButton(QMessageBox::Cancel);
       
  1168 
       
  1169     QPushButton *retryButton = retryMsg.addButton(QMessageBox::Ok);
       
  1170     retryButton->setText(tr("Try Again"));
       
  1171     retryButton->setFocus();
       
  1172 
       
  1173     retryMsg.exec();
       
  1174 
       
  1175     if (retryMsg.clickedButton() == retryButton) {
       
  1176        return true;
       
  1177     }
       
  1178     return false;
  1081 }
  1179 }
  1082 
  1180 
  1083 void HWForm::NetTeamAccepted(const QString & team)
  1181 void HWForm::NetTeamAccepted(const QString & team)
  1084 {
  1182 {
  1085     ui.pageNetGame->pNetTeamsWidget->changeTeamStatus(team);
  1183     ui.pageNetGame->pNetTeamsWidget->changeTeamStatus(team);
  1128     connect(hwnet, SIGNAL(EnteredGame()), this, SLOT(NetGameEnter()), Qt::QueuedConnection);
  1226     connect(hwnet, SIGNAL(EnteredGame()), this, SLOT(NetGameEnter()), Qt::QueuedConnection);
  1129     connect(hwnet, SIGNAL(LeftRoom(const QString&)), this, SLOT(NetLeftRoom(const QString&)), Qt::QueuedConnection);
  1227     connect(hwnet, SIGNAL(LeftRoom(const QString&)), this, SLOT(NetLeftRoom(const QString&)), Qt::QueuedConnection);
  1130     connect(hwnet, SIGNAL(AddNetTeam(const HWTeam&)), this, SLOT(AddNetTeam(const HWTeam&)), Qt::QueuedConnection);
  1228     connect(hwnet, SIGNAL(AddNetTeam(const HWTeam&)), this, SLOT(AddNetTeam(const HWTeam&)), Qt::QueuedConnection);
  1131     connect(hwnet, SIGNAL(RemoveNetTeam(const HWTeam&)), this, SLOT(RemoveNetTeam(const HWTeam&)), Qt::QueuedConnection);
  1229     connect(hwnet, SIGNAL(RemoveNetTeam(const HWTeam&)), this, SLOT(RemoveNetTeam(const HWTeam&)), Qt::QueuedConnection);
  1132     connect(hwnet, SIGNAL(TeamAccepted(const QString&)), this, SLOT(NetTeamAccepted(const QString&)), Qt::QueuedConnection);
  1230     connect(hwnet, SIGNAL(TeamAccepted(const QString&)), this, SLOT(NetTeamAccepted(const QString&)), Qt::QueuedConnection);
  1133     connect(hwnet, SIGNAL(AskForPassword(const QString&)), this, SLOT(NetPassword(const QString&)), Qt::QueuedConnection);
  1231     connect(hwnet, SIGNAL(NickRegistered(const QString&)), this, SLOT(NetNickRegistered(const QString&)), Qt::QueuedConnection);
       
  1232     connect(hwnet, SIGNAL(NickNotRegistered(const QString&)), this, SLOT(NetNickNotRegistered(const QString&)), Qt::QueuedConnection);
  1134     connect(hwnet, SIGNAL(NickTaken(const QString&)), this, SLOT(NetNickTaken(const QString&)), Qt::QueuedConnection);
  1233     connect(hwnet, SIGNAL(NickTaken(const QString&)), this, SLOT(NetNickTaken(const QString&)), Qt::QueuedConnection);
  1135     connect(hwnet, SIGNAL(AuthFailed()), this, SLOT(NetAuthFailed()), Qt::QueuedConnection);
  1234     connect(hwnet, SIGNAL(AuthFailed()), this, SLOT(NetAuthFailed()), Qt::QueuedConnection);
  1136     //connect(ui.pageNetGame->BtnBack, SIGNAL(clicked()), hwnet, SLOT(partRoom()));
  1235     //connect(ui.pageNetGame->BtnBack, SIGNAL(clicked()), hwnet, SLOT(partRoom()));
  1137 
  1236 
  1138     ui.pageRoomsList->chatWidget->setUsersModel(hwnet->lobbyPlayersModel());
  1237     ui.pageRoomsList->chatWidget->setUsersModel(hwnet->lobbyPlayersModel());
  1248 
  1347 
  1249 // config stuff
  1348 // config stuff
  1250     connect(hwnet, SIGNAL(paramChanged(const QString &, const QStringList &)), ui.pageNetGame->pGameCFG, SLOT(setParam(const QString &, const QStringList &)));
  1349     connect(hwnet, SIGNAL(paramChanged(const QString &, const QStringList &)), ui.pageNetGame->pGameCFG, SLOT(setParam(const QString &, const QStringList &)));
  1251     connect(ui.pageNetGame->pGameCFG, SIGNAL(paramChanged(const QString &, const QStringList &)), hwnet, SLOT(onParamChanged(const QString &, const QStringList &)));
  1350     connect(ui.pageNetGame->pGameCFG, SIGNAL(paramChanged(const QString &, const QStringList &)), hwnet, SLOT(onParamChanged(const QString &, const QStringList &)));
  1252     connect(hwnet, SIGNAL(configAsked()), ui.pageNetGame->pGameCFG, SLOT(fullNetConfig()));
  1351     connect(hwnet, SIGNAL(configAsked()), ui.pageNetGame->pGameCFG, SLOT(fullNetConfig()));
  1253    
  1352 
  1254 //nick and pass stuff
  1353 //nick and pass stuff
  1255     
  1354 
  1256     //remove temppasswordhash just in case
  1355     //remove temppasswordhash just in case
  1257     config->value("net/temppasswordhash", "");
  1356     config->clearTempHash();
  1258     config->remove("net/temppasswordhash");
  1357 
  1259     
       
  1260     //initialize
  1358     //initialize
  1261     QString hash = config->value("net/passwordhash", "").toString();
  1359     QString hash = config->passwordHash();
  1262     QString temphash = config->value("net/temppasswordhash", "").toString();
  1360     QString temphash = config->tempHash();
  1263     QString nickname = config->value("net/nick", "").toString();
  1361     QString nickname = config->value("net/nick", "").toString();
  1264     QString password;
  1362     QString password;
  1265     
  1363 
  1266     if (nickname.isEmpty() || hash.isEmpty()) { //if something from login is missing, start dialog loop
  1364     if (nickname.isEmpty() || hash.isEmpty()) { //if something from login is missing, start dialog loop
  1267     
  1365 
  1268     while (nickname.isEmpty() || (hash.isEmpty() && temphash.isEmpty())) //while a nickname, or both hashes are missing
  1366         while (nickname.isEmpty() || (hash.isEmpty() && temphash.isEmpty())) //while a nickname, or both hashes are missing
  1269     {
  1367         {
  1270 	//open dialog
  1368         //open dialog
  1271         HWPasswordDialog * hpd = new HWPasswordDialog(this);
  1369             HWPasswordDialog * pwDialog = new HWPasswordDialog(this);
  1272         hpd->cbSave->setChecked(config->value("net/savepassword", true).toBool());
  1370             pwDialog->cbSave->setChecked(config->value("net/savepassword", true).toBool());
  1273 
  1371 
  1274 	//if nickname is present, put it into the field
  1372         //if nickname is present, put it into the field
  1275 	if (!nickname.isEmpty()) {
  1373         if (!nickname.isEmpty()) {
  1276 	    hpd->leNickname->setText(nickname);
  1374             pwDialog->leNickname->setText(nickname);
  1277 	    hpd->lePassword->setFocus();
  1375             pwDialog->lePassword->setFocus();
  1278 	}
  1376         }
  1279 
  1377 
  1280 	//if dialog close, create an error message
  1378         //if dialog close, create an error message
  1281         if (hpd->exec() != QDialog::Accepted)
  1379         if (pwDialog->exec() != QDialog::Accepted) {
  1282         {
  1380             delete pwDialog;
  1283             ForcedDisconnect(tr("Login info not supplied."));
  1381             GoBack();
  1284             delete hpd;
       
  1285             return;
  1382             return;
  1286         }
  1383         }
  1287 
  1384 
  1288 	//set nick and pass from the dialog
  1385         //set nick and pass from the dialog
  1289 	nickname = hpd->leNickname->text();
  1386         nickname = pwDialog->leNickname->text();
  1290         password = hpd->lePassword->text();
  1387         password = pwDialog->lePassword->text();
  1291 
  1388 
  1292 	//calculate temphash and set it into config
  1389         //check the nickname variable
  1293 	temphash = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Md5).toHex();
  1390         if (nickname.isEmpty()) {
  1294 	config->setValue("net/temppasswordhash", temphash);
  1391             int retry = RetryDialog(tr("Hedgewars - Empty nickname"), tr("No nickname supplied."));
  1295 
  1392             GoBack();
  1296 	//if user wants to save password
  1393             delete pwDialog;
  1297         bool save = hpd->cbSave->isChecked();
  1394             if (retry) {
  1298         config->setValue("net/savepassword", save);
  1395                 NetConnectOfficialServer();
  1299         if (save) // user wants to save password
  1396             }
  1300         {
  1397             return;
  1301             config->setValue("net/passwordhash", temphash);
  1398         }
  1302             config->setValue("net/passwordlength", password.size());
  1399 
  1303             config->setNetPasswordLength(password.size());
  1400         if (!password.isEmpty()) {
  1304         }
  1401             //calculate temphash and set it into config
  1305 
  1402             temphash = QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Md5).toHex();
  1306         delete hpd;
  1403             config->setTempHash(temphash);
  1307 
  1404 
  1308 
  1405             //if user wants to save password
  1309 	//update nickname
  1406             bool save = pwDialog->cbSave->isChecked();
       
  1407             config->setValue("net/savepassword", save);
       
  1408             if (save) // user wants to save password
       
  1409             {
       
  1410                 config->setPasswordHash(temphash);
       
  1411             }
       
  1412         }
       
  1413         else {
       
  1414             delete pwDialog;
       
  1415             config->setValue("net/nick", nickname);
       
  1416             config->updNetNick();
       
  1417             config->clearPasswordHash();
       
  1418             break;
       
  1419         }
       
  1420 
       
  1421         delete pwDialog;
       
  1422 
       
  1423         //update nickname
  1310         config->setValue("net/nick", nickname);
  1424         config->setValue("net/nick", nickname);
  1311         config->updNetNick();
  1425         config->updNetNick();
  1312 	
  1426 
  1313 	//and all the variables
  1427         //and all the variables
  1314 	hash = config->value("net/passwordhash", "").toString();
  1428         hash = config->passwordHash();
  1315 	temphash = config->value("net/temppasswordhash", "").toString();
  1429         temphash = config->tempHash();
  1316 	nickname = config->value("net/nick", "").toString();
  1430         nickname = config->value("net/nick", "").toString();
  1317     }
  1431         }
  1318     
       
  1319     
       
  1320 	//if pass is none (hash is generated anyway), remove the hash
       
  1321 	if (password.size() <= 0) {
       
  1322 	    config->setValue("net/temppasswordhash", "");
       
  1323 	    config->remove("net/temppasswordhash");
       
  1324 	}
       
  1325     }
  1432     }
  1326 
  1433 
  1327     ui.pageRoomsList->setUser(nickname);
  1434     ui.pageRoomsList->setUser(nickname);
  1328     ui.pageNetGame->setUser(nickname);
  1435     ui.pageNetGame->setUser(nickname);
  1329 
  1436 
  1394         hwnet->Disconnect();
  1501         hwnet->Disconnect();
  1395 }
  1502 }
  1396 
  1503 
  1397 void HWForm::ForcedDisconnect(const QString & reason)
  1504 void HWForm::ForcedDisconnect(const QString & reason)
  1398 {
  1505 {
       
  1506     if (reason == "Reconnected too fast") { //TODO: this is a hack, which should be remade
       
  1507         bool retry = RetryDialog(tr("Hedgewars - Connection error"), tr("You reconnected too fast.\nPlease wait a few seconds and try again."));
       
  1508         if (retry) {
       
  1509             NetConnectOfficialServer();
       
  1510         }
       
  1511         else {
       
  1512             while (ui.Pages->currentIndex() != ID_PAGE_NET
       
  1513                 && ui.Pages->currentIndex() != ID_PAGE_NETTYPE
       
  1514                 && ui.Pages->currentIndex() != ID_PAGE_MAIN) 
       
  1515             {
       
  1516                 GoBack();
       
  1517             }
       
  1518         }
       
  1519         return;
       
  1520     }
  1399     if (pnetserver)
  1521     if (pnetserver)
  1400         return; // we have server - let it care of all things
  1522         return; // we have server - let it care of all things
  1401     if (hwnet)
  1523     if (hwnet)
  1402     {
  1524     {
  1403         QString errorStr = QMessageBox::tr("Connection to server is lost") + (reason.isEmpty()?"":("\n\n" + HWNewNet::tr("Quit reason: ") + '"' + reason +'"'));
  1525         QString errorStr = QMessageBox::tr("Connection to server is lost") + (reason.isEmpty()?"":("\n\n" + HWNewNet::tr("Quit reason: ") + '"' + reason +'"'));
  1498 }
  1620 }
  1499 
  1621 
  1500 void HWForm::CreateGame(GameCFGWidget * gamecfg, TeamSelWidget* pTeamSelWidget, QString ammo)
  1622 void HWForm::CreateGame(GameCFGWidget * gamecfg, TeamSelWidget* pTeamSelWidget, QString ammo)
  1501 {
  1623 {
  1502     game = new HWGame(config, gamecfg, ammo, pTeamSelWidget);
  1624     game = new HWGame(config, gamecfg, ammo, pTeamSelWidget);
  1503     connect(game, SIGNAL(CampStateChanged(int)), this, SLOT(UpdateCampaignPageProgress(int)));
  1625     connect(game, SIGNAL(campStateChanged(int)), this, SLOT(UpdateCampaignPageProgress(int)));
  1504     connect(game, SIGNAL(GameStateChanged(GameState)), this, SLOT(GameStateChanged(GameState)));
  1626     connect(game, SIGNAL(GameStateChanged(GameState)), this, SLOT(GameStateChanged(GameState)));
  1505     connect(game, SIGNAL(GameStats(char, const QString &)), ui.pageGameStats, SLOT(GameStats(char, const QString &)));
  1627     connect(game, SIGNAL(GameStats(char, const QString &)), ui.pageGameStats, SLOT(GameStats(char, const QString &)));
  1506     connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowErrorMessage(const QString &)), Qt::QueuedConnection);
  1628     connect(game, SIGNAL(ErrorMessage(const QString &)), this, SLOT(ShowErrorMessage(const QString &)), Qt::QueuedConnection);
  1507     connect(game, SIGNAL(HaveRecord(RecordType, const QByteArray &)), this, SLOT(GetRecord(RecordType, const QByteArray &)));
  1629     connect(game, SIGNAL(HaveRecord(RecordType, const QByteArray &)), this, SLOT(GetRecord(RecordType, const QByteArray &)));
  1508     m_lastDemo = QByteArray();
  1630     m_lastDemo = QByteArray();
  1757 }
  1879 }
  1758 
  1880 
  1759 // used for --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]
  1881 // used for --set-everything [screen width] [screen height] [color dept] [volume] [enable music] [enable sounds] [language file] [full screen] [show FPS] [alternate damage] [timer value] [reduced quality]
  1760 QString HWForm::getDemoArguments()
  1882 QString HWForm::getDemoArguments()
  1761 {
  1883 {
       
  1884 #ifdef Q_WS_WIN
       
  1885     QString userdir = cfgdir->absolutePath().replace("/","\\");
       
  1886 #else
       
  1887     QString userdir = cfgdir->absolutePath();
       
  1888 #endif
       
  1889 
  1762     QRect resolution = config->vid_Resolution();
  1890     QRect resolution = config->vid_Resolution();
  1763     return QString(QString::number(resolution.width()) + " "
  1891     return QString("--user-dir " + userdir
  1764                    + QString::number(resolution.height()) + " "
  1892                    + " --width " + QString::number(resolution.width())
  1765                    + QString::number(config->bitDepth()) + " " // bpp
  1893                    + " --height " + QString::number(resolution.height())
  1766                    + QString::number(config->volume()) + " " // sound volume
  1894                    + " --volume " + QString::number(config->volume())
  1767                    + (config->isMusicEnabled() ? "1" : "0") + " "
  1895                    + (config->isMusicEnabled() ? "" : " --nomusic")
  1768                    + (config->isSoundEnabled() ? "1" : "0") + " "
  1896                    + (config->isSoundEnabled() ? "" : " --nosound")
  1769                    + config->language() + ".txt "
  1897                    + " --locale " + config->language() + ".txt"
  1770                    + (config->vid_Fullscreen() ? "1" : "0") + " "
  1898                    + (config->vid_Fullscreen() ? " --fullscreen" : "")
  1771                    + (config->isShowFPSEnabled() ? "1" : "0") + " "
  1899                    + (config->isShowFPSEnabled() ? " --showfps" : "")
  1772                    + (config->isAltDamageEnabled() ? "1" : "0") + " "
  1900                    + (config->isAltDamageEnabled() ? " --altdmg" : "")
  1773                    + QString::number(config->timerInterval()) + " "
  1901                    + " --frame-interval " + QString::number(config->timerInterval())
  1774                    + QString::number(config->translateQuality()));
  1902                    + " --raw-quality " + QString::number(config->translateQuality()));
  1775 }
  1903 }
  1776 
  1904 
  1777 void HWForm::AssociateFiles()
  1905 void HWForm::AssociateFiles()
  1778 {
  1906 {
  1779     bool success = true;
  1907     bool success = true;
  1784     registry_hkcr.setValue(".hws/Default", "Hedgewars.Save");
  1912     registry_hkcr.setValue(".hws/Default", "Hedgewars.Save");
  1785     registry_hkcr.setValue("Hedgewars.Demo/Default", tr("Hedgewars Demo File", "File Types"));
  1913     registry_hkcr.setValue("Hedgewars.Demo/Default", tr("Hedgewars Demo File", "File Types"));
  1786     registry_hkcr.setValue("Hedgewars.Save/Default", tr("Hedgewars Save File", "File Types"));
  1914     registry_hkcr.setValue("Hedgewars.Save/Default", tr("Hedgewars Save File", "File Types"));
  1787     registry_hkcr.setValue("Hedgewars.Demo/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwdfile.ico\",0");
  1915     registry_hkcr.setValue("Hedgewars.Demo/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwdfile.ico\",0");
  1788     registry_hkcr.setValue("Hedgewars.Save/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwsfile.ico\",0");
  1916     registry_hkcr.setValue("Hedgewars.Save/DefaultIcon/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwsfile.ico\",0");
  1789     registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments);
  1917     registry_hkcr.setValue("Hedgewars.Demo/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" "+arguments);
  1790     registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + cfgdir->absolutePath().replace("/","\\") + "\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" --set-everything "+arguments);
  1918     registry_hkcr.setValue("Hedgewars.Save/Shell/Open/Command/Default", "\"" + bindir->absolutePath().replace("/", "\\") + "\\hwengine.exe\" \"" + datadir->absolutePath().replace("/", "\\") + "\" \"%1\" "+arguments);
  1791 #elif defined __APPLE__
  1919 #elif defined __APPLE__
  1792     // only useful when other apps have taken precedence over our file extensions and you want to reset it
  1920     // only useful when other apps have taken precedence over our file extensions and you want to reset it
  1793     system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hwd</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
  1921     system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hwd</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
  1794     system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hws</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
  1922     system("defaults write com.apple.LaunchServices LSHandlers -array-add '<dict><key>LSHandlerContentTag</key><string>hws</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.hedgewars.desktop</string></dict>'");
  1795     system("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -domain local -domain system -domain user");
  1923     system("/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -domain local -domain system -domain user");
  1806     if (success) success = system(("cp "+datadir->absolutePath()+"/misc/hwengine.desktop "+QDir::home().absolutePath()+"/.local/share/applications").toLocal8Bit().constData())==0;
  1934     if (success) success = system(("cp "+datadir->absolutePath()+"/misc/hwengine.desktop "+QDir::home().absolutePath()+"/.local/share/applications").toLocal8Bit().constData())==0;
  1807     if (success) success = system(("update-mime-database "+QDir::home().absolutePath()+"/.local/share/mime").toLocal8Bit().constData())==0;
  1935     if (success) success = system(("update-mime-database "+QDir::home().absolutePath()+"/.local/share/mime").toLocal8Bit().constData())==0;
  1808     if (success) success = system("xdg-mime default hwengine.desktop application/x-hedgewars-demo")==0;
  1936     if (success) success = system("xdg-mime default hwengine.desktop application/x-hedgewars-demo")==0;
  1809     if (success) success = system("xdg-mime default hwengine.desktop application/x-hedgewars-save")==0;
  1937     if (success) success = system("xdg-mime default hwengine.desktop application/x-hedgewars-save")==0;
  1810     // hack to add user's settings to hwengine. might be better at this point to read in the file, append it, and write it out to its new home.  This assumes no spaces in the data dir path
  1938     // hack to add user's settings to hwengine. might be better at this point to read in the file, append it, and write it out to its new home.  This assumes no spaces in the data dir path
  1811     if (success) success = system(("sed -i 's/^\\(Exec=.*\\) \\([^ ]* %f\\)/\\1 "+cfgdir->absolutePath().replace(" ","\\\\ ").replace("/","\\/")+" \\2 --set-everything "+arguments+"/' "+QDir::home().absolutePath()+"/.local/share/applications/hwengine.desktop").toLocal8Bit().constData())==0;
  1939     if (success) success = system(("sed -i 's/^\\(Exec=.*\\) \\([^ ]* %f\\)/\\1 \\2 "+arguments+"/' "+QDir::home().absolutePath()+"/.local/share/applications/hwengine.desktop").toLocal8Bit().constData())==0;
  1812 #endif
  1940 #endif
  1813     if (success)
  1941     if (success)
  1814     {
  1942     {
  1815         QMessageBox infoMsg(this);
  1943         QMessageBox infoMsg(this);
  1816         infoMsg.setIcon(QMessageBox::Information);
  1944         infoMsg.setIcon(QMessageBox::Information);