00001 #include <qapplication.h>
00002 #include <qpushbutton.h>
00003 #include <stdlib.h>
00004 #include <iostream>
00005 using namespace std;
00006
00007 #include "gametree.h"
00008 #include "gamehandler.h"
00009
00010 #include <mythtv/mythcontext.h>
00011 #include <mythtv/mythdbcon.h>
00012 #include <mythtv/mythwidgets.h>
00013 #include <mythtv/uitypes.h>
00014
00015 #define LOC_ERR QString("MythGame:GAMETREE Error: ")
00016 #define LOC QString("MythGame:GAMETREE: ")
00017
00018 QString GameTreeItem::getFillSql(QString layer) const
00019 {
00020 unsigned childDepth = m_depth + 1;
00021 bool childIsLeaf = childDepth == m_root->getDepth();
00022 QString childLevel = m_root->getLevel(childDepth - 1);
00023 QString columns;
00024
00025 QString filter = m_root->getFilter();
00026 QString conj = "where ";
00027
00028 if (!filter.isEmpty())
00029 {
00030 filter = conj + filter;
00031 conj = " and ";
00032 }
00033 if ((childLevel == "gamename") && (m_gameShowFileName))
00034 {
00035 columns = childIsLeaf
00036 ? "romname,system,year,genre,gamename"
00037 : "romname";
00038
00039 if (m_showHashed)
00040 filter += " and romname like '" + layer + "%'";
00041
00042 }
00043 else if ((childLevel == "gamename") && (layer.length() == 1)) {
00044 columns = childIsLeaf
00045 ? childLevel + ",system,year,genre,gamename"
00046 : childLevel;
00047
00048 if (m_showHashed)
00049 filter += " and gamename like '" + layer + "%'";
00050
00051 }
00052 else if (childLevel == "hash") {
00053 columns = "left(gamename,1)";
00054 }
00055 else {
00056
00057 columns = childIsLeaf
00058 ? childLevel + ",system,year,genre,gamename"
00059 : childLevel;
00060 }
00061
00062
00063
00064 if (m_romInfo) {
00065
00066 if (!m_romInfo->System().isEmpty())
00067 {
00068 filter += conj + "trim(system)=:SYSTEM";
00069 conj = " and ";
00070 }
00071 if (m_romInfo->Year() != "")
00072 {
00073 filter += conj + "year=:YEAR";
00074 conj = " and ";
00075 }
00076 if (!m_romInfo->Genre().isEmpty())
00077 {
00078 filter += conj + "trim(genre)=:GENRE";
00079 conj = " and ";
00080 }
00081 if (!m_romInfo->Publisher().isEmpty())
00082 {
00083 filter += conj + "publisher=:PUBLISHER";
00084 conj = " and ";
00085 }
00086
00087 if (!m_romInfo->Gamename().isEmpty())
00088 {
00089 filter += conj + "trim(gamename)=:GAMENAME";
00090 }
00091
00092 }
00093
00094 filter += conj + " display = 1 ";
00095
00096 QString sql;
00097
00098 if ((childLevel == "gamename") && (m_gameShowFileName))
00099 {
00100 sql = "select distinct "
00101 + columns
00102 + " from gamemetadata "
00103 + filter
00104 + " order by romname"
00105 + ";";
00106 }
00107 else if (childLevel == "hash") {
00108 sql = "select distinct "
00109 + columns
00110 + " from gamemetadata "
00111 + filter
00112 + " order by gamename,romname"
00113 + ";";
00114 }
00115 else
00116 {
00117 sql = "select distinct "
00118 + columns
00119 + " from gamemetadata "
00120 + filter
00121 + " order by "
00122 + childLevel
00123 + ";";
00124 }
00125
00126 return sql;
00127 }
00128
00129 GameTreeItem* GameTreeItem::createChild(QSqlQuery *query) const
00130 {
00131 GameTreeItem *childItem = new GameTreeItem(m_root, m_showHashed);
00132 childItem->m_depth = m_depth + 1;
00133
00134 QString current = query->value(0).toString().stripWhiteSpace();
00135 if (childItem->isLeaf())
00136 {
00137 RomInfo temp;
00138 temp.setSystem(query->value(1).toString().stripWhiteSpace());
00139 childItem->m_romInfo = GameHandler::CreateRomInfo(&temp);
00140
00141 childItem->m_romInfo->setSystem(temp.System());
00142 childItem->m_romInfo->setYear(query->value(2).toString());
00143 childItem->m_romInfo->setGenre(query->value(3).toString().stripWhiteSpace());
00144 childItem->m_romInfo->setGamename(query->value(4).toString().stripWhiteSpace());
00145 }
00146 else
00147 {
00148 childItem->m_romInfo = m_romInfo
00149 ? new RomInfo(*m_romInfo)
00150 : new RomInfo();
00151 if (childItem->getLevel() != "hash")
00152 childItem->m_romInfo->setField(childItem->getLevel(), current);
00153
00154 }
00155
00156 return childItem;
00157 }
00158
00159
00160
00161
00162
00163 GameTree::GameTree(MythMainWindow *parent, QString windowName,
00164 QString themeFilename, const char *name)
00165 : MythThemedDialog(parent, windowName, themeFilename, name)
00166 {
00167 QString levels;
00168 GameTreeRoot *root;
00169 GenericTree *node;
00170 int pos = 0;
00171
00172 m_gameTree = new GenericTree("game root", 0, false);
00173
00174 timer = new QTimer( this );
00175 connect( timer, SIGNAL(timeout()), SLOT(showImageTimeout()) );
00176
00177 wireUpTheme();
00178
00179 QString systemFilter;
00180
00181
00182
00183 unsigned handlercount = GameHandler::count();
00184
00185 for (unsigned i = 0; i < handlercount; ++i)
00186 {
00187 QString system = GameHandler::getHandler(i)->SystemName();
00188 if (i == 0)
00189 systemFilter = "system in ('" + system + "'";
00190 else
00191 systemFilter += ",'" + system + "'";
00192 }
00193 if (systemFilter.isEmpty())
00194 {
00195 systemFilter = "1=0";
00196 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find any game handlers!"));
00197 }
00198 else
00199 systemFilter += ")";
00200
00201 m_showHashed = gContext->GetSetting("GameTreeView").toInt();
00202
00203
00204
00205
00206
00207 levels = gContext->GetSetting("GameFavTreeLevels");
00208 root = new GameTreeRoot(levels, systemFilter + " and favorite=1");
00209 m_gameTreeRoots.push_back(root);
00210 m_gameTreeItems.push_back(new GameTreeItem(root));
00211 node = m_gameTree->addNode(tr("Favourites"), m_gameTreeItems.size(), false);
00212 m_favouriteNode = node;
00213
00214 levels = gContext->GetSetting("GameAllTreeLevels");
00215
00216 if (m_showHashed) {
00217 pos = levels.find("gamename",0);
00218
00219 if (pos != -1)
00220 levels.insert(pos, " hash ");
00221
00222 }
00223
00224 root = new GameTreeRoot(levels, systemFilter);
00225 m_gameTreeRoots.push_back(root);
00226 m_gameTreeItems.push_back(new GameTreeItem(root, m_showHashed));
00227 node = m_gameTree->addNode(tr("All Games"), m_gameTreeItems.size(), false);
00228
00229 root = new GameTreeRoot("genre gamename", systemFilter);
00230 m_gameTreeRoots.push_back(root);
00231 m_gameTreeItems.push_back(new GameTreeItem(root));
00232 node = m_gameTree->addNode(tr("- By Genre"), m_gameTreeItems.size(), false);
00233
00234 root = new GameTreeRoot("year gamename", systemFilter);
00235 m_gameTreeRoots.push_back(root);
00236 m_gameTreeItems.push_back(new GameTreeItem(root));
00237 node = m_gameTree->addNode(tr("- By Year"), m_gameTreeItems.size(), false);
00238
00239 root = new GameTreeRoot("gamename", systemFilter);
00240 m_gameTreeRoots.push_back(root);
00241 m_gameTreeItems.push_back(new GameTreeItem(root));
00242 node = m_gameTree->addNode(tr("- By Name"), m_gameTreeItems.size(), false);
00243
00244 root = new GameTreeRoot("publisher gamename", systemFilter);
00245 m_gameTreeRoots.push_back(root);
00246 m_gameTreeItems.push_back(new GameTreeItem(root));
00247 node = m_gameTree->addNode(tr("- By Publisher"), m_gameTreeItems.size(), false);
00248
00249
00250 m_gameTreeUI->assignTreeData(m_gameTree);
00251 m_gameTreeUI->enter();
00252 m_gameTreeUI->pushDown();
00253
00254 updateForeground();
00255 }
00256
00257 GameTree::~GameTree()
00258 {
00259 delete m_gameTree;
00260 }
00261
00262 void GameTree::updateRomInfo(RomInfo *rom) {
00263
00264 m_gameTitle->SetText(rom->Gamename());
00265 m_gameSystem->SetText(rom->AllSystems());
00266 m_gameYear->SetText(rom->Year());
00267 m_gameGenre->SetText(rom->Genre());
00268
00269 if (rom->Favorite())
00270 m_gameFavourite->SetText("Yes");
00271 else
00272 m_gameFavourite->SetText("No");
00273
00274 if (rom->ImagePath())
00275 m_gameImage->SetImage(rom->ImagePath());
00276
00277 }
00278
00279 void GameTree::clearRomInfo(void) {
00280 m_gameTitle->SetText("");
00281 m_gameSystem->SetText("");
00282 m_gameYear->SetText("");
00283 m_gameGenre->SetText("");
00284 m_gameFavourite->SetText("");
00285 m_gameImage->SetImage("");
00286
00287 if (m_gameImage->isShown())
00288 m_gameImage->hide();
00289
00290 }
00291
00292 void GameTree::handleTreeListEntry(int nodeInt, IntVector *)
00293 {
00294 GameTreeItem *item = nodeInt ? m_gameTreeItems[nodeInt - 1] : 0;
00295 RomInfo *romInfo = item ? item->getRomInfo() : 0;
00296
00297 if (item && !item->isLeaf())
00298 {
00299 GenericTree *node = m_gameTreeUI->getCurrentNode();
00300 if (!node)
00301 {
00302 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't get current node"));
00303 return;
00304 }
00305 if (!item->isFilled() || node == m_favouriteNode)
00306 {
00307 node->deleteAllChildren();
00308 fillNode(node);
00309 }
00310 }
00311
00312 if (romInfo)
00313 {
00314 if (item->isLeaf() && romInfo->Romname().isEmpty())
00315 romInfo->fillData();
00316
00317 updateRomInfo(romInfo);
00318
00319 if (item->isLeaf())
00320 {
00321 if (romInfo->ImagePath())
00322 {
00323 if ( timer->isActive() )
00324 timer->changeInterval(330);
00325 else
00326 timer->start(330, true);
00327
00328 }
00329 }
00330 else {
00331 if ( timer->isActive() )
00332 timer->stop();
00333
00334 clearRomInfo();
00335 }
00336 }
00337 else
00338 {
00339 if ( timer->isActive() )
00340 timer->stop();
00341
00342 clearRomInfo();
00343 }
00344
00345 }
00346
00347 void GameTree::showImageTimeout(void)
00348 {
00349 m_gameImage->LoadImage();
00350 if (!m_gameImage->isShown())
00351 m_gameImage->show();
00352 }
00353
00354
00355 QString getElement(QStringList list, int pos)
00356 {
00357 int curpos = 0;
00358
00359 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00360 if (curpos == pos)
00361 return *it;
00362 curpos++;
00363 }
00364 return NULL;
00365 }
00366
00367 void GameTree::handleTreeListSelection(int nodeInt, IntVector *)
00368 {
00369 if (nodeInt > 0)
00370 {
00371 GameTreeItem *item = nodeInt ? m_gameTreeItems[nodeInt - 1] : 0;
00372
00373 if (item->isLeaf())
00374 {
00375 if (item->getRomInfo()->RomCount() == 1)
00376 GameHandler::Launchgame(item->getRomInfo(),NULL);
00377 else if (item->getRomInfo()->RomCount() > 1)
00378 {
00379 QString all_systems = item->getRomInfo()->AllSystems();
00380 QStringList players = QStringList::split(",", all_systems);
00381 players += QObject::tr("Cancel");
00382
00383 DialogCode val = MythPopupBox::ShowButtonPopup(
00384 gContext->GetMainWindow(),
00385 "", tr("Players Available. \n\n Please pick one."),
00386 players, kDialogCodeButton0);
00387
00388 int idx = MythDialog::CalcItemIndex(val);
00389 if ((0 <= idx) && (idx < ((int)players.size() - 1)))
00390 {
00391 QString systemname = getElement(players, idx);
00392 if (!systemname.isEmpty())
00393 GameHandler::Launchgame(item->getRomInfo(),systemname);
00394 }
00395 }
00396 raise();
00397 setActiveWindow();
00398 }
00399 }
00400 }
00401
00402 void GameTree::showInfo(void)
00403 {
00404 GenericTree *curNode = m_gameTreeUI->getCurrentNode();
00405 int i = curNode->getInt();
00406 GameTreeItem *curItem = i ? m_gameTreeItems[i - 1] : 0;
00407 if (curItem && curItem->getRomInfo() && curItem->isLeaf())
00408 curItem->showGameInfo(curItem->getRomInfo());
00409 }
00410
00411 void GameTreeItem::showGameInfo(RomInfo *rom)
00412 {
00413 if (info_popup)
00414 return;
00415
00416 info_popup = new MythPopupBox(gContext->GetMainWindow(), "info_popup");
00417
00418
00419 info_popup->addLabel(QString("Name: %1 (%2)")
00420 .arg(rom->Gamename()).arg(rom->GameType()));
00421 info_popup->addLabel(QString("Rom : %1").arg(rom->Romname()));
00422 info_popup->addLabel(QString("CRC : %1").arg(rom->CRC_VALUE()));
00423 info_popup->addLabel(QString("Path: %1").arg(rom->Rompath()));
00424
00425 info_popup->addLabel(QString("Genre: %1").arg(rom->Genre()));
00426 info_popup->addLabel(QString("Year: %1").arg(rom->Year()));
00427 info_popup->addLabel(QString("Country: %1").arg(rom->Country()));
00428 info_popup->addLabel(QString("Publisher: %1").arg(rom->Publisher()));
00429
00430 info_popup->addLabel(QString("Player(s): %1").arg(rom->AllSystems()));
00431
00432 OKButton = info_popup->addButton(QString("OK"), this,
00433 SLOT(closeGameInfo()));
00434 OKButton->setFocus();
00435 info_popup->addButton(QString("EDIT"), this,
00436 SLOT(edit()));
00437
00438 info_popup->ShowPopup(this,SLOT(closeGameInfo()));
00439 }
00440
00441 void GameTreeItem::closeGameInfo(void)
00442 {
00443 if (info_popup)
00444 {
00445 info_popup->deleteLater();
00446 info_popup = NULL;
00447 }
00448 }
00449
00450 void GameTreeItem::edit(void)
00451 {
00452 if (m_romInfo)
00453 {
00454 m_romInfo->edit_rominfo();
00455 }
00456
00457 if (info_popup)
00458 {
00459 info_popup->deleteLater();
00460 info_popup = NULL;
00461 }
00462 }
00463
00464 void GameTree::keyPressEvent(QKeyEvent *e)
00465 {
00466 bool handled = false;
00467 QStringList actions;
00468 gContext->GetMainWindow()->TranslateKeyPress("Game", e, actions);
00469
00470 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00471 {
00472 QString action = actions[i];
00473 handled = true;
00474
00475 if (action == "SELECT")
00476 m_gameTreeUI->select();
00477 else if (action == "MENU" || action == "INFO")
00478 showInfo();
00479 else if (action == "UP")
00480 m_gameTreeUI->moveUp();
00481 else if (action == "DOWN")
00482 m_gameTreeUI->moveDown();
00483 else if (action == "LEFT")
00484 m_gameTreeUI->popUp();
00485 else if (action == "RIGHT")
00486 m_gameTreeUI->pushDown();
00487 else if (action == "PAGEUP")
00488 m_gameTreeUI->pageUp();
00489 else if (action == "PAGEDOWN")
00490 m_gameTreeUI->pageDown();
00491 else if (action == "TOGGLEFAV")
00492 toggleFavorite();
00493 else if (action == "INCSEARCH")
00494 m_gameTreeUI->incSearchStart();
00495 else if (action == "INCSEARCHNEXT")
00496 m_gameTreeUI->incSearchNext();
00497 else
00498 handled = false;
00499 }
00500
00501 if (!handled)
00502 MythThemedDialog::keyPressEvent(e);
00503 }
00504
00505 void GameTree::wireUpTheme(void)
00506 {
00507 m_gameTreeUI = getUIManagedTreeListType("gametreelist");
00508 if (!m_gameTreeUI)
00509 {
00510 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find a gametreelist in your theme"));
00511 exit(0);
00512 }
00513 m_gameTreeUI->showWholeTree(true);
00514 m_gameTreeUI->colorSelectables(true);
00515
00516 connect(m_gameTreeUI, SIGNAL(nodeSelected(int, IntVector*)),
00517 this, SLOT(handleTreeListSelection(int, IntVector*)));
00518 connect(m_gameTreeUI, SIGNAL(nodeEntered(int, IntVector*)),
00519 this, SLOT(handleTreeListEntry(int, IntVector*)));
00520
00521 m_gameTitle = getUITextType("gametitle");
00522 if (!m_gameTitle)
00523 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find a text area gametitle"));
00524
00525 m_gameSystem = getUITextType("systemname");
00526 if (!m_gameSystem)
00527 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find a text area systemname"));
00528
00529 m_gameYear = getUITextType("yearname");
00530 if (!m_gameYear)
00531 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find a text area yearname"));
00532
00533 m_gameGenre = getUITextType("genrename");
00534 if (!m_gameGenre)
00535 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find a text area genrename"));
00536
00537 m_gameFavourite = getUITextType("showfavorite");
00538 if (!m_gameFavourite)
00539 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find a text area showfavorite"));
00540
00541 m_gameImage = getUIImageType("gameimage");
00542 if (!m_gameImage)
00543 VERBOSE(VB_GENERAL, LOC_ERR + QString("Couldn't find an imagetag gameimage"));
00544 }
00545
00546 void GameTree::fillNode(GenericTree *node)
00547 {
00548 int i = node->getInt();
00549 GameTreeItem* curItem = m_gameTreeItems[i - 1];
00550 QString layername = node->getString();
00551
00552 MSqlQuery query(MSqlQuery::InitCon());
00553
00554 query.prepare(curItem->getFillSql(layername));
00555
00556 if (curItem->m_romInfo)
00557 {
00558 if (!curItem->m_romInfo->System().isEmpty())
00559 query.bindValue(":SYSTEM", curItem->m_romInfo->System());
00560 else if (curItem->m_romInfo->Year() != "")
00561 query.bindValue(":YEAR", curItem->m_romInfo->Year());
00562 else if (!curItem->m_romInfo->Genre().isEmpty())
00563 query.bindValue(":GENRE", curItem->m_romInfo->Genre());
00564 else if (!curItem->m_romInfo->Publisher().isEmpty())
00565 query.bindValue(":PUBLISHER", curItem->m_romInfo->Publisher());
00566 else if (!curItem->m_romInfo->Gamename().isEmpty())
00567 query.bindValue(":GAMENAME", curItem->m_romInfo->Gamename());
00568 }
00569
00570 query.exec();
00571
00572 if (query.isActive() && query.size() > 0)
00573 {
00574 while (query.next())
00575 {
00576 GameTreeItem *childItem = curItem->createChild(&query);
00577 m_gameTreeItems.push_back(childItem);
00578 node->addNode(query.value(0).toString().stripWhiteSpace(),
00579 m_gameTreeItems.size(), childItem->isLeaf());
00580 }
00581 }
00582 curItem->setFilled(true);
00583 }
00584
00585 void GameTree::toggleFavorite(void)
00586 {
00587 GenericTree *node = m_gameTreeUI->getCurrentNode();
00588 int i = node->getInt();
00589 GameTreeItem *item = i ? m_gameTreeItems[i - 1] : 0;
00590
00591 if (item && item->isLeaf())
00592 {
00593 item->getRomInfo()->setFavorite();
00594 if (item->getRomInfo()->Favorite())
00595 m_gameFavourite->SetText("Yes");
00596 else
00597 m_gameFavourite->SetText("No");
00598 }
00599 }