Ticket #603: gallery_removable_v5.diff
File gallery_removable_v5.diff, 39.7 KB (added by , 18 years ago) |
---|
-
mythgallery/mythgallery/glsingleview.cpp
405 405 { 406 406 ThumbItem *item = m_itemList.at(m_pos); 407 407 if (item) { 408 if( item->Remove() ) {408 if( GalleryUtil::Delete(item->path) ) { 409 409 m_zoom = 1.0; 410 410 m_sx = 0; 411 411 m_sy = 0; -
mythgallery/mythgallery/galleryutil.h
1 // -*- Mode: c++ -*- 1 2 /* ============================================================ 2 3 * File : exifutil.h 3 4 * Description : … … 23 24 24 25 class GalleryUtil 25 26 { 26 27 27 public: 28 28 static bool isImage(const char* filePath); 29 29 static bool isMovie(const char* filePath); … … 34 34 static bool loadDirectory(ThumbList& itemList, 35 35 const QString& dir, bool recurse, 36 36 ThumbDict *itemDict, ThumbGenerator* thumbGen); 37 38 static bool CopyMove(const QFileInfo &src, QFileInfo &dst, bool move) 39 { if (move) return Move(src, dst); else return Copy(src, dst); } 40 41 static bool Copy(const QFileInfo &src, QFileInfo &dst); 42 static bool Move(const QFileInfo &src, QFileInfo &dst); 43 static bool Delete(const QFileInfo &file); 44 45 private: 46 static bool CopyDirectory(const QFileInfo src, QFileInfo &dst); 47 static bool MoveDirectory(const QFileInfo src, QFileInfo &dst); 48 static bool DeleteDirectory(const QFileInfo &dir); 37 49 }; 38 50 39 51 #endif /* EXIFUTIL_H */ -
mythgallery/mythgallery/singleview.cpp
450 450 { 451 451 ThumbItem *item = m_itemList.at(m_pos); 452 452 if (item) { 453 if( item->Remove() ) {453 if( GalleryUtil::Delete(item->path) ) { 454 454 m_zoom = 1.0; 455 455 m_sx = 0; 456 456 m_sy = 0; -
mythgallery/mythgallery/iconview.cpp
31 31 #include <mythtv/xmlparse.h> 32 32 #include <mythtv/dialogbox.h> 33 33 #include <mythtv/mythdbcon.h> 34 #include <mythtv/mythdialogs.h> 34 35 36 #ifndef _WIN32 37 #include <mythtv/mythmediamonitor.h> 38 #endif 39 35 40 #include "galleryutil.h" 36 41 #include "gallerysettings.h" 37 42 #include "thumbgenerator.h" … … 45 50 #include "glsingleview.h" 46 51 #endif 47 52 48 49 53 int ThumbItem::GetRotationAngle() 50 54 { 51 55 MSqlQuery query(MSqlQuery::InitCon()); … … 84 88 return false; 85 89 } 86 90 87 IconView::IconView(const QString& galleryDir, MythM ainWindow* parent,88 const char* name )91 IconView::IconView(const QString& galleryDir, MythMediaDevice *initialDevice, 92 MythMainWindow* parent, const char* name ) 89 93 : MythDialog(parent, name) 90 94 { 91 95 m_galleryDir = galleryDir; 92 96 93 97 m_inMenu = false; 98 m_inSubMenu = false; 94 99 m_itemList.setAutoDelete(true); 95 100 m_itemDict.setAutoDelete(false); 96 101 … … 108 113 m_lastCol = 0; 109 114 m_topRow = 0; 110 115 m_isGallery = false; 116 m_showDevices = false; 117 m_currDevice = initialDevice; 111 118 112 119 srand(time(NULL)); 113 loadDirectory(galleryDir); 120 121 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 122 if (m_currDevice && mon && mon->ValidateAndLock(m_currDevice)) 123 { 124 if (!m_currDevice->isMounted(true)) 125 m_currDevice->mount(); 126 127 connect(m_currDevice, SIGNAL(statusChanged(MediaStatus, MythMediaDevice*)), 128 SLOT(mediaStatusChanged(MediaStatus, MythMediaDevice*))); 129 130 loadDirectory(m_currDevice->getMountPath()); 131 132 mon->Unlock(m_currDevice); 133 } 134 else 135 { 136 m_currDevice = NULL; 137 loadDirectory(galleryDir); 138 } 114 139 } 115 140 116 141 IconView::~IconView() 117 142 { 118 UIListBtnTypeItem* item = m_menuType->GetItemFirst(); 119 while (item) { 120 Action *act = (Action*) item->getData(); 121 if (act) 122 delete act; 123 item = m_menuType->GetItemNext(item); 124 } 143 clearMenu(m_submenuType); 144 clearMenu(m_menuType); 125 145 126 146 delete m_thumbGen; 127 147 delete m_theme; … … 258 278 item->pixmap->height()/2-bh2+sh, 259 279 bw-2*sw, bh-2*sh-(int)(15*hmult)); 260 280 281 if (m_itemMarked.contains(item->path)) 282 p.drawPixmap(xpos, ypos, m_MrkPix); 283 261 284 } 262 285 else { 263 286 … … 272 295 item->pixmap->width()/2-bw2+sw, 273 296 item->pixmap->height()/2-bh2+sh, 274 297 bw-2*sw, bh-2*sh); 298 299 if (m_itemMarked.contains(item->path)) 300 p.drawPixmap(xpos, ypos, m_MrkPix); 275 301 } 276 302 277 303 curPos++; … … 299 325 QString action = actions[i]; 300 326 if (action == "MENU") { 301 327 m_inMenu = !m_inMenu; 302 m_menuType->SetActive(m_inMenu); 328 m_menuType->SetActive(m_inMenu & !m_inSubMenu); 329 m_submenuType->SetActive(m_inMenu & m_inSubMenu); 303 330 menuHandled = true; 304 331 } 332 else if (action == "ESCAPE") { 333 if (m_inMenu & m_inSubMenu) { 334 actionMainMenu(); 335 m_menuType->SetActive(m_inMenu & !m_inSubMenu); 336 m_submenuType->SetActive(m_inMenu & m_inSubMenu); 337 menuHandled = true; 338 } 339 } 305 340 else if (action == "UP") { 306 if (m_inMenu ) {341 if (m_inMenu & !m_inSubMenu) { 307 342 m_menuType->MoveUp(); 308 343 menuHandled = true; 309 344 } 345 else if (m_inMenu & m_inSubMenu) { 346 m_submenuType->MoveUp(); 347 menuHandled = true; 348 } 310 349 else 311 350 handled = moveUp(); 312 351 } 313 352 else if (action == "DOWN") { 314 if (m_inMenu ) {353 if (m_inMenu & !m_inSubMenu) { 315 354 m_menuType->MoveDown(); 316 355 menuHandled = true; 317 356 } 357 else if (m_inMenu & m_inSubMenu) { 358 m_submenuType->MoveDown(); 359 menuHandled = true; 360 } 318 361 else 319 362 handled = moveDown(); 320 363 } … … 363 406 actionDelete(); 364 407 handled = true; 365 408 } 409 else if (action == "MARK") 410 { 411 int pos = m_currRow * m_nCols + m_currCol; 412 ThumbItem *item = m_itemList.at(pos); 413 if (!item) { 414 std::cerr << "The impossible happened" << std::endl; 415 break; 416 } 417 418 if (!m_itemMarked.contains(item->path)) 419 m_itemMarked.append(item->path); 420 else 421 m_itemMarked.remove(item->path); 422 423 handled = true; 424 } 366 425 else if (action == "SELECT" || action == "PLAY" || action == "SLIDESHOW" || action == "RANDOMSHOW" ) 367 426 { 368 427 if (m_inMenu && (action == "SELECT" || action == "PLAY") ) { … … 378 437 } 379 438 380 439 QFileInfo fi(item->path); 381 if (item->isDir && (action == "SELECT" || action == "PLAY") ) { 440 441 // if the selected item is a Media Device 442 // attempt to mount it if it isn't already 443 if (item->mediaDevice && (action == "SELECT" || action == "PLAY") ) 444 { 445 446 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 447 if (mon && mon->ValidateAndLock(item->mediaDevice)) 448 { 449 m_currDevice = item->mediaDevice; 450 451 if (!m_currDevice->isMounted()) 452 m_currDevice->mount(); 453 454 item->path = m_currDevice->getMountPath(); 455 456 connect(m_currDevice, 457 SIGNAL(statusChanged(MediaStatus, MythMediaDevice*)), 458 SLOT(mediaStatusChanged(MediaStatus, MythMediaDevice*))); 459 460 mon->Unlock(m_currDevice); 461 } 462 else 463 { 464 // device was removed 465 MythPopupBox::showOkPopup(gContext->GetMainWindow(), 466 tr("Error"), 467 tr("The selected device is no longer available")); 468 469 actionShowDevices(); 470 m_currRow = 0; 471 m_currCol = 0; 472 handled = true; 473 break; 474 } 475 } 476 477 if (!handled && item->isDir && 478 (action == "SELECT" || action == "PLAY") ) { 382 479 loadDirectory(item->path); 383 480 handled = true; 384 481 } … … 414 511 gContext->GetMainWindow()); 415 512 sv.exec(); 416 513 } 514 515 // if the user deleted files while in single view mode 516 // the cached contents of the directory will be out of 517 // sync, reload the current directory to refresh the view 518 loadDirectory(m_currDir); 417 519 } 418 520 } 419 521 } … … 426 528 { 427 529 QString action = actions[i]; 428 530 if (action == "ESCAPE") { 531 if (m_showDevices) 532 { 533 loadDirectory(m_galleryDir); 534 handled = true; 535 } 536 else 537 { 429 538 QDir d(m_currDir); 539 #ifndef _WIN32 540 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 541 if (mon) 542 { 543 QValueList<MythMediaDevice*> removables = 544 mon->GetMedias(MEDIATYPE_DATA); 545 546 QValueList<MythMediaDevice*>::Iterator it = 547 removables.begin(); 548 for (; it != removables.end(); it++) 549 { 550 if (mon->ValidateAndLock(*it)) 551 { 552 if (d == QDir((*it)->getMountPath())) 553 { 554 actionShowDevices(); 555 556 // make sure previous devies is visible and selected 557 ThumbItem *item; 558 if ((*it)->getVolumeID() != "") 559 item = m_itemDict.find((*it)->getVolumeID()); 560 else 561 item = m_itemDict.find((*it)->getDevicePath()); 562 563 if (item) 564 { 565 int pos = m_itemList.find(item); 566 if (pos != -1) 567 { 568 m_currRow = pos/m_nCols; 569 m_currCol = pos-m_currRow*m_nCols; 570 m_topRow = QMAX(0, m_currRow-(m_nRows-1)); 571 } 572 } 573 handled = true; 574 mon->Unlock(*it); 575 break; 576 } 577 mon->Unlock(*it); 578 } 579 } 580 } 581 582 if (!handled) 583 { 584 #endif 430 585 if (d != QDir(m_galleryDir)) { 431 586 432 587 QString oldDirName = d.dirName(); … … 445 600 } 446 601 handled = true; 447 602 } 603 #ifndef _WIN32 604 } 605 } 606 #endif 448 607 } 449 608 } 450 609 } … … 456 615 { 457 616 MythDialog::keyPressEvent(e); 458 617 } 459 460 618 } 461 619 462 620 void IconView::customEvent(QCustomEvent *e) … … 547 705 exit(-1); 548 706 } 549 707 708 m_submenuType = (UIListBtnType*)container->GetType("submenu"); 709 if (!m_menuType) { 710 std::cerr << "MythGallery: Failed to get submenu area." 711 << std::endl; 712 exit(-1); 713 } 714 550 715 // Menu Actions 551 716 552 717 UIListBtnTypeItem* item; … … 554 719 item->setData(new Action(&IconView::actionSlideShow)); 555 720 item = new UIListBtnTypeItem(m_menuType, tr("Random")); 556 721 item->setData(new Action(&IconView::actionRandomShow)); 557 item = new UIListBtnTypeItem(m_menuType, tr("Rotate CW")); 558 item->setData(new Action(&IconView::actionRotateCW)); 559 item = new UIListBtnTypeItem(m_menuType, tr("Rotate CCW")); 560 item->setData(new Action(&IconView::actionRotateCCW)); 561 item = new UIListBtnTypeItem(m_menuType, tr("Delete")); 562 item->setData(new Action(&IconView::actionDelete)); 563 item = new UIListBtnTypeItem(m_menuType, tr("Import")); 564 item->setData(new Action(&IconView::actionImport)); 722 item = new UIListBtnTypeItem(m_menuType, tr("Meta Data...")); 723 item->setData(new Action(&IconView::actionSubMenuMetadata)); 724 item = new UIListBtnTypeItem(m_menuType, tr("Marking...")); 725 item->setData(new Action(&IconView::actionSubMenuMark)); 726 item = new UIListBtnTypeItem(m_menuType, tr("File...")); 727 item->setData(new Action(&IconView::actionSubMenuFile)); 565 728 item = new UIListBtnTypeItem(m_menuType, tr("Settings")); 566 729 item->setData(new Action(&IconView::actionSettings)); 567 730 … … 618 781 m_folderSelPix = QPixmap(*img); 619 782 delete img; 620 783 784 img = gContext->LoadScaleImage("gallery-mark.png"); 785 if (!img) { 786 std::cerr << "Failed to load gallery-mark.png" 787 << std::endl; 788 exit(-1); 789 } 790 m_MrkPix = QPixmap(*img); 791 delete img; 792 621 793 m_thumbW = m_backRegPix.width(); 622 794 m_thumbH = m_backRegPix.height(); 623 795 m_nCols = m_viewRect.width()/m_thumbW - 1; … … 634 806 if (!d.exists()) 635 807 return; 636 808 809 m_showDevices = false; 810 637 811 m_currDir = d.absPath(); 638 812 m_itemList.clear(); 639 813 m_itemDict.clear(); … … 778 952 779 953 void IconView::pressMenu() 780 954 { 781 UIListBtnTypeItem* item = m_menuType->GetItemCurrent();955 UIListBtnTypeItem* item; 782 956 957 if (m_inSubMenu) 958 item = m_submenuType->GetItemCurrent(); 959 else 960 item = m_menuType->GetItemCurrent(); 961 783 962 if (!item || !item->getData()) 784 963 return; 785 964 786 965 Action *act = (Action*) item->getData(); 787 966 (this->*(*act))(); 967 968 m_menuType->SetActive(m_inMenu & !m_inSubMenu); 969 m_submenuType->SetActive(m_inMenu & m_inSubMenu); 788 970 } 789 971 972 void IconView::actionMainMenu() 973 { 974 clearMenu(m_submenuType); 975 m_submenuType->Reset(); 976 977 m_inSubMenu = false; 978 } 979 980 void IconView::actionSubMenuMetadata() 981 { 982 clearMenu(m_submenuType); 983 m_submenuType->Reset(); 984 985 UIListBtnTypeItem *item; 986 item = new UIListBtnTypeItem(m_submenuType, tr("Return")); 987 item->setData(new Action(&IconView::actionMainMenu)); 988 item = new UIListBtnTypeItem(m_submenuType, tr("Rotate CW")); 989 item->setData(new Action(&IconView::actionRotateCW)); 990 item = new UIListBtnTypeItem(m_submenuType, tr("Rotate CCW")); 991 item->setData(new Action(&IconView::actionRotateCCW)); 992 993 m_inSubMenu = true; 994 } 995 996 void IconView::actionSubMenuMark() 997 { 998 clearMenu(m_submenuType); 999 m_submenuType->Reset(); 1000 1001 UIListBtnTypeItem *item; 1002 item = new UIListBtnTypeItem(m_submenuType, tr("Return")); 1003 item->setData(new Action(&IconView::actionMainMenu)); 1004 item = new UIListBtnTypeItem(m_submenuType, tr("Clear Marked")); 1005 item->setData(new Action(&IconView::actionClearMarked)); 1006 item = new UIListBtnTypeItem(m_submenuType, tr("Select All")); 1007 item->setData(new Action(&IconView::actionSelectAll)); 1008 1009 m_inSubMenu = true; 1010 } 1011 1012 void IconView::actionSubMenuFile() 1013 { 1014 clearMenu(m_submenuType); 1015 m_submenuType->Reset(); 1016 1017 UIListBtnTypeItem *item; 1018 item = new UIListBtnTypeItem(m_submenuType, tr("Return")); 1019 item->setData(new Action(&IconView::actionMainMenu)); 1020 item = new UIListBtnTypeItem(m_submenuType, tr("Show Devices")); 1021 item->setData(new Action(&IconView::actionShowDevices)); 1022 item = new UIListBtnTypeItem(m_submenuType, tr("Import")); 1023 item->setData(new Action(&IconView::actionImport)); 1024 item = new UIListBtnTypeItem(m_submenuType, tr("Copy here")); 1025 item->setData(new Action(&IconView::actionCopyHere)); 1026 item = new UIListBtnTypeItem(m_submenuType, tr("Move here")); 1027 item->setData(new Action(&IconView::actionMoveHere)); 1028 item = new UIListBtnTypeItem(m_submenuType, tr("Delete")); 1029 item->setData(new Action(&IconView::actionDelete)); 1030 item = new UIListBtnTypeItem(m_submenuType, tr("Create Dir")); 1031 item->setData(new Action(&IconView::actionMkDir)); 1032 1033 m_inSubMenu = true; 1034 } 1035 790 1036 void IconView::actionRotateCW() 791 1037 { 792 1038 ThumbItem* item = m_itemList.at(m_currRow * m_nCols + … … 833 1079 } 834 1080 } 835 1081 836 void IconView::actionDelete ()1082 void IconView::actionDeleteCurrent() 837 1083 { 838 ThumbItem* item = m_itemList.at(m_currRow * m_nCols + 839 m_currCol); 840 if (!item || item->isDir)1084 ThumbItem* item = m_itemList.at(m_currRow * m_nCols + m_currCol); 1085 1086 if (!item) 841 1087 return; 842 1088 843 if( item->Remove() ) { 844 loadDirectory(m_currDir, false); 1089 bool cont = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), 1090 tr("Delete Current File or Folder"), 1091 (item->isDir) ? 1092 QString(tr("Deleting 1 folder, including any " 1093 "subfolders and files.")) : 1094 QString(tr("Deleting 1 image.")), 1095 false); 1096 1097 if (cont) 1098 { 1099 QFileInfo fi; 1100 fi.setFile(item->path); 1101 GalleryUtil::Delete(fi); 1102 1103 loadDirectory(m_currDir); 845 1104 } 846 1105 } 847 1106 … … 980 1239 } 981 1240 } 982 1241 1242 void IconView::actionShowDevices() 1243 { 1244 #ifndef _WIN32 1245 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 1246 if (m_currDevice && mon && mon->ValidateAndLock(m_currDevice)) 1247 { 1248 m_currDevice->disconnect(this); 1249 mon->Unlock(m_currDevice); 1250 } 1251 #endif 1252 1253 m_currDevice = NULL; 1254 1255 m_showDevices = true; 1256 1257 m_itemList.clear(); 1258 m_itemDict.clear(); 1259 1260 m_thumbGen->cancel(); 1261 1262 // add gallery directory 1263 ThumbItem *item = new ThumbItem; 1264 item->name = QString("Gallery"); 1265 item->path = m_galleryDir; 1266 item->isDir = true; 1267 m_itemList.append(item); 1268 m_itemDict.insert(item->name, item); 1269 1270 #ifndef _WIN32 1271 if (mon) 1272 { 1273 QValueList<MythMediaDevice*> removables = mon->GetMedias(MEDIATYPE_DATA); 1274 QValueList<MythMediaDevice*>::Iterator it = removables.begin(); 1275 for (; it != removables.end(); it++) 1276 { 1277 if (mon->ValidateAndLock(*it)) 1278 { 1279 item = new ThumbItem; 1280 if ((*it)->getVolumeID() != "") 1281 item->name = (*it)->getVolumeID(); 1282 else 1283 item->name = (*it)->getDevicePath(); 1284 item->path = (*it)->getMountPath(); 1285 item->isDir = true; 1286 item->mediaDevice = *it; 1287 m_itemList.append(item); 1288 m_itemDict.insert(item->name, item); 1289 1290 mon->Unlock(*it); 1291 } 1292 } 1293 } 1294 #endif 1295 1296 m_lastRow = QMAX((int)ceilf((float)m_itemList.count()/(float)m_nCols)-1,0); 1297 m_lastCol = QMAX(m_itemList.count()-m_lastRow*m_nCols-1,0); 1298 } 1299 1300 void IconView::actionCopyHere() 1301 { 1302 CopyMarkedFiles(false); 1303 actionClearMarked(); 1304 } 1305 1306 void IconView::actionMoveHere() 1307 { 1308 CopyMarkedFiles(true); 1309 actionClearMarked(); 1310 } 1311 1312 void IconView::actionDelete() 1313 { 1314 if (m_itemMarked.isEmpty()) 1315 actionDeleteCurrent(); 1316 else 1317 actionDeleteMarked(); 1318 } 1319 1320 void IconView::actionDeleteMarked() 1321 { 1322 bool cont = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), 1323 tr("Delete Marked Files"), 1324 QString(tr("Deleting %1 images and folders, including " 1325 "any subfolders and files.")) 1326 .arg(m_itemMarked.count()), 1327 false); 1328 1329 if (cont) 1330 { 1331 QStringList::iterator it; 1332 QFileInfo fi; 1333 1334 for (it = m_itemMarked.begin(); it != m_itemMarked.end(); it++) 1335 { 1336 fi.setFile(*it); 1337 1338 GalleryUtil::Delete(fi); 1339 } 1340 1341 m_itemMarked.clear(); 1342 1343 loadDirectory(m_currDir); 1344 } 1345 } 1346 1347 void IconView::actionClearMarked() 1348 { 1349 m_itemMarked.clear(); 1350 } 1351 1352 void IconView::actionSelectAll() 1353 { 1354 ThumbItem *item; 1355 for (item = m_itemList.first(); item; item = m_itemList.next()) 1356 { 1357 if (!m_itemMarked.contains(item->path)) 1358 m_itemMarked.append(item->path); 1359 } 1360 } 1361 1362 void IconView::actionMkDir() 1363 { 1364 QString folderName = tr("New Folder"); 1365 1366 bool res = MythPopupBox::showGetTextPopup(gContext->GetMainWindow(), tr("Create New Folder"), 1367 tr("Create New Folder"), folderName); 1368 1369 if (res) 1370 { 1371 QDir cdir(m_currDir); 1372 cdir.mkdir(folderName); 1373 1374 loadDirectory(m_currDir); 1375 } 1376 } 1377 983 1378 void IconView::importFromDir(const QString &fromDir, const QString &toDir) 984 1379 { 985 1380 QDir d(fromDir); … … 1019 1414 } 1020 1415 } 1021 1416 } 1417 1418 void IconView::CopyMarkedFiles(bool move) 1419 { 1420 if (m_itemMarked.isEmpty()) 1421 return; 1422 1423 QStringList::iterator it; 1424 QFileInfo fi; 1425 QFileInfo dest; 1426 int count = 0; 1427 1428 1429 MythProgressDialog *progress = 1430 new MythProgressDialog((move) ? tr("Moving marked images...") : 1431 tr("Copying marked images..."), 1432 m_itemMarked.count()); 1433 1434 for (it = m_itemMarked.begin(); it != m_itemMarked.end(); it++) 1435 { 1436 fi.setFile(*it); 1437 dest.setFile(QDir(m_currDir), fi.fileName()); 1438 1439 if (fi.exists()) 1440 GalleryUtil::CopyMove(fi, dest, move); 1441 1442 progress->setProgress(++count); 1443 } 1444 1445 progress->Close(); 1446 delete progress; 1447 1448 loadDirectory(m_currDir); 1449 } 1450 1451 void IconView::clearMenu(UIListBtnType *menu) 1452 { 1453 UIListBtnTypeItem* item = menu->GetItemFirst(); 1454 while (item) 1455 { 1456 Action *act = (Action*) item->getData(); 1457 if (act) 1458 delete act; 1459 item = menu->GetItemNext(item); 1460 } 1461 } 1462 1463 void IconView::mediaStatusChanged(MediaStatus oldStatus, 1464 MythMediaDevice *pMedia) 1465 { 1466 (void) oldStatus; 1467 if (m_currDevice == pMedia) 1468 { 1469 actionShowDevices(); 1470 1471 m_currRow = 0; 1472 m_currCol = 0; 1473 1474 updateView(); 1475 updateText(); 1476 } 1477 } -
mythgallery/mythgallery/main.cpp
14 14 #include <mythtv/mythdialogs.h> 15 15 #include <mythtv/mythplugin.h> 16 16 #include <mythtv/dialogbox.h> 17 #include <mythtv/mythmedia.h> 17 18 18 19 extern "C" { 19 20 int mythplugin_init(const char *libversion); … … 33 34 diag.AddButton(QObject::tr("Ok")); 34 35 diag.exec(); 35 36 } 36 else { 37 IconView icv(startdir, gContext->GetMainWindow(), "IconView"); 37 else 38 { 39 IconView icv(startdir, NULL, gContext->GetMainWindow(), "IconView"); 38 40 icv.exec(); 39 41 } 40 42 gContext->removeCurrentLocation(); 41 43 } 42 44 45 void handleMedia(MythMediaDevice *dev) 46 { 47 QString galleryDir = gContext->GetSetting("GalleryDir"); 48 QDir dir(galleryDir); 49 if (!dir.exists() || !dir.isReadable()) 50 { 51 DialogBox diag(gContext->GetMainWindow(), 52 QObject::tr("Gallery Directory does not " 53 "exist or is unreadable.")); 54 diag.AddButton(QObject::tr("Ok")); 55 diag.exec(); 56 } 57 else 58 { 59 IconView icv(galleryDir, dev, gContext->GetMainWindow(), "IconView"); 60 icv.exec(); 61 } 62 } 63 64 43 65 void setupKeys(void) 44 66 { 45 67 REG_JUMP("MythGallery", "Image viewer / slideshow", "", runGallery); … … 67 89 REG_KEY("Gallery", "LOWRIGHT", "Go to the lower-right corner of the image", 68 90 "PgDown"); 69 91 REG_KEY("Gallery", "INFO", "Toggle Showing Information about Image", "I"); 70 REG_KEY("Gallery", "DELETE", "Delete current image", "D"); 92 REG_KEY("Gallery", "DELETE", "Delete marked images or current image if none are marked", "D"); 93 REG_KEY("Gallery", "MARK", "Mark image", "T"); 94 95 REG_MEDIA_HANDLER("MythGallery Media Handler", "", "", handleMedia, MEDIATYPE_DATA | MEDIATYPE_MIXED); 71 96 } 72 97 73 98 int mythplugin_init(const char *libversion) -
mythgallery/mythgallery/thumbgenerator.cpp
308 308 309 309 QString ThumbGenerator::getThumbcacheDir(const QString& inDir) 310 310 { 311 QString galleryDir = gContext->GetSetting("GalleryDir"); 312 311 313 // For directory "/my/images/january", this function either returns 312 314 // "/my/images/january/.thumbcache" or "~/.mythtv/mythgallery/january/.thumbcache" 313 315 QString aPath = inDir + QString("/.thumbcache/"); 314 316 if ( gContext->GetNumSetting("GalleryThumbnailLocation") 315 && ! QDir(aPath).exists() )317 && ! QDir(aPath).exists() && inDir.startsWith(galleryDir)) 316 318 { 317 319 mkpath(aPath); 318 320 } 319 if ( ! gContext->GetNumSetting("GalleryThumbnailLocation") || ! QDir(aPath).exists() )321 if ( ! gContext->GetNumSetting("GalleryThumbnailLocation") || ! QDir(aPath).exists() || ! inDir.startsWith(galleryDir)) 320 322 { 321 323 // Arrive here if storing thumbs in home dir, 322 324 // OR failed to create thumb dir in gallery pics location -
mythgallery/mythgallery/iconview.h
26 26 #include <qpixmap.h> 27 27 28 28 #include <mythtv/mythdialogs.h> 29 #include <mythtv/mythmedia.h> 29 30 30 31 class XMLParse; 31 32 class UIListBtnType; … … 42 43 caption= ""; 43 44 path = ""; 44 45 isDir = false; 46 mediaDevice = NULL; 45 47 } 46 48 47 49 ~ThumbItem() { … … 58 60 QString caption; 59 61 QString path; 60 62 bool isDir; 63 MythMediaDevice *mediaDevice; 61 64 }; 62 65 63 66 typedef QPtrList<ThumbItem> ThumbList; … … 69 72 70 73 public: 71 74 72 IconView(const QString& galleryDir, MythM ainWindow* parent,73 const char* name = 0);75 IconView(const QString& galleryDir, MythMediaDevice *initialDevice, 76 MythMainWindow* parent, const char* name = 0); 74 77 ~IconView(); 75 78 76 79 protected: … … 93 96 bool moveLeft(); 94 97 bool moveRight(); 95 98 99 void actionMainMenu(); 100 void actionSubMenuMetadata(); 101 void actionSubMenuMark(); 102 void actionSubMenuFile(); 103 96 104 void actionRotateCW(); 97 105 void actionRotateCCW(); 98 void actionDelete ();106 void actionDeleteCurrent(); 99 107 void actionSlideShow(); 100 108 void actionRandomShow(); 101 109 void actionSettings(); 102 110 void actionImport(); 111 #ifndef _WIN32 112 void actionShowDevices(); 113 #endif 114 void actionCopyHere(); 115 void actionMoveHere(); 116 void actionDelete(); 117 void actionDeleteMarked(); 118 void actionClearMarked(); 119 void actionSelectAll(); 120 void actionMkDir(); 103 121 104 122 void pressMenu(); 105 123 106 124 void loadThumbnail(ThumbItem *item); 107 125 void importFromDir(const QString &fromDir, const QString &toDir); 126 void CopyMarkedFiles(bool move = false); 127 128 void clearMenu(UIListBtnType *menu); 108 129 109 130 QPtrList<ThumbItem> m_itemList; 110 131 QDict<ThumbItem> m_itemDict; 132 QStringList m_itemMarked; 111 133 QString m_galleryDir; 112 134 113 135 XMLParse *m_theme; … … 116 138 QRect m_viewRect; 117 139 118 140 bool m_inMenu; 141 bool m_inSubMenu; 119 142 UIListBtnType *m_menuType; 143 UIListBtnType *m_submenuType; 120 144 121 145 QPixmap m_backRegPix; 122 146 QPixmap m_backSelPix; 123 147 QPixmap m_folderRegPix; 124 148 QPixmap m_folderSelPix; 149 QPixmap m_MrkPix; 125 150 126 151 QString m_currDir; 127 152 bool m_isGallery; 153 bool m_showDevices; 154 MythMediaDevice *m_currDevice; 128 155 129 156 int m_currRow; 130 157 int m_currCol; … … 143 170 int m_showcaption; 144 171 145 172 typedef void (IconView::*Action)(); 173 174 public slots: 175 void mediaStatusChanged( MediaStatus oldStatus, MythMediaDevice* pMedia); 146 176 }; 147 177 148 178 -
mythgallery/mythgallery/gallery-ui.xml
21 21 </font> 22 22 23 23 <container name="menu"> 24 <area>20,20,140, 240</area>24 <area>20,20,140,500</area> 25 25 26 26 <listbtnarea name="menu" draworder="0"> 27 27 <area>0,0,140,240</area> … … 35 35 <showscrollarrows>no</showscrollarrows> 36 36 </listbtnarea> 37 37 38 <listbtnarea name="submenu" draworder="0"> 39 <area>0,260,140,240</area> 40 <gradient type="unselected" start="#000000" end="#505050" alpha="100"> 41 </gradient> 42 <gradient type="selected" start="#52CA38" end="#349838" alpha="255"> 43 </gradient> 44 <fcnfont name="active" function="active"></fcnfont> 45 <fcnfont name="inactive" function="inactive"></fcnfont> 46 <showarrow>no</showarrow> 47 <showscrollarrows>no</showscrollarrows> 48 </listbtnarea> 49 38 50 </container> 39 51 40 52 <container name="text"> -
mythgallery/mythgallery/galleryutil.cpp
16 16 * 17 17 * ============================================================ */ 18 18 19 #include <iostream>20 19 #include <qfileinfo.h> 21 20 #include <qdir.h> 22 21 22 #include <mythtv/mythcontext.h> 23 #include <mythtv/mythdbcon.h> 24 #include <mythtv/util.h> 25 23 26 #include "config.h" 24 27 #include "constants.h" 25 28 #include "galleryutil.h" … … 31 34 // include "exif.hpp" 32 35 #endif // EXIF_SUPPORT 33 36 37 #define LOC QString("GalleryUtil:") 38 #define LOC_ERR QString("GalleryUtil, Error:") 39 40 static QFileInfo MakeUnique(const QFileInfo &dest); 41 static QFileInfo MakeUniqueDirectory(const QFileInfo &dest); 42 static bool FileCopy(const QFileInfo &src, const QFileInfo &dst); 43 static bool FileMove(const QFileInfo &src, const QFileInfo &dst); 44 static bool FileDelete(const QFileInfo &file); 45 34 46 bool GalleryUtil::isImage(const char* filePath) 35 47 { 36 48 QFileInfo fi(filePath); … … 81 93 } 82 94 else 83 95 { 84 std::cerr << "Could not load exif data from " << filePath << std::endl; 96 VERBOSE(VB_IMPORTANT, LOC_ERR + 97 QString("Could not load exif data from '%1'") 98 .arg(filePath)); 85 99 } 86 100 87 101 delete [] exifvalue; … … 115 129 } 116 130 catch (...) 117 131 { 118 std::cerr << "GalleryUtil: Failed to extract EXIF headers from " 119 << filePath << std::endl; 132 VERBOSE(VB_IMPORTANT, LOC_ERR + 133 QString("Failed to extract EXIF headers from '%1'") 134 .arg(filePath)); 120 135 } 121 136 122 137 return rotateAngle; … … 249 264 } 250 265 else 251 266 { 252 std::cerr << "Could not load exif data from " << filePath << std::endl; 267 VERBOSE(VB_IMPORTANT, LOC_ERR + 268 QString("Could not load exif data from '%1'") 269 .arg(filePath)); 253 270 } 254 271 255 272 delete [] exifvalue; … … 257 274 } 258 275 catch (...) 259 276 { 260 std::cerr << "GalleryUtil: Failed to extract EXIF headers from " 261 << filePath << std::endl; 277 VERBOSE(VB_IMPORTANT, LOC_ERR + 278 QString("Failed to extract EXIF headers from '%1'") 279 .arg(filePath)); 262 280 } 263 281 264 282 return caption; 265 283 } 284 285 bool GalleryUtil::Copy(const QFileInfo &src, QFileInfo &dst) 286 { 287 if (src.isDir()) 288 return CopyDirectory(src, dst); 289 290 dst = MakeUnique(dst); 291 292 if (!FileCopy(src, dst)) 293 return false; 294 295 MSqlQuery query(MSqlQuery::InitCon()); 296 query.prepare("INSERT INTO gallerymetadata (image, keywords, angle) " 297 "SELECT :IMAGENEW , keywords, angle " 298 "FROM gallerymetadata " 299 "WHERE image = :IMAGEOLD"); 300 query.bindValue(":IMAGENEW", dst.absFilePath().utf8()); 301 query.bindValue(":IMAGEOLD", src.absFilePath().utf8()); 302 if (query.exec()) 303 return true; 304 305 // try to undo copy on DB failure 306 FileDelete(dst); 307 return false; 308 } 309 310 bool GalleryUtil::Move(const QFileInfo &src, QFileInfo &dst) 311 { 312 if (src.isDir()) 313 return MoveDirectory(src, dst); 314 315 dst = MakeUnique(dst); 316 317 if (!FileMove(src, dst)) 318 return false; 319 320 MSqlQuery query(MSqlQuery::InitCon()); 321 query.prepare("UPDATE gallerymetadata " 322 "SET image = :IMAGENEW " 323 "WHERE image = :IMAGEOLD"); 324 query.bindValue(":IMAGENEW", dst.absFilePath().utf8()); 325 query.bindValue(":IMAGEOLD", src.absFilePath().utf8()); 326 if (query.exec()) 327 return true; 328 329 // try to undo move on DB failure 330 FileMove(dst, src); 331 return false; 332 } 333 334 bool GalleryUtil::Delete(const QFileInfo &file) 335 { 336 if (!file.exists()) 337 return false; 338 339 if (file.isDir()) 340 return DeleteDirectory(file); 341 342 MSqlQuery query(MSqlQuery::InitCon()); 343 query.prepare("DELETE FROM gallerymetadata " 344 "WHERE image = :IMAGE ;"); 345 query.bindValue(":IMAGE", file.absFilePath().utf8()); 346 if (query.exec()) 347 return FileDelete(file); 348 349 return false; 350 } 351 352 bool GalleryUtil::CopyDirectory(const QFileInfo src, QFileInfo &dst) 353 { 354 QDir srcDir(src.absFilePath()); 355 356 dst = MakeUniqueDirectory(dst); 357 if (!dst.exists()) 358 { 359 srcDir.mkdir(dst.absFilePath()); 360 dst.refresh(); 361 } 362 363 if (!dst.exists() || !dst.isDir()) 364 return false; 365 366 bool ok = true; 367 QDir dstDir(dst.absFilePath()); 368 QFileInfoListIterator it(*srcDir.entryInfoList()); 369 for (; it.current(); ++it) 370 { 371 const QString fn = (it.current())->fileName(); 372 if (fn != "." && fn != "..") 373 { 374 QFileInfo dfi(dstDir, fn); 375 ok &= Copy(*(it.current()), dfi); 376 } 377 } 378 379 return ok; 380 } 381 382 bool GalleryUtil::MoveDirectory(const QFileInfo src, QFileInfo &dst) 383 { 384 QDir srcDir(src.absFilePath()); 385 386 dst = MakeUniqueDirectory(dst); 387 if (!dst.exists()) 388 { 389 srcDir.mkdir(dst.absFilePath()); 390 dst.refresh(); 391 } 392 393 if (!dst.exists() || !dst.isDir()) 394 return false; 395 396 bool ok = true; 397 QDir dstDir(dst.absFilePath()); 398 QFileInfoListIterator it(*srcDir.entryInfoList()); 399 for (; it.current(); ++it) 400 { 401 const QString fn = (it.current())->fileName(); 402 if (fn != "." && fn != "..") 403 { 404 QFileInfo dfi(dstDir, fn); 405 ok &= Move(*(it.current()), dfi); 406 } 407 } 408 409 return ok && FileDelete(src); 410 } 411 412 bool GalleryUtil::DeleteDirectory(const QFileInfo &dir) 413 { 414 if (!dir.exists()) 415 return false; 416 417 QDir srcDir(dir.absFilePath()); 418 QFileInfoListIterator it(*srcDir.entryInfoList()); 419 for (; it.current(); ++it) 420 { 421 const QString fn = (it.current())->fileName(); 422 if (fn != "." && fn != "..") 423 Delete(*(it.current())); 424 } 425 426 return FileDelete(dir); 427 } 428 429 static QFileInfo MakeUnique(const QFileInfo &dest) 430 { 431 QFileInfo newDest = dest; 432 433 for (uint i = 0; newDest.exists(); i++) 434 { 435 QString basename = QString("%1_%2.%3") 436 .arg(dest.baseName(false)).arg(i).arg(dest.extension()); 437 438 newDest.setFile(dest.dir(), basename); 439 440 VERBOSE(VB_GENERAL, LOC_ERR + 441 QString("Need to find a new name for '%1' trying '%2'") 442 .arg(dest.absFilePath()).arg(newDest.absFilePath())); 443 } 444 445 return newDest; 446 } 447 448 static QFileInfo MakeUniqueDirectory(const QFileInfo &dest) 449 { 450 QFileInfo newDest = dest; 451 452 for (uint i = 0; newDest.exists() && !newDest.isDir(); i++) 453 { 454 QString fullname = QString("%1_%2").arg(dest.absFilePath()).arg(i); 455 newDest.setFile(fullname); 456 457 VERBOSE(VB_GENERAL, LOC_ERR + 458 QString("Need to find a new name for '%1' trying '%2'") 459 .arg(dest.absFilePath()).arg(newDest.absFilePath())); 460 } 461 462 return newDest; 463 } 464 465 static bool FileCopy(const QFileInfo &src, const QFileInfo &dst) 466 { 467 const int bufferSize = 16*1024; 468 469 QFile s(src.absFilePath()); 470 QFile d(dst.absFilePath()); 471 char buffer[bufferSize]; 472 int len; 473 474 if (!s.open(IO_ReadOnly)) 475 return false; 476 477 if (!d.open(IO_WriteOnly)) 478 { 479 s.close(); 480 return false; 481 } 482 483 len = s.readBlock(buffer, bufferSize); 484 do 485 { 486 d.writeBlock(buffer, len); 487 len = s.readBlock(buffer, bufferSize); 488 } while (len > 0); 489 490 s.close(); 491 d.close(); 492 493 return true; 494 } 495 496 static bool FileMove(const QFileInfo &src, const QFileInfo &dst) 497 { 498 // attempt to rename the file, 499 // this will fail if files are on different partitions 500 if (rename(src.absFilePath().local8Bit(), 501 dst.absFilePath().local8Bit()) == 0) 502 return true; 503 504 // src and dst are on different mount points, move manually. 505 if (errno == EXDEV) 506 { 507 if (FileCopy(src, dst)) 508 return FileDelete(src); 509 } 510 511 return false; 512 } 513 514 static bool FileDelete(const QFileInfo &file) 515 { 516 if (!file.isDir()) 517 return QFile::remove(file.absFilePath()); 518 519 // delete .thumbcache 520 QDir srcDir(file.absFilePath()); 521 QFileInfo tc(srcDir, ".thumbcache"); 522 GalleryUtil::Delete(tc); 523 524 srcDir.rmdir(srcDir.absPath()); 525 526 return true; 527 } 528 529 // Allow wholesale clearing of marks 530 // Exit "Show Devices" on exit from submenu 531 // Avoid using #define and #ifdef when possible. -
mythvideo/mythvideo/videolist.cpp
286 286 while(itr != medias.end()) 287 287 { 288 288 pDev = *itr; 289 if ( pDev)289 if (mon->ValidateAndLock(pDev)) 290 290 { 291 291 QString path = pDev->getMountPath(); 292 292 QString name = path.right(path.length() 293 293 - path.findRev("/")-1); 294 294 nodespath.append(path); 295 295 nodesname.append(name); 296 297 mon->Unlock(pDev); 296 298 } 297 299 itr++; 298 300 }