Ticket #603: gallery_removable_v3.patch

File gallery_removable_v3.patch, 37.0 KB (added by danielk, 14 years ago)

updated version

  • mythplugins/mythgallery/mythgallery/galleryutil.h

     
     1// -*- Mode: c++ -*-
    12/* ============================================================
    23 * File  : exifutil.h
    34 * Description :
     
    2324
    2425class GalleryUtil
    2526{
    26 
    27  public:
     27  public:
    2828    static bool isImage(const char* filePath);
    2929    static bool isMovie(const char* filePath);
    3030    static long getNaturalRotation(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 */
  • mythplugins/mythgallery/mythgallery/iconview.cpp

     
    3131#include <mythtv/xmlparse.h>
    3232#include <mythtv/dialogbox.h>
    3333#include <mythtv/mythdbcon.h>
     34#include <mythtv/mythmediamonitor.h>
     35#include <mythtv/mythdialogs.h>
    3436
    3537#include "galleryutil.h"
    3638#include "gallerysettings.h"
     
    8486    return false;
    8587}
    8688
    87 IconView::IconView(const QString& galleryDir, MythMainWindow* parent,
    88                    const char* name )
     89IconView::IconView(const QString& galleryDir, MythMediaDevice *initialDevice,
     90                   MythMainWindow* parent, const char* name )
    8991    : MythDialog(parent, name)
    9092{
    9193    m_galleryDir = galleryDir;   
    9294
    9395    m_inMenu     = false;
     96    m_inSubMenu = false;
    9497    m_itemList.setAutoDelete(true);
    9598    m_itemDict.setAutoDelete(false);
    9699
     
    108111    m_lastCol = 0;
    109112    m_topRow  = 0;
    110113    m_isGallery  = false;
     114#ifndef _WIN32
     115    m_showDevices = false;
     116    m_currDevice = initialDevice;
     117#endif
    111118
    112119    srand(time(NULL));
    113     loadDirectory(galleryDir);
     120
     121#ifndef _WIN32
     122    if (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    else
     133#endif
     134        loadDirectory(galleryDir);
    114135}
    115136
    116137IconView::~IconView()
    117138{
    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     }
    125    
     139    clearMenu(m_submenuType);
     140    clearMenu(m_menuType);
     141
    126142    delete m_thumbGen;
    127143    delete m_theme;
    128144}
     
    258274                                 item->pixmap->height()/2-bh2+sh,
    259275                                 bw-2*sw, bh-2*sh-(int)(15*hmult));
    260276
     277                if (m_itemMarked.contains(item->path))
     278                    p.drawPixmap(xpos, ypos, m_MrkPix);
     279
    261280            }
    262281            else {
    263282
     
    272291                                 item->pixmap->width()/2-bw2+sw,
    273292                                 item->pixmap->height()/2-bh2+sh,
    274293                                 bw-2*sw, bh-2*sh);
     294
     295                if (m_itemMarked.contains(item->path))
     296                    p.drawPixmap(xpos, ypos, m_MrkPix);
    275297            }
    276298           
    277299            curPos++;
     
    299321        QString action = actions[i];
    300322        if (action == "MENU") {
    301323            m_inMenu = !m_inMenu;
    302             m_menuType->SetActive(m_inMenu);
     324            m_menuType->SetActive(m_inMenu & !m_inSubMenu);
     325            m_submenuType->SetActive(m_inMenu & m_inSubMenu);
    303326            menuHandled = true;
    304327        }
    305328        else if (action == "UP") {
    306             if (m_inMenu) {
     329            if (m_inMenu & !m_inSubMenu) {
    307330                m_menuType->MoveUp();
    308331                menuHandled = true;
    309332            }
     333            else if (m_inMenu & m_inSubMenu) {
     334                m_submenuType->MoveUp();
     335                menuHandled = true;
     336            }
    310337            else
    311338                handled = moveUp();
    312339        }
    313340        else if (action == "DOWN") {
    314             if (m_inMenu) {
     341            if (m_inMenu & !m_inSubMenu) {
    315342                m_menuType->MoveDown();
    316343                menuHandled = true;
    317344            }
     345            else if (m_inMenu & m_inSubMenu) {
     346                m_submenuType->MoveDown();
     347                menuHandled = true;
     348            }
    318349            else
    319350                handled = moveDown();
    320351        }
     
    363394            actionDelete();
    364395            handled = true;
    365396        }
     397        else if (action == "MARK")
     398        {
     399            int pos = m_currRow * m_nCols + m_currCol;
     400            ThumbItem *item = m_itemList.at(pos);
     401            if (!item) {
     402                std::cerr << "The impossible happened" << std::endl;
     403                break;
     404            }
     405
     406            std::cout << "(un)marking " << item->path.ascii() << std::endl;
     407
     408            if (!m_itemMarked.contains(item->path))
     409                m_itemMarked.append(item->path);
     410            else
     411                m_itemMarked.remove(item->path);
     412
     413            handled = true;
     414        }
    366415        else if (action == "SELECT" || action == "PLAY" || action == "SLIDESHOW" || action == "RANDOMSHOW" )
    367416        {
    368417            if (m_inMenu && (action == "SELECT" || action == "PLAY") ) {
     
    378427                }
    379428       
    380429                QFileInfo fi(item->path);
     430#ifndef _WIN32
     431                // if the selected item is a mediaDevice attempt to mount it if it isn't already
     432                if (item->mediaDevice && (action == "SELECT" || action == "PLAY") )
     433                {
     434                    m_currDevice = item->mediaDevice;
     435
     436                    if (!m_currDevice->isMounted())
     437                        m_currDevice->mount();
     438
     439                    item->path = m_currDevice->getMountPath();
     440
     441                    connect(m_currDevice, SIGNAL(statusChanged(MediaStatus, MythMediaDevice*)),
     442                            SLOT(mediaStatusChanged(MediaStatus, MythMediaDevice*)));
     443                }
     444#endif
    381445                if (item->isDir && (action == "SELECT" || action == "PLAY") ) {
    382446                    loadDirectory(item->path);
    383447                    handled = true;
     
    426490        {
    427491            QString action = actions[i];
    428492            if (action == "ESCAPE") {
    429                 QDir d(m_currDir);
    430                 if (d != QDir(m_galleryDir)) {
     493#ifndef _WIN32
     494                if (m_showDevices)
     495                {
     496                    loadDirectory(m_galleryDir);
     497                    handled = true;
     498                }
     499                else
     500                {
     501#endif
     502                    QDir d(m_currDir);
     503#ifndef _WIN32
     504                    MediaMonitor *mon = MediaMonitor::GetMediaMonitor();
     505                    if (mon)
     506                    {
     507                        QValueList <MythMediaDevice *> removables =
     508                            mon->GetMedias(MEDIATYPE_DATA);
     509                        QValueList <MythMediaDevice *>::Iterator it = removables.begin();
     510                        for (; it != removables.end(); it++)
     511                        {
     512                            if (d == QDir((*it)->getMountPath()))
     513                            {
     514                                actionShowDevices();
    431515
    432                     QString oldDirName = d.dirName();
    433                     d.cdUp();
    434                     loadDirectory(d.absPath());
     516                                // make sure previous devies is visible and selected
     517                                ThumbItem *item;
     518                                if ((*it)->getVolumeID() != "")
     519                                    item = m_itemDict.find((*it)->getVolumeID());
     520                                else
     521                                    item = m_itemDict.find((*it)->getDevicePath());
    435522
    436                     // make sure up-directory is visible and selected
    437                     ThumbItem* item = m_itemDict.find(oldDirName);
    438                     if (item) {
    439                         int pos = m_itemList.find(item);
    440                         if (pos != -1) {
    441                             m_currRow = pos/m_nCols;
    442                             m_currCol = pos-m_currRow*m_nCols;
    443                             m_topRow  = QMAX(0, m_currRow-(m_nRows-1));
     523                                if (item)
     524                                {
     525                                    int pos = m_itemList.find(item);
     526                                    if (pos != -1)
     527                                    {
     528                                        m_currRow = pos/m_nCols;
     529                                        m_currCol = pos-m_currRow*m_nCols;
     530                                        m_topRow = QMAX(0, m_currRow-(m_nRows-1));
     531                                    }
     532                                }
     533                                handled = true;
     534                                break;
     535                            }
    444536                        }
    445537                    }
    446                     handled = true;
     538                    if (!handled)
     539                    {
     540#endif
     541                        if (d != QDir(m_galleryDir)) {
     542
     543                            QString oldDirName = d.dirName();
     544                            d.cdUp();
     545                            loadDirectory(d.absPath());
     546
     547                            // make sure up-directory is visible and selected
     548                            ThumbItem* item = m_itemDict.find(oldDirName);
     549                            if (item) {
     550                                int pos = m_itemList.find(item);
     551                                if (pos != -1) {
     552                                    m_currRow = pos/m_nCols;
     553                                    m_currCol = pos-m_currRow*m_nCols;
     554                                    m_topRow  = QMAX(0, m_currRow-(m_nRows-1));
     555                                }
     556                            }
     557                            handled = true;
     558                        }
     559#ifndef _WIN32
     560                    }
    447561                }
     562#endif
    448563            }
    449564        }
    450565    }
     
    547662        exit(-1);
    548663    }
    549664
     665    m_submenuType = (UIListBtnType*)container->GetType("submenu");
     666    if (!m_menuType) {
     667        std::cerr << "MythGallery: Failed to get submenu area."
     668                  << std::endl;
     669        exit(-1);
     670    }
     671
    550672    // Menu Actions
    551673
    552674    UIListBtnTypeItem* item;
     
    554676    item->setData(new Action(&IconView::actionSlideShow));
    555677    item = new UIListBtnTypeItem(m_menuType, tr("Random"));
    556678    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));
     679    item = new UIListBtnTypeItem(m_menuType, tr("Meta Data..."));
     680    item->setData(new Action(&IconView::actionSubMenuMetadata));
     681    item = new UIListBtnTypeItem(m_menuType, tr("Marking..."));
     682    item->setData(new Action(&IconView::actionSubMenuMark));
     683    item = new UIListBtnTypeItem(m_menuType, tr("File..."));
     684    item->setData(new Action(&IconView::actionSubMenuFile));
    561685    item = new UIListBtnTypeItem(m_menuType, tr("Delete"));
    562686    item->setData(new Action(&IconView::actionDelete));
    563     item = new UIListBtnTypeItem(m_menuType, tr("Import"));
    564     item->setData(new Action(&IconView::actionImport));
    565687    item = new UIListBtnTypeItem(m_menuType, tr("Settings"));
    566688    item->setData(new Action(&IconView::actionSettings));
    567689   
     
    618740        m_folderSelPix = QPixmap(*img);
    619741        delete img;
    620742
     743        img = gContext->LoadScaleImage("gallery-mark.png");
     744        if (!img) {
     745            std::cerr << "Failed to load gallery-mark.png"
     746                      << std::endl;
     747            exit(-1);
     748        }
     749        m_MrkPix = QPixmap(*img);
     750        delete img;
     751
    621752        m_thumbW = m_backRegPix.width();
    622753        m_thumbH = m_backRegPix.height();
    623754        m_nCols  = m_viewRect.width()/m_thumbW - 1;
     
    634765    if (!d.exists())
    635766        return;
    636767
     768#ifndef _WIN32
     769    m_showDevices = false;
     770#endif
     771
    637772    m_currDir = d.absPath();
    638773    m_itemList.clear();
    639774    m_itemDict.clear();
     
    778913
    779914void IconView::pressMenu()
    780915{
    781     UIListBtnTypeItem* item = m_menuType->GetItemCurrent();
     916    UIListBtnTypeItem* item;
    782917
     918    if (m_inSubMenu)
     919        item = m_submenuType->GetItemCurrent();
     920    else
     921        item = m_menuType->GetItemCurrent();
     922
    783923    if (!item || !item->getData())
    784924        return;
    785925
    786926    Action *act = (Action*) item->getData();
    787927    (this->*(*act))();
     928
     929    m_menuType->SetActive(m_inMenu & !m_inSubMenu);
     930    m_submenuType->SetActive(m_inMenu & m_inSubMenu);
    788931}
    789932
     933void IconView::actionMainMenu()
     934{
     935    clearMenu(m_submenuType);
     936    m_submenuType->Reset();
     937
     938    m_inSubMenu = false;
     939}
     940
     941void IconView::actionSubMenuMetadata()
     942{
     943    clearMenu(m_submenuType);
     944    m_submenuType->Reset();
     945
     946    UIListBtnTypeItem *item;
     947    item = new UIListBtnTypeItem(m_submenuType, tr("Return"));
     948    item->setData(new Action(&IconView::actionMainMenu));
     949    item = new UIListBtnTypeItem(m_submenuType, tr("Rotate CW"));
     950    item->setData(new Action(&IconView::actionRotateCW));
     951    item = new UIListBtnTypeItem(m_submenuType, tr("Rotate CCW"));
     952    item->setData(new Action(&IconView::actionRotateCCW));
     953
     954    m_inSubMenu = true;
     955}
     956
     957void IconView::actionSubMenuMark()
     958{
     959    clearMenu(m_submenuType);
     960    m_submenuType->Reset();
     961
     962    UIListBtnTypeItem *item;
     963    item = new UIListBtnTypeItem(m_submenuType, tr("Return"));
     964    item->setData(new Action(&IconView::actionMainMenu));
     965    item = new UIListBtnTypeItem(m_submenuType, tr("Clear Marked"));
     966    item->setData(new Action(&IconView::actionClearMarked));
     967    item = new UIListBtnTypeItem(m_submenuType, tr("Select All"));
     968    item->setData(new Action(&IconView::actionSelectAll));
     969
     970    m_inSubMenu = true;
     971}
     972
     973void IconView::actionSubMenuFile()
     974{
     975    clearMenu(m_submenuType);
     976    m_submenuType->Reset();
     977
     978    UIListBtnTypeItem *item;
     979    item = new UIListBtnTypeItem(m_submenuType, tr("Return"));
     980    item->setData(new Action(&IconView::actionMainMenu));
     981#ifndef _WIN32
     982    item = new UIListBtnTypeItem(m_submenuType, tr("Show Devices"));
     983    item->setData(new Action(&IconView::actionShowDevices));
     984#endif
     985    item = new UIListBtnTypeItem(m_submenuType, tr("Import"));
     986    item->setData(new Action(&IconView::actionImport));
     987    item = new UIListBtnTypeItem(m_submenuType, tr("Copy here"));
     988    item->setData(new Action(&IconView::actionCopyHere));
     989    item = new UIListBtnTypeItem(m_submenuType, tr("Move here"));
     990    item->setData(new Action(&IconView::actionMoveHere));
     991    item = new UIListBtnTypeItem(m_submenuType, tr("Delete Marked"));
     992    item->setData(new Action(&IconView::actionDeleteMarked));
     993    item = new UIListBtnTypeItem(m_submenuType, tr("Create Dir"));
     994    item->setData(new Action(&IconView::actionMkDir));
     995
     996    m_inSubMenu = true;
     997}
     998
    790999void IconView::actionRotateCW()
    7911000{
    7921001    ThumbItem* item = m_itemList.at(m_currRow * m_nCols +
     
    9801189    }
    9811190}
    9821191
     1192#ifndef _WIN32
     1193void IconView::actionShowDevices()
     1194{
     1195    if (m_currDevice)
     1196    {
     1197        m_currDevice->disconnect(this);
     1198        m_currDevice = NULL;
     1199    }
     1200
     1201    m_showDevices = true;
     1202
     1203    m_itemList.clear();
     1204    m_itemDict.clear();
     1205
     1206    m_thumbGen->cancel();
     1207
     1208    /* add gallery directory */
     1209    ThumbItem *item = new ThumbItem;
     1210    item->name = QString("Gallery");
     1211    item->path = m_galleryDir;
     1212    item->isDir = true;
     1213    m_itemList.append(item);
     1214    m_itemDict.insert(item->name, item);
     1215
     1216    MediaMonitor *mon = MediaMonitor::GetMediaMonitor();
     1217    if (mon)
     1218    {
     1219        QValueList <MythMediaDevice *> removables =
     1220            mon->GetMedias(MEDIATYPE_DATA);
     1221        QValueList <MythMediaDevice *>::Iterator it = removables.begin();
     1222        for (; it != removables.end(); it++)
     1223        {
     1224            item = new ThumbItem;
     1225            if ((*it)->getVolumeID() != "")
     1226                item->name = (*it)->getVolumeID();
     1227            else
     1228                item->name = (*it)->getDevicePath();
     1229            item->path = (*it)->getMountPath();
     1230            item->isDir = true;
     1231            item->mediaDevice = *it;
     1232            m_itemList.append(item);
     1233            m_itemDict.insert(item->name, item);
     1234        }
     1235    }
     1236
     1237    m_lastRow = QMAX((int)ceilf((float)m_itemList.count()/(float)m_nCols)-1,0);
     1238    m_lastCol = QMAX(m_itemList.count()-m_lastRow*m_nCols-1,0);
     1239}
     1240#endif
     1241
     1242void IconView::actionCopyHere()
     1243{
     1244    CopyMarkedFiles(false);
     1245}
     1246
     1247void IconView::actionMoveHere()
     1248{
     1249    CopyMarkedFiles(true);
     1250}
     1251
     1252void IconView::actionDeleteMarked()
     1253{
     1254    std::cerr << "deleting marked files\n";
     1255
     1256    bool cont = MythPopupBox::showOkCancelPopup(gContext->GetMainWindow(), tr("Delete Marked Files"),
     1257                                                QString(tr("Deleting %1 images and folders"))
     1258                                                .arg(m_itemMarked.count()), false);
     1259
     1260    if (cont)
     1261    {
     1262        QStringList::iterator it;
     1263        QFileInfo fi;
     1264
     1265        for (it = m_itemMarked.begin(); it != m_itemMarked.end(); it++)
     1266        {
     1267            fi.setFile(*it);
     1268
     1269            std::cerr << "fi = " << fi.absFilePath() << endl;
     1270
     1271            GalleryUtil::Delete(fi);
     1272        }
     1273
     1274        m_itemMarked.clear();
     1275
     1276        loadDirectory(m_currDir);
     1277    }
     1278}
     1279
     1280void IconView::actionClearMarked()
     1281{
     1282    m_itemMarked.clear();
     1283}
     1284
     1285void IconView::actionSelectAll()
     1286{
     1287    ThumbItem *item;
     1288    for (item = m_itemList.first(); item; item = m_itemList.next())
     1289    {
     1290        if (!m_itemMarked.contains(item->path))
     1291            m_itemMarked.append(item->path);
     1292    }
     1293}
     1294
     1295void IconView::actionMkDir()
     1296{
     1297    QString folderName = tr("New Folder");
     1298
     1299    bool res = MythPopupBox::showGetTextPopup(gContext->GetMainWindow(), tr("Create New Folder"),
     1300                                              tr("Create New Folder"), folderName);
     1301
     1302    if (res)
     1303    {
     1304        QDir cdir(m_currDir);
     1305        cdir.mkdir(folderName);
     1306
     1307        loadDirectory(m_currDir);
     1308    }
     1309}
     1310
    9831311void IconView::importFromDir(const QString &fromDir, const QString &toDir)
    9841312{
    9851313    QDir d(fromDir);
     
    10191347        }
    10201348    }
    10211349}
     1350
     1351void IconView::CopyMarkedFiles(bool move)
     1352{
     1353    QStringList::iterator it;
     1354    QFileInfo fi;
     1355    QFileInfo dest;
     1356
     1357    for (it = m_itemMarked.begin(); it != m_itemMarked.end(); it++)
     1358    {
     1359        fi.setFile(*it);
     1360        dest.setFile(QDir(m_currDir), fi.fileName());
     1361
     1362        if (fi.exists())
     1363        {
     1364            GalleryUtil::CopyMove(fi, dest, move);
     1365            *it = dest.absFilePath();
     1366        }
     1367    }
     1368
     1369    loadDirectory(m_currDir);
     1370}
     1371
     1372void IconView::clearMenu(UIListBtnType *menu)
     1373{
     1374    UIListBtnTypeItem* item = menu->GetItemFirst();
     1375    while (item)
     1376    {
     1377        Action *act = (Action*) item->getData();
     1378        if (act)
     1379            delete act;
     1380        item = menu->GetItemNext(item);
     1381    }
     1382}
     1383
     1384void IconView::mediaStatusChanged(MediaStatus oldStatus,
     1385                                  MythMediaDevice *pMedia)
     1386{
     1387    (void) oldStatus;
     1388    if (m_currDevice == pMedia)
     1389    {
     1390        actionShowDevices();
     1391
     1392        m_currRow = 0;
     1393        m_currCol = 0;
     1394
     1395        updateView();
     1396        updateText();
     1397    }
     1398}
  • mythplugins/mythgallery/mythgallery/main.cpp

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: mythplugins/mythgallery/mythgallery/images/gallery-mark.png
    ___________________________________________________________________
    Name: svn:mime-type
       + application/octet-stream
    
     
    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}
     44 
     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}
    4263
     64
    4365void setupKeys(void)
    4466{
    4567    REG_JUMP("MythGallery", "Image viewer / slideshow", "", runGallery);
     
    6890            "PgDown");
    6991    REG_KEY("Gallery", "INFO", "Toggle Showing Information about Image", "I");
    7092    REG_KEY("Gallery", "DELETE", "Delete current image", "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)
  • mythplugins/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
  • mythplugins/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();
    98106    void actionDelete();
     
    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 actionDeleteMarked();
     117    void actionClearMarked();
     118    void actionSelectAll();
     119    void actionMkDir();
    103120
     121
    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#ifndef _WIN32
     154    bool                m_showDevices;
     155    MythMediaDevice    *m_currDevice;
     156#endif
    128157
    129158    int                 m_currRow;
    130159    int                 m_currCol;
     
    143172    int                 m_showcaption;
    144173
    145174    typedef void (IconView::*Action)();
     175
     176#ifndef _WIN32
     177public slots:
     178    void mediaStatusChanged( MediaStatus oldStatus, MythMediaDevice* pMedia);
     179#endif
    146180};
    147181
    148182
  • mythplugins/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">
  • mythplugins/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));
     99                           
    85100        }
    86101       
    87102        delete [] exifvalue;
     
    115130    }
    116131    catch (...)
    117132    {
    118         std::cerr << "GalleryUtil: Failed to extract EXIF headers from "
    119         << filePath << std::endl;
     133        VERBOSE(VB_IMPORTANT, LOC_ERR +
     134                QString("Failed to extract EXIF headers from '%1'")
     135                .arg(filePath));
    120136    }
    121137
    122138    return rotateAngle;
     
    249265        }
    250266        else
    251267        {
    252            std::cerr << "Could not load exif data from " << filePath << std::endl;
     268           VERBOSE(VB_IMPORTANT, LOC_ERR +
     269                   QString("Could not load exif data from '%1'")
     270                   .arg(filePath));
    253271        }
    254272       
    255273        delete [] exifvalue;
     
    257275    }
    258276    catch (...)
    259277    {
    260         std::cerr << "GalleryUtil: Failed to extract EXIF headers from "
    261         << filePath << std::endl;
     278        VERBOSE(VB_IMPORTANT, LOC_ERR +
     279                QString("Failed to extract EXIF headers from '%1'")
     280                .arg(filePath));
    262281    }
    263282
    264283    return caption;
    265284}
     285
     286bool GalleryUtil::Copy(const QFileInfo &src, QFileInfo &dst)
     287{
     288    if (src.isDir())
     289        return CopyDirectory(src, dst);
     290
     291    dst = MakeUnique(dst);
     292
     293    if (!FileCopy(src, dst))
     294        return false;
     295
     296    MSqlQuery query(MSqlQuery::InitCon());
     297    query.prepare("INSERT INTO gallerymetadata (image, keywords, angle) "
     298                  "SELECT :IMAGENEW , keywords, angle "
     299                  "FROM gallerymetadata "
     300                  "WHERE image = :IMAGEOLD");
     301    query.bindValue(":IMAGENEW", dst.absFilePath().utf8());
     302    query.bindValue(":IMAGEOLD", src.absFilePath().utf8());
     303    if (query.exec())
     304        return true;
     305
     306    // try to undo copy on DB failure
     307    FileDelete(dst);
     308    return false;
     309}
     310
     311bool GalleryUtil::Move(const QFileInfo &src, QFileInfo &dst)
     312{
     313    if (src.isDir())
     314        return MoveDirectory(src, dst);
     315
     316    dst = MakeUnique(dst);
     317
     318    if (!FileMove(src, dst))
     319        return false;
     320
     321    MSqlQuery query(MSqlQuery::InitCon());
     322    query.prepare("UPDATE gallerymetadata "
     323                  "SET image = :IMAGENEW "
     324                  "WHERE image = :IMAGEOLD");
     325    query.bindValue(":IMAGENEW", dst.absFilePath().utf8());
     326    query.bindValue(":IMAGEOLD", src.absFilePath().utf8());
     327    if (query.exec())
     328        return true;
     329
     330    // try to undo move on DB failure
     331    FileMove(dst, src);
     332    return false;
     333}
     334
     335bool GalleryUtil::Delete(const QFileInfo &file)
     336{
     337    if (!file.exists())
     338        return false;
     339
     340    if (file.isDir())
     341        return DeleteDirectory(file);
     342
     343    MSqlQuery query(MSqlQuery::InitCon());
     344    query.prepare("DELETE FROM gallerymetadata "
     345                  "WHERE image = :IMAGE ;");
     346    query.bindValue(":IMAGE", file.absFilePath().utf8());
     347    if (query.exec())
     348        return FileDelete(file);
     349
     350    return false;
     351}
     352
     353bool GalleryUtil::CopyDirectory(const QFileInfo src, QFileInfo &dst)
     354{
     355    QDir srcDir(src.absFilePath());
     356
     357    dst = MakeUniqueDirectory(dst);
     358    if (!dst.exists())
     359    {
     360        srcDir.mkdir(dst.absFilePath());
     361        dst.refresh();
     362    }
     363
     364    if (!dst.exists() || !dst.isDir())
     365        return false;
     366
     367    bool ok = true;
     368    QDir dstDir(dst.absFilePath());
     369    QFileInfoListIterator it(*srcDir.entryInfoList());
     370    for (; it.current(); ++it)
     371    {
     372        const QString fn = (it.current())->fileName();
     373        if (fn != "." && fn != "..")
     374        {
     375            QFileInfo dfi(dstDir, fn);
     376            ok &= Copy(*(it.current()), dfi);
     377        }
     378    }
     379
     380    return ok;
     381}
     382
     383bool GalleryUtil::MoveDirectory(const QFileInfo src, QFileInfo &dst)
     384{
     385    QDir srcDir(src.absFilePath());
     386
     387    dst = MakeUniqueDirectory(dst);
     388    if (!dst.exists())
     389    {
     390        srcDir.mkdir(dst.absFilePath());
     391        dst.refresh();
     392    }
     393
     394    if (!dst.exists() || !dst.isDir())
     395        return false;
     396
     397    bool ok = true;
     398    QDir dstDir(dst.absFilePath());
     399    QFileInfoListIterator it(*srcDir.entryInfoList());
     400    for (; it.current(); ++it)
     401    {
     402        const QString fn = (it.current())->fileName();
     403        if (fn != "." && fn != "..")
     404        {
     405            QFileInfo dfi(dstDir, fn);
     406            ok &= Move(*(it.current()), dfi);
     407        }
     408    }
     409
     410    return ok && FileDelete(src);
     411}
     412
     413bool GalleryUtil::DeleteDirectory(const QFileInfo &dir)
     414{
     415    if (!dir.exists())
     416        return false;
     417
     418    QDir srcDir(dir.absFilePath());
     419    QFileInfoListIterator it(*srcDir.entryInfoList());
     420    for (; it.current(); ++it)
     421    {
     422        const QString fn = (it.current())->fileName();
     423        if (fn != "." && fn != "..")
     424            Delete(*(it.current()));
     425    }
     426
     427    return FileDelete(dir);
     428}
     429
     430static QFileInfo MakeUnique(const QFileInfo &dest)
     431{
     432    QFileInfo newDest = dest;
     433
     434    for (uint i = 0; newDest.exists(); i++)
     435    {
     436        QString basename = QString("%1_%2.%3")
     437            .arg(dest.baseName(false)).arg(i).arg(dest.extension());
     438
     439        newDest.setFile(dest.dir(), basename);
     440
     441        VERBOSE(VB_GENERAL, LOC_ERR +
     442                QString("Need to find a new name for '%1' trying '%2'")
     443                .arg(dest.absFilePath()).arg(newDest.absFilePath()));
     444    }
     445
     446    return newDest;
     447}
     448
     449static QFileInfo MakeUniqueDirectory(const QFileInfo &dest)
     450{
     451    QFileInfo newDest = dest;
     452
     453    for (uint i = 0; newDest.exists() && !newDest.isDir(); i++)
     454    {
     455        QString fullname = QString("%1_%2").arg(dest.absFilePath()).arg(i);
     456        newDest.setFile(fullname);
     457
     458        VERBOSE(VB_GENERAL, LOC_ERR +
     459                QString("Need to find a new name for '%1' trying '%2'")
     460                .arg(dest.absFilePath()).arg(newDest.absFilePath()));
     461    }
     462
     463    return newDest;
     464}
     465
     466static bool FileCopy(const QFileInfo &src, const QFileInfo &dst)
     467{
     468    QString cmd = "cp ";
     469    cmd += "\"" + src.absFilePath().local8Bit() + "\" \"";
     470    cmd += dst.absFilePath().local8Bit() + "\"";
     471    myth_system(cmd);
     472    return true;
     473}
     474
     475static bool FileMove(const QFileInfo &src, const QFileInfo &dst)
     476{
     477    QString cmd = "mv ";
     478    cmd += "\"" + src.absFilePath().local8Bit() + "\" \"";
     479    cmd += dst.absFilePath().local8Bit() + "\"";
     480    myth_system(cmd);
     481    return true;
     482}
     483
     484static bool FileDelete(const QFileInfo &file)
     485{
     486    if (!file.isDir())
     487    {
     488        QString cmd = "rm \"" + file.absFilePath().local8Bit() + "\"";
     489        myth_system(cmd);
     490        return true;
     491    }
     492
     493    QDir srcDir(file.absFilePath());
     494    srcDir.setNameFilter(MEDIA_FILENAMES);
     495    srcDir.setSorting(QDir::Name | QDir::DirsFirst | QDir::IgnoreCase);
     496    srcDir.setMatchAllDirs(true);
     497
     498    // delete .thumbcache
     499    QString cmd = "rm -rf \"" + srcDir.absPath().local8Bit();
     500    cmd += "/.thumbcache\"";
     501
     502    myth_system(cmd);
     503
     504    srcDir.rmdir(srcDir.absPath());
     505    return true;
     506}
     507
     508// Clear marks after operation
     509// Allow wholesale clearing of marks
     510// If there are no marks and operation is delete,
     511//   mark then delete selected item
     512// Exit submenu on ESCAPE
     513// Bind DELETE to 'Delete Marked'
     514// Show progress bar while performing operation
     515// Use Qt or C API for renaming/unlinking/copying files or directories.
     516// Exit "Show Devices" on exit from submenu
     517// GetMedias() is unsafe if a device is removed/unmounted while you are
     518//   looking at its returned list...
     519// Avoid using #define and #ifdef when possible.
  • mythtv/themes/blue/gallery-ui.xml

     
    77   
    88
    99    <container name="menu">
    10       <area>20,20,140,200</area>
     10      <area>20,20,140,500</area>
    1111
    1212      <listbtnarea name="menu" draworder="0">
    1313        <area>0,0,140,200</area>
     
    2121        <showscrollarrows>no</showscrollarrows>
    2222      </listbtnarea>
    2323
     24      <listbtnarea name="submenu" draworder="0">
     25        <area>0,220,140,500</area>
     26        <gradient type="unselected" start="#000000" end="#505050" alpha="100">
     27        </gradient>
     28        <gradient type="selected" start="#52CA38" end="#349838" alpha="255">
     29        </gradient>
     30        <fcnfont name="list-active" function="active"></fcnfont>
     31        <fcnfont name="list-inactive" function="inactive"></fcnfont>
     32        <showarrow>no</showarrow>
     33        <showscrollarrows>no</showscrollarrows>
     34      </listbtnarea>
     35
    2436    </container>
    2537
    2638    <container name="text">