Ticket #603: gallery_removable_v4.diff

File gallery_removable_v4.diff, 36.7 KB (added by Aaron McCarthy <mccarthy.aaron@…>, 14 years ago)
  • mythgallery/mythgallery/glsingleview.cpp

     
    405405        {
    406406            ThumbItem *item = m_itemList.at(m_pos);
    407407            if (item) {
    408                 if( item->Remove() ) {
     408                if( GalleryUtil::Delete(item->path) ) {
    409409                    m_zoom = 1.0;
    410410                    m_sx   = 0;
    411411                    m_sy   = 0;
  • mythgallery/mythgallery/galleryutil.h

     
     1// -*- Mode: c++ -*-
    12/* ============================================================
    23 * File  : exifutil.h
    34 * Description :
     
    2324
    2425class GalleryUtil
    2526{
    26 
    2727 public:
    2828    static bool isImage(const char* filePath);
    2929    static bool isMovie(const char* filePath);
     
    3434    static bool loadDirectory(ThumbList& itemList,
    3535                              const QString& dir, bool recurse,
    3636                              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);
    3749};
    3850
    3951#endif /* EXIFUTIL_H */
  • mythgallery/mythgallery/singleview.cpp

     
    450450        {
    451451            ThumbItem *item = m_itemList.at(m_pos);
    452452            if (item) {
    453                 if( item->Remove() ) {
     453                if( GalleryUtil::Delete(item->path) ) {
    454454                    m_zoom = 1.0;
    455455                    m_sx   = 0;
    456456                    m_sy   = 0;
  • mythgallery/mythgallery/iconview.cpp

     
    3131#include <mythtv/xmlparse.h>
    3232#include <mythtv/dialogbox.h>
    3333#include <mythtv/mythdbcon.h>
     34#include <mythtv/mythdialogs.h>
    3435
     36#ifndef _WIN32
     37#include <mythtv/mythmediamonitor.h>
     38#endif
     39
    3540#include "galleryutil.h"
    3641#include "gallerysettings.h"
    3742#include "thumbgenerator.h"
     
    4550#include "glsingleview.h"
    4651#endif
    4752
    48 
    4953int ThumbItem::GetRotationAngle()
    5054{
    5155    MSqlQuery query(MSqlQuery::InitCon());
     
    8488    return false;
    8589}
    8690
    87 IconView::IconView(const QString& galleryDir, MythMainWindow* parent,
    88                    const char* name )
     91IconView::IconView(const QString& galleryDir, MythMediaDevice *initialDevice,
     92                   MythMainWindow* parent, const char* name )
    8993    : MythDialog(parent, name)
    9094{
    9195    m_galleryDir = galleryDir;   
    9296
    9397    m_inMenu     = false;
     98    m_inSubMenu = false;
    9499    m_itemList.setAutoDelete(true);
    95100    m_itemDict.setAutoDelete(false);
    96101
     
    108113    m_lastCol = 0;
    109114    m_topRow  = 0;
    110115    m_isGallery  = false;
     116    m_showDevices = false;
     117    m_currDevice = initialDevice;
    111118
    112119    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
    113132    loadDirectory(galleryDir);
    114133}
    115134
    116135IconView::~IconView()
    117136{
    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);
    125139   
    126140    delete m_thumbGen;
    127141    delete m_theme;
     
    258272                                 item->pixmap->height()/2-bh2+sh,
    259273                                 bw-2*sw, bh-2*sh-(int)(15*hmult));
    260274
     275                if (m_itemMarked.contains(item->path))
     276                    p.drawPixmap(xpos, ypos, m_MrkPix);
     277
    261278            }
    262279            else {
    263280
     
    272289                                 item->pixmap->width()/2-bw2+sw,
    273290                                 item->pixmap->height()/2-bh2+sh,
    274291                                 bw-2*sw, bh-2*sh);
     292
     293                if (m_itemMarked.contains(item->path))
     294                    p.drawPixmap(xpos, ypos, m_MrkPix);
    275295            }
    276296           
    277297            curPos++;
     
    299319        QString action = actions[i];
    300320        if (action == "MENU") {
    301321            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);
    303324            menuHandled = true;
    304325        }
     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        }
    305334        else if (action == "UP") {
    306             if (m_inMenu) {
     335            if (m_inMenu & !m_inSubMenu) {
    307336                m_menuType->MoveUp();
    308337                menuHandled = true;
    309338            }
     339            else if (m_inMenu & m_inSubMenu) {
     340                m_submenuType->MoveUp();
     341                menuHandled = true;
     342            }
    310343            else
    311344                handled = moveUp();
    312345        }
    313346        else if (action == "DOWN") {
    314             if (m_inMenu) {
     347            if (m_inMenu & !m_inSubMenu) {
    315348                m_menuType->MoveDown();
    316349                menuHandled = true;
    317350            }
     351            else if (m_inMenu & m_inSubMenu) {
     352                m_submenuType->MoveDown();
     353                menuHandled = true;
     354            }
    318355            else
    319356                handled = moveDown();
    320357        }
     
    363400            actionDelete();
    364401            handled = true;
    365402        }
     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        }
    366419        else if (action == "SELECT" || action == "PLAY" || action == "SLIDESHOW" || action == "RANDOMSHOW" )
    367420        {
    368421            if (m_inMenu && (action == "SELECT" || action == "PLAY") ) {
     
    378431                }
    379432       
    380433                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
    381450                if (item->isDir && (action == "SELECT" || action == "PLAY") ) {
    382451                    loadDirectory(item->path);
    383452                    handled = true;
     
    414483                                      gContext->GetMainWindow());
    415484                        sv.exec();
    416485                    }                         
     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);
    417491                }
    418492            }
    419493        }
     
    426500        {
    427501            QString action = actions[i];
    428502            if (action == "ESCAPE") {
     503                if (m_showDevices)
     504                {
     505                    loadDirectory(m_galleryDir);
     506                    handled = true;
     507                }
     508                else
     509                {
    429510                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
    430549                if (d != QDir(m_galleryDir)) {
    431550
    432551                    QString oldDirName = d.dirName();
     
    445564                    }
    446565                    handled = true;
    447566                }
     567#ifndef _WIN32
     568                    }
     569                }
     570#endif
    448571            }
    449572        }
    450573    }
     
    547670        exit(-1);
    548671    }
    549672
     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
    550680    // Menu Actions
    551681
    552682    UIListBtnTypeItem* item;
     
    554684    item->setData(new Action(&IconView::actionSlideShow));
    555685    item = new UIListBtnTypeItem(m_menuType, tr("Random"));
    556686    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));
    565693    item = new UIListBtnTypeItem(m_menuType, tr("Settings"));
    566694    item->setData(new Action(&IconView::actionSettings));
    567695   
     
    618746        m_folderSelPix = QPixmap(*img);
    619747        delete img;
    620748
     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
    621758        m_thumbW = m_backRegPix.width();
    622759        m_thumbH = m_backRegPix.height();
    623760        m_nCols  = m_viewRect.width()/m_thumbW - 1;
     
    634771    if (!d.exists())
    635772        return;
    636773
     774    m_showDevices = false;
     775
    637776    m_currDir = d.absPath();
    638777    m_itemList.clear();
    639778    m_itemDict.clear();
     
    778917
    779918void IconView::pressMenu()
    780919{
    781     UIListBtnTypeItem* item = m_menuType->GetItemCurrent();
     920    UIListBtnTypeItem* item;
    782921
     922    if (m_inSubMenu)
     923        item = m_submenuType->GetItemCurrent();
     924    else
     925        item = m_menuType->GetItemCurrent();
     926
    783927    if (!item || !item->getData())
    784928        return;
    785929
    786930    Action *act = (Action*) item->getData();
    787931    (this->*(*act))();
     932
     933    m_menuType->SetActive(m_inMenu & !m_inSubMenu);
     934    m_submenuType->SetActive(m_inMenu & m_inSubMenu);
    788935}
    789936
     937void IconView::actionMainMenu()
     938{
     939    clearMenu(m_submenuType);
     940    m_submenuType->Reset();
     941
     942    m_inSubMenu = false;
     943}
     944
     945void 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
     961void 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
     977void 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
    7901001void IconView::actionRotateCW()
    7911002{
    7921003    ThumbItem* item = m_itemList.at(m_currRow * m_nCols +
     
    8331044    }
    8341045}
    8351046
    836 void IconView::actionDelete()
     1047void IconView::actionDeleteCurrent()
    8371048{
    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)
    8411052        return;
    8421053
    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);
    8451069    }
    8461070}
    8471071
     
    9801204    }
    9811205}
    9821206
     1207void 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
     1257void IconView::actionCopyHere()
     1258{
     1259    CopyMarkedFiles(false);
     1260    actionClearMarked();
     1261}
     1262
     1263void IconView::actionMoveHere()
     1264{
     1265    CopyMarkedFiles(true);
     1266    actionClearMarked();
     1267}
     1268
     1269void IconView::actionDelete()
     1270{
     1271    if (m_itemMarked.isEmpty())
     1272        actionDeleteCurrent();
     1273    else
     1274        actionDeleteMarked();
     1275}
     1276
     1277void 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
     1304void IconView::actionClearMarked()
     1305{
     1306    m_itemMarked.clear();
     1307}
     1308
     1309void 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
     1319void 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
    9831335void IconView::importFromDir(const QString &fromDir, const QString &toDir)
    9841336{
    9851337    QDir d(fromDir);
     
    10191371        }
    10201372    }
    10211373}
     1374
     1375void 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
     1408void 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
     1420void 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

     
    1414#include <mythtv/mythdialogs.h>
    1515#include <mythtv/mythplugin.h>
    1616#include <mythtv/dialogbox.h>
     17#include <mythtv/mythmedia.h>
    1718
    1819extern "C" {
    1920int mythplugin_init(const char *libversion);
     
    3334        diag.AddButton(QObject::tr("Ok"));
    3435        diag.exec();
    3536    }
    36     else {
    37         IconView icv(startdir, gContext->GetMainWindow(), "IconView");
     37    else
     38    {
     39        IconView icv(startdir, NULL, gContext->GetMainWindow(), "IconView");
    3840        icv.exec();
    3941    }
    4042    gContext->removeCurrentLocation();
    4143}
    4244
     45void 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
    4365void setupKeys(void)
    4466{
    4567    REG_JUMP("MythGallery", "Image viewer / slideshow", "", runGallery);
     
    6789    REG_KEY("Gallery", "LOWRIGHT", "Go to the lower-right corner of the image",
    6890            "PgDown");
    6991    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);
    7196}
    7297
    7398int mythplugin_init(const char *libversion)
  • mythgallery/mythgallery/thumbgenerator.cpp

     
    308308
    309309QString ThumbGenerator::getThumbcacheDir(const QString& inDir)
    310310{
     311    QString galleryDir = gContext->GetSetting("GalleryDir");
     312
    311313    // For directory "/my/images/january", this function either returns
    312314    // "/my/images/january/.thumbcache" or "~/.mythtv/mythgallery/january/.thumbcache"
    313315    QString aPath = inDir + QString("/.thumbcache/");
    314316    if ( gContext->GetNumSetting("GalleryThumbnailLocation")
    315             && ! QDir(aPath).exists() )
     317            && ! QDir(aPath).exists() && inDir.startsWith(galleryDir))
    316318    {
    317319        mkpath(aPath);
    318320    }
    319     if ( ! gContext->GetNumSetting("GalleryThumbnailLocation") || ! QDir(aPath).exists() )
     321    if ( ! gContext->GetNumSetting("GalleryThumbnailLocation") || ! QDir(aPath).exists() || ! inDir.startsWith(galleryDir))
    320322    {
    321323        // Arrive here if storing thumbs in home dir,
    322324        // OR failed to create thumb dir in gallery pics location
  • mythgallery/mythgallery/iconview.h

     
    2626#include <qpixmap.h>
    2727
    2828#include <mythtv/mythdialogs.h>
     29#include <mythtv/mythmedia.h>
    2930
    3031class XMLParse;
    3132class UIListBtnType;
     
    4243        caption= "";
    4344        path   = "";
    4445        isDir  = false;
     46        mediaDevice = NULL;
    4547    }
    4648
    4749    ~ThumbItem() {
     
    5860    QString  caption;
    5961    QString  path;
    6062    bool     isDir;
     63    MythMediaDevice *mediaDevice;
    6164};
    6265
    6366typedef QPtrList<ThumbItem> ThumbList;
     
    6972
    7073public:
    7174
    72     IconView(const QString& galleryDir, MythMainWindow* parent,
    73              const char* name = 0);
     75    IconView(const QString& galleryDir, MythMediaDevice *initialDevice,
     76             MythMainWindow* parent, const char* name = 0);
    7477    ~IconView();
    7578
    7679protected:
     
    9396    bool moveLeft();
    9497    bool moveRight();
    9598
     99    void actionMainMenu();
     100    void actionSubMenuMetadata();
     101    void actionSubMenuMark();
     102    void actionSubMenuFile();
     103
    96104    void actionRotateCW();
    97105    void actionRotateCCW();
    98     void actionDelete();
     106    void actionDeleteCurrent();
    99107    void actionSlideShow();
    100108    void actionRandomShow();
    101109    void actionSettings();
    102110    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();
    103121
    104122    void pressMenu();
    105123
    106124    void loadThumbnail(ThumbItem *item);
    107125    void importFromDir(const QString &fromDir, const QString &toDir);
     126    void CopyMarkedFiles(bool move = false);
     127
     128    void clearMenu(UIListBtnType *menu);
    108129   
    109130    QPtrList<ThumbItem> m_itemList;
    110131    QDict<ThumbItem>    m_itemDict;
     132    QStringList         m_itemMarked;
    111133    QString             m_galleryDir;
    112134
    113135    XMLParse           *m_theme;
     
    116138    QRect               m_viewRect;
    117139
    118140    bool                m_inMenu;
     141    bool                m_inSubMenu;
    119142    UIListBtnType      *m_menuType;
     143    UIListBtnType      *m_submenuType;
    120144   
    121145    QPixmap             m_backRegPix;
    122146    QPixmap             m_backSelPix;
    123147    QPixmap             m_folderRegPix;
    124148    QPixmap             m_folderSelPix;
     149    QPixmap             m_MrkPix;
    125150
    126151    QString             m_currDir;
    127152    bool                m_isGallery;
     153    bool                m_showDevices;
     154    MythMediaDevice    *m_currDevice;
    128155
    129156    int                 m_currRow;
    130157    int                 m_currCol;
     
    143170    int                 m_showcaption;
    144171
    145172    typedef void (IconView::*Action)();
     173
     174public slots:
     175    void mediaStatusChanged( MediaStatus oldStatus, MythMediaDevice* pMedia);
    146176};
    147177
    148178
  • mythgallery/mythgallery/gallery-ui.xml

     
    2121    </font>
    2222
    2323    <container name="menu">
    24       <area>20,20,140,240</area>
     24      <area>20,20,140,500</area>
    2525
    2626      <listbtnarea name="menu" draworder="0">
    2727        <area>0,0,140,240</area>
     
    3535        <showscrollarrows>no</showscrollarrows>
    3636      </listbtnarea>
    3737
     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
    3850    </container>
    3951
    4052    <container name="text">
  • mythgallery/mythgallery/galleryutil.cpp

     
    1616 *
    1717 * ============================================================ */
    1818
    19 #include <iostream>
    2019#include <qfileinfo.h>
    2120#include <qdir.h>
    2221
     22#include <mythtv/mythcontext.h>
     23#include <mythtv/mythdbcon.h>
     24#include <mythtv/util.h>
     25
    2326#include "config.h"
    2427#include "constants.h"
    2528#include "galleryutil.h"
     
    3134// include "exif.hpp"
    3235#endif // EXIF_SUPPORT
    3336
     37#define LOC QString("GalleryUtil:")
     38#define LOC_ERR QString("GalleryUtil, Error:")
     39
     40static QFileInfo MakeUnique(const QFileInfo &dest);
     41static QFileInfo MakeUniqueDirectory(const QFileInfo &dest);
     42static bool FileCopy(const QFileInfo &src, const QFileInfo &dst);
     43static bool FileMove(const QFileInfo &src, const QFileInfo &dst);
     44static bool FileDelete(const QFileInfo &file);
     45
    3446bool GalleryUtil::isImage(const char* filePath)
    3547{
    3648    QFileInfo fi(filePath);
     
    8193        }
    8294        else
    8395        {
    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));
    8599        }
    86100       
    87101        delete [] exifvalue;
     
    115129    }
    116130    catch (...)
    117131    {
    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));
    120135    }
    121136
    122137    return rotateAngle;
     
    249264        }
    250265        else
    251266        {
    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));
    253270        }
    254271       
    255272        delete [] exifvalue;
     
    257274    }
    258275    catch (...)
    259276    {
    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));
    262280    }
    263281
    264282    return caption;
    265283}
     284
     285bool 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
     310bool 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
     334bool 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
     352bool 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
     382bool 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
     412bool 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
     429static 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
     448static 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
     465static 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
     474static 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
     483static 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.