Ticket #603: gallery_removable_v4.diff
File gallery_removable_v4.diff, 36.7 KB (added by , 19 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)); 120 121 if (m_currDevice) 122 { 123 if (!m_currDevice->isMounted(true)) 124 m_currDevice->mount(); 125 126 connect(m_currDevice, SIGNAL(statusChanged(MediaStatus, MythMediaDevice*)), 127 SLOT(mediaStatusChanged(MediaStatus, MythMediaDevice*))); 128 129 loadDirectory(m_currDevice->getMountPath()); 130 } 131 else 113 132 loadDirectory(galleryDir); 114 133 } 115 134 116 135 IconView::~IconView() 117 136 { 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 } 137 clearMenu(m_submenuType); 138 clearMenu(m_menuType); 125 139 126 140 delete m_thumbGen; 127 141 delete m_theme; … … 258 272 item->pixmap->height()/2-bh2+sh, 259 273 bw-2*sw, bh-2*sh-(int)(15*hmult)); 260 274 275 if (m_itemMarked.contains(item->path)) 276 p.drawPixmap(xpos, ypos, m_MrkPix); 277 261 278 } 262 279 else { 263 280 … … 272 289 item->pixmap->width()/2-bw2+sw, 273 290 item->pixmap->height()/2-bh2+sh, 274 291 bw-2*sw, bh-2*sh); 292 293 if (m_itemMarked.contains(item->path)) 294 p.drawPixmap(xpos, ypos, m_MrkPix); 275 295 } 276 296 277 297 curPos++; … … 299 319 QString action = actions[i]; 300 320 if (action == "MENU") { 301 321 m_inMenu = !m_inMenu; 302 m_menuType->SetActive(m_inMenu); 322 m_menuType->SetActive(m_inMenu & !m_inSubMenu); 323 m_submenuType->SetActive(m_inMenu & m_inSubMenu); 303 324 menuHandled = true; 304 325 } 326 else if (action == "ESCAPE") { 327 if (m_inMenu & m_inSubMenu) { 328 actionMainMenu(); 329 m_menuType->SetActive(m_inMenu & !m_inSubMenu); 330 m_submenuType->SetActive(m_inMenu & m_inSubMenu); 331 menuHandled = true; 332 } 333 } 305 334 else if (action == "UP") { 306 if (m_inMenu ) {335 if (m_inMenu & !m_inSubMenu) { 307 336 m_menuType->MoveUp(); 308 337 menuHandled = true; 309 338 } 339 else if (m_inMenu & m_inSubMenu) { 340 m_submenuType->MoveUp(); 341 menuHandled = true; 342 } 310 343 else 311 344 handled = moveUp(); 312 345 } 313 346 else if (action == "DOWN") { 314 if (m_inMenu ) {347 if (m_inMenu & !m_inSubMenu) { 315 348 m_menuType->MoveDown(); 316 349 menuHandled = true; 317 350 } 351 else if (m_inMenu & m_inSubMenu) { 352 m_submenuType->MoveDown(); 353 menuHandled = true; 354 } 318 355 else 319 356 handled = moveDown(); 320 357 } … … 363 400 actionDelete(); 364 401 handled = true; 365 402 } 403 else if (action == "MARK") 404 { 405 int pos = m_currRow * m_nCols + m_currCol; 406 ThumbItem *item = m_itemList.at(pos); 407 if (!item) { 408 std::cerr << "The impossible happened" << std::endl; 409 break; 410 } 411 412 if (!m_itemMarked.contains(item->path)) 413 m_itemMarked.append(item->path); 414 else 415 m_itemMarked.remove(item->path); 416 417 handled = true; 418 } 366 419 else if (action == "SELECT" || action == "PLAY" || action == "SLIDESHOW" || action == "RANDOMSHOW" ) 367 420 { 368 421 if (m_inMenu && (action == "SELECT" || action == "PLAY") ) { … … 378 431 } 379 432 380 433 QFileInfo fi(item->path); 434 435 // if the selected item is a mediaDevice 436 // attempt to mount it if it isn't already 437 if (item->mediaDevice && (action == "SELECT" || action == "PLAY") ) 438 { 439 m_currDevice = item->mediaDevice; 440 441 if (!m_currDevice->isMounted()) 442 m_currDevice->mount(); 443 444 item->path = m_currDevice->getMountPath(); 445 446 connect(m_currDevice, SIGNAL(statusChanged(MediaStatus, MythMediaDevice*)), 447 SLOT(mediaStatusChanged(MediaStatus, MythMediaDevice*))); 448 } 449 381 450 if (item->isDir && (action == "SELECT" || action == "PLAY") ) { 382 451 loadDirectory(item->path); 383 452 handled = true; … … 414 483 gContext->GetMainWindow()); 415 484 sv.exec(); 416 485 } 486 487 // if the user deleted files while in single view mode 488 // the contents of the directory will be out of date 489 // reload the current directory to refresh the view 490 loadDirectory(m_currDir); 417 491 } 418 492 } 419 493 } … … 426 500 { 427 501 QString action = actions[i]; 428 502 if (action == "ESCAPE") { 503 if (m_showDevices) 504 { 505 loadDirectory(m_galleryDir); 506 handled = true; 507 } 508 else 509 { 429 510 QDir d(m_currDir); 511 #ifndef _WIN32 512 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 513 if (mon) 514 { 515 QValueList <MythMediaDevice *> removables = 516 mon->GetMedias(MEDIATYPE_DATA); 517 QValueList <MythMediaDevice *>::Iterator it = removables.begin(); 518 for (; it != removables.end(); it++) 519 { 520 if (d == QDir((*it)->getMountPath())) 521 { 522 actionShowDevices(); 523 524 // make sure previous devies is visible and selected 525 ThumbItem *item; 526 if ((*it)->getVolumeID() != "") 527 item = m_itemDict.find((*it)->getVolumeID()); 528 else 529 item = m_itemDict.find((*it)->getDevicePath()); 530 531 if (item) 532 { 533 int pos = m_itemList.find(item); 534 if (pos != -1) 535 { 536 m_currRow = pos/m_nCols; 537 m_currCol = pos-m_currRow*m_nCols; 538 m_topRow = QMAX(0, m_currRow-(m_nRows-1)); 539 } 540 } 541 handled = true; 542 break; 543 } 544 } 545 } 546 if (!handled) 547 { 548 #endif 430 549 if (d != QDir(m_galleryDir)) { 431 550 432 551 QString oldDirName = d.dirName(); … … 445 564 } 446 565 handled = true; 447 566 } 567 #ifndef _WIN32 568 } 569 } 570 #endif 448 571 } 449 572 } 450 573 } … … 547 670 exit(-1); 548 671 } 549 672 673 m_submenuType = (UIListBtnType*)container->GetType("submenu"); 674 if (!m_menuType) { 675 std::cerr << "MythGallery: Failed to get submenu area." 676 << std::endl; 677 exit(-1); 678 } 679 550 680 // Menu Actions 551 681 552 682 UIListBtnTypeItem* item; … … 554 684 item->setData(new Action(&IconView::actionSlideShow)); 555 685 item = new UIListBtnTypeItem(m_menuType, tr("Random")); 556 686 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)); 687 item = new UIListBtnTypeItem(m_menuType, tr("Meta Data...")); 688 item->setData(new Action(&IconView::actionSubMenuMetadata)); 689 item = new UIListBtnTypeItem(m_menuType, tr("Marking...")); 690 item->setData(new Action(&IconView::actionSubMenuMark)); 691 item = new UIListBtnTypeItem(m_menuType, tr("File...")); 692 item->setData(new Action(&IconView::actionSubMenuFile)); 565 693 item = new UIListBtnTypeItem(m_menuType, tr("Settings")); 566 694 item->setData(new Action(&IconView::actionSettings)); 567 695 … … 618 746 m_folderSelPix = QPixmap(*img); 619 747 delete img; 620 748 749 img = gContext->LoadScaleImage("gallery-mark.png"); 750 if (!img) { 751 std::cerr << "Failed to load gallery-mark.png" 752 << std::endl; 753 exit(-1); 754 } 755 m_MrkPix = QPixmap(*img); 756 delete img; 757 621 758 m_thumbW = m_backRegPix.width(); 622 759 m_thumbH = m_backRegPix.height(); 623 760 m_nCols = m_viewRect.width()/m_thumbW - 1; … … 634 771 if (!d.exists()) 635 772 return; 636 773 774 m_showDevices = false; 775 637 776 m_currDir = d.absPath(); 638 777 m_itemList.clear(); 639 778 m_itemDict.clear(); … … 778 917 779 918 void IconView::pressMenu() 780 919 { 781 UIListBtnTypeItem* item = m_menuType->GetItemCurrent();920 UIListBtnTypeItem* item; 782 921 922 if (m_inSubMenu) 923 item = m_submenuType->GetItemCurrent(); 924 else 925 item = m_menuType->GetItemCurrent(); 926 783 927 if (!item || !item->getData()) 784 928 return; 785 929 786 930 Action *act = (Action*) item->getData(); 787 931 (this->*(*act))(); 932 933 m_menuType->SetActive(m_inMenu & !m_inSubMenu); 934 m_submenuType->SetActive(m_inMenu & m_inSubMenu); 788 935 } 789 936 937 void IconView::actionMainMenu() 938 { 939 clearMenu(m_submenuType); 940 m_submenuType->Reset(); 941 942 m_inSubMenu = false; 943 } 944 945 void IconView::actionSubMenuMetadata() 946 { 947 clearMenu(m_submenuType); 948 m_submenuType->Reset(); 949 950 UIListBtnTypeItem *item; 951 item = new UIListBtnTypeItem(m_submenuType, tr("Return")); 952 item->setData(new Action(&IconView::actionMainMenu)); 953 item = new UIListBtnTypeItem(m_submenuType, tr("Rotate CW")); 954 item->setData(new Action(&IconView::actionRotateCW)); 955 item = new UIListBtnTypeItem(m_submenuType, tr("Rotate CCW")); 956 item->setData(new Action(&IconView::actionRotateCCW)); 957 958 m_inSubMenu = true; 959 } 960 961 void IconView::actionSubMenuMark() 962 { 963 clearMenu(m_submenuType); 964 m_submenuType->Reset(); 965 966 UIListBtnTypeItem *item; 967 item = new UIListBtnTypeItem(m_submenuType, tr("Return")); 968 item->setData(new Action(&IconView::actionMainMenu)); 969 item = new UIListBtnTypeItem(m_submenuType, tr("Clear Marked")); 970 item->setData(new Action(&IconView::actionClearMarked)); 971 item = new UIListBtnTypeItem(m_submenuType, tr("Select All")); 972 item->setData(new Action(&IconView::actionSelectAll)); 973 974 m_inSubMenu = true; 975 } 976 977 void IconView::actionSubMenuFile() 978 { 979 clearMenu(m_submenuType); 980 m_submenuType->Reset(); 981 982 UIListBtnTypeItem *item; 983 item = new UIListBtnTypeItem(m_submenuType, tr("Return")); 984 item->setData(new Action(&IconView::actionMainMenu)); 985 item = new UIListBtnTypeItem(m_submenuType, tr("Show Devices")); 986 item->setData(new Action(&IconView::actionShowDevices)); 987 item = new UIListBtnTypeItem(m_submenuType, tr("Import")); 988 item->setData(new Action(&IconView::actionImport)); 989 item = new UIListBtnTypeItem(m_submenuType, tr("Copy here")); 990 item->setData(new Action(&IconView::actionCopyHere)); 991 item = new UIListBtnTypeItem(m_submenuType, tr("Move here")); 992 item->setData(new Action(&IconView::actionMoveHere)); 993 item = new UIListBtnTypeItem(m_submenuType, tr("Delete")); 994 item->setData(new Action(&IconView::actionDelete)); 995 item = new UIListBtnTypeItem(m_submenuType, tr("Create Dir")); 996 item->setData(new Action(&IconView::actionMkDir)); 997 998 m_inSubMenu = true; 999 } 1000 790 1001 void IconView::actionRotateCW() 791 1002 { 792 1003 ThumbItem* item = m_itemList.at(m_currRow * m_nCols + … … 833 1044 } 834 1045 } 835 1046 836 void IconView::actionDelete ()1047 void IconView::actionDeleteCurrent() 837 1048 { 838 ThumbItem* item = m_itemList.at(m_currRow * m_nCols + 839 m_currCol); 840 if (!item || item->isDir)1049 ThumbItem* item = m_itemList.at(m_currRow * m_nCols + m_currCol); 1050 1051 if (!item) 841 1052 return; 842 1053 843 if( item->Remove() ) { 844 loadDirectory(m_currDir, false); 1054 bool cont = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), 1055 tr("Delete Current File or Folder"), 1056 (item->isDir) ? 1057 QString(tr("Deleting 1 folder, including any " 1058 "subfolders and files.")) : 1059 QString(tr("Deleting 1 image.")), 1060 false); 1061 1062 if (cont) 1063 { 1064 QFileInfo fi; 1065 fi.setFile(item->path); 1066 GalleryUtil::Delete(fi); 1067 1068 loadDirectory(m_currDir); 845 1069 } 846 1070 } 847 1071 … … 980 1204 } 981 1205 } 982 1206 1207 void IconView::actionShowDevices() 1208 { 1209 if (m_currDevice) 1210 { 1211 m_currDevice->disconnect(this); 1212 m_currDevice = NULL; 1213 } 1214 1215 m_showDevices = true; 1216 1217 m_itemList.clear(); 1218 m_itemDict.clear(); 1219 1220 m_thumbGen->cancel(); 1221 1222 /* add gallery directory */ 1223 ThumbItem *item = new ThumbItem; 1224 item->name = QString("Gallery"); 1225 item->path = m_galleryDir; 1226 item->isDir = true; 1227 m_itemList.append(item); 1228 m_itemDict.insert(item->name, item); 1229 1230 #ifndef _WIN32 1231 MediaMonitor *mon = MediaMonitor::GetMediaMonitor(); 1232 if (mon) 1233 { 1234 QValueList <MythMediaDevice *> removables = 1235 mon->GetMedias(MEDIATYPE_DATA); 1236 QValueList <MythMediaDevice *>::Iterator it = removables.begin(); 1237 for (; it != removables.end(); it++) 1238 { 1239 item = new ThumbItem; 1240 if ((*it)->getVolumeID() != "") 1241 item->name = (*it)->getVolumeID(); 1242 else 1243 item->name = (*it)->getDevicePath(); 1244 item->path = (*it)->getMountPath(); 1245 item->isDir = true; 1246 item->mediaDevice = *it; 1247 m_itemList.append(item); 1248 m_itemDict.insert(item->name, item); 1249 } 1250 } 1251 #endif 1252 1253 m_lastRow = QMAX((int)ceilf((float)m_itemList.count()/(float)m_nCols)-1,0); 1254 m_lastCol = QMAX(m_itemList.count()-m_lastRow*m_nCols-1,0); 1255 } 1256 1257 void IconView::actionCopyHere() 1258 { 1259 CopyMarkedFiles(false); 1260 actionClearMarked(); 1261 } 1262 1263 void IconView::actionMoveHere() 1264 { 1265 CopyMarkedFiles(true); 1266 actionClearMarked(); 1267 } 1268 1269 void IconView::actionDelete() 1270 { 1271 if (m_itemMarked.isEmpty()) 1272 actionDeleteCurrent(); 1273 else 1274 actionDeleteMarked(); 1275 } 1276 1277 void IconView::actionDeleteMarked() 1278 { 1279 bool cont = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), 1280 tr("Delete Marked Files"), 1281 QString(tr("Deleting %1 images and folders, including " 1282 "any subfolders and files.")) 1283 .arg(m_itemMarked.count()), 1284 false); 1285 1286 if (cont) 1287 { 1288 QStringList::iterator it; 1289 QFileInfo fi; 1290 1291 for (it = m_itemMarked.begin(); it != m_itemMarked.end(); it++) 1292 { 1293 fi.setFile(*it); 1294 1295 GalleryUtil::Delete(fi); 1296 } 1297 1298 m_itemMarked.clear(); 1299 1300 loadDirectory(m_currDir); 1301 } 1302 } 1303 1304 void IconView::actionClearMarked() 1305 { 1306 m_itemMarked.clear(); 1307 } 1308 1309 void IconView::actionSelectAll() 1310 { 1311 ThumbItem *item; 1312 for (item = m_itemList.first(); item; item = m_itemList.next()) 1313 { 1314 if (!m_itemMarked.contains(item->path)) 1315 m_itemMarked.append(item->path); 1316 } 1317 } 1318 1319 void IconView::actionMkDir() 1320 { 1321 QString folderName = tr("New Folder"); 1322 1323 bool res = MythPopupBox::showGetTextPopup(gContext->GetMainWindow(), tr("Create New Folder"), 1324 tr("Create New Folder"), folderName); 1325 1326 if (res) 1327 { 1328 QDir cdir(m_currDir); 1329 cdir.mkdir(folderName); 1330 1331 loadDirectory(m_currDir); 1332 } 1333 } 1334 983 1335 void IconView::importFromDir(const QString &fromDir, const QString &toDir) 984 1336 { 985 1337 QDir d(fromDir); … … 1019 1371 } 1020 1372 } 1021 1373 } 1374 1375 void IconView::CopyMarkedFiles(bool move) 1376 { 1377 if (m_itemMarked.isEmpty()) 1378 return; 1379 1380 QStringList::iterator it; 1381 QFileInfo fi; 1382 QFileInfo dest; 1383 int count = 0; 1384 1385 1386 MythProgressDialog *progress = 1387 new MythProgressDialog((move) ? tr("Moving marked images...") : 1388 tr("Copying marked images..."), 1389 m_itemMarked.count()); 1390 1391 for (it = m_itemMarked.begin(); it != m_itemMarked.end(); it++) 1392 { 1393 fi.setFile(*it); 1394 dest.setFile(QDir(m_currDir), fi.fileName()); 1395 1396 if (fi.exists()) 1397 GalleryUtil::CopyMove(fi, dest, move); 1398 1399 progress->setProgress(++count); 1400 } 1401 1402 progress->Close(); 1403 delete progress; 1404 1405 loadDirectory(m_currDir); 1406 } 1407 1408 void IconView::clearMenu(UIListBtnType *menu) 1409 { 1410 UIListBtnTypeItem* item = menu->GetItemFirst(); 1411 while (item) 1412 { 1413 Action *act = (Action*) item->getData(); 1414 if (act) 1415 delete act; 1416 item = menu->GetItemNext(item); 1417 } 1418 } 1419 1420 void IconView::mediaStatusChanged(MediaStatus oldStatus, 1421 MythMediaDevice *pMedia) 1422 { 1423 (void) oldStatus; 1424 if (m_currDevice == pMedia) 1425 { 1426 actionShowDevices(); 1427 1428 m_currRow = 0; 1429 m_currCol = 0; 1430 1431 updateView(); 1432 updateText(); 1433 } 1434 } -
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 QString cmd = "cp "; 468 cmd += "\"" + src.absFilePath().local8Bit() + "\" \""; 469 cmd += dst.absFilePath().local8Bit() + "\""; 470 myth_system(cmd); 471 return true; 472 } 473 474 static bool FileMove(const QFileInfo &src, const QFileInfo &dst) 475 { 476 QString cmd = "mv "; 477 cmd += "\"" + src.absFilePath().local8Bit() + "\" \""; 478 cmd += dst.absFilePath().local8Bit() + "\""; 479 myth_system(cmd); 480 return true; 481 } 482 483 static bool FileDelete(const QFileInfo &file) 484 { 485 if (!file.isDir()) 486 return QFile::remove(file.absFilePath()); 487 488 // delete .thumbcache 489 QDir srcDir(file.absFilePath()); 490 QFileInfo tc(srcDir, ".thumbcache"); 491 GalleryUtil::Delete(tc); 492 493 srcDir.rmdir(srcDir.absPath()); 494 495 return true; 496 } 497 498 // Allow wholesale clearing of marks 499 // Use Qt or C API for renaming/unlinking/copying files or directories. 500 // Exit "Show Devices" on exit from submenu 501 // GetMedias() is unsafe if a device is removed/unmounted while you are 502 // looking at its returned list... 503 // Avoid using #define and #ifdef when possible.