1. Andrew Cook
  2. Ogitor

Commits

stealth977  committed b9429dc

- Restore functionality added for recycle bin items

  • Participants
  • Parent commits ac6c8a4
  • Branches default

Comments (0)

Files changed (7)

File Dependencies/OFS/include/ofs14.h

View file
  • Ignore whitespace
             int          Id;              /* Id of the Owner Entry */
             int          ParentId;        /* Id of the Owner Entry's Parent Directory, -1 if root directory */
             unsigned int Flags;           /* File Flags */
-            unsigned int RESERVED[3];     /* RESERVED */
+            int          OldParentId;     /* Id of the Owner Entry's Old Parent Directory, -1 if root directory */
+            unsigned int RESERVED[2];     /* RESERVED */
             ofs64        FileSize;        /* Entry's File Size, 0 for Directories */
             ofs64        NextBlock;       /* File Position of Next Block owned by this entry */
             char         Name[256];       /* Entry's Name */
             int           Id;                     /* Id of the Owner Entry */
             int           ParentId;               /* Id of the Owner Entry's Parent Directory, -1 if root directory */
             unsigned int  Flags;                  /* File Flags */
+            int           OldParentId;            /* Id of the Owner Entry's Parent Directory, -1 if root directory */
             UUID          Uuid;                   /* UUID of Entry */
             time_t        CreationTime;           /* Entry's Creation Time */
             ofs64         FileSize;               /* Entry's File Size, 0 for Directories */
         */
         OfsResult    moveToRecycleBin(const char *path);
         /**
+        * Restores a given file/directory from recycle-bin
+        * @param id ID of file/directory to restore, we dont use names 
+        *           since there may be multiple items with same name
+        * @return Result of operation, OFS_OK if successful
+        */
+        OfsResult    restoreFromRecycleBin(int id);
+        /**
         * Deletes all Files in recyle bin and frees the space used
         * @return Result of operation, OFS_OK if successful
         */
         inline void   _setFileFlags(OfsEntryDesc *file, unsigned int flags);
         /* Internal  function to free files in recycle bin */
         inline void   _deleteRecycleBinDesc(OfsEntryDesc *desc);
+        /* Internal  function to find an entry by id */
+        OfsEntryDesc* _Ofs::_findDescById( OfsEntryDesc* base, int id );
+
 
         /* Searches given filename in the list of file system instances, 
          * returns it if found or creates a new one and adds it to the list otherwise */

File Dependencies/OFS/source/ofs14.cpp

View file
  • Ignore whitespace
                 else
                     entryDesc->UsedBlocks[0] = blockData;
 
+                if(entryDesc->ParentId == RECYCLEBIN_DIRECTORY_ID)
+                    entryDesc->OldParentId = mainEntry.OldParentId;
+                else
+                    entryDesc->OldParentId = ROOT_DIRECTORY_ID;
+                
                 entryDesc->Parent = it->second;
                 it->second->Children.push_back(entryDesc);
 
         dir->Id = mHeader.LAST_ID++;
         dir->ParentId = parent->Id;
         dir->Flags = OFS_DIR;
+        dir->OldParentId = ROOT_DIRECTORY_ID;
         dir->Name = name;
         dir->FileSize = 0;
         dir->Parent = parent;
         fileHeader.Id = dir->Id;
         fileHeader.ParentId = dir->ParentId;
         fileHeader.Flags = dir->Flags;
+        fileHeader.OldParentId = ROOT_DIRECTORY_ID;
         fileHeader.NextBlock = 0;
         fileHeader.FileSize = 0;
         fileHeader.CreationTime = dir->CreationTime;
         file->Id = mHeader.LAST_ID++;
         file->ParentId = parent->Id;
         file->Flags = OFS_FILE;
+        file->OldParentId = ROOT_DIRECTORY_ID;
         file->Name = name;
         file->FileSize = file_size;
         file->Parent = parent;
         fileHeader.Id = file->Id;
         fileHeader.ParentId = file->ParentId;
         fileHeader.Flags = file->Flags;
+        fileHeader.OldParentId = ROOT_DIRECTORY_ID;
         fileHeader.NextBlock = 0;
         fileHeader.FileSize = file->FileSize;
         fileHeader.CreationTime = file->CreationTime;
                     fileHeader.Id = fileDesc->Id;
                     fileHeader.ParentId = fileDesc->ParentId;
                     fileHeader.Flags = fileDesc->Flags;
+                    fileHeader.OldParentId = ROOT_DIRECTORY_ID;
                     fileHeader.NextBlock = 0;
                     fileHeader.FileSize = 0;
                     fileHeader.CreationTime = fileDesc->CreationTime;
                 fileHeader.Id = fileDesc->Id;
                 fileHeader.ParentId = fileDesc->ParentId;
                 fileHeader.Flags = fileDesc->Flags;
+                fileHeader.OldParentId = ROOT_DIRECTORY_ID;
                 fileHeader.NextBlock = 0;
                 fileHeader.FileSize = 0;
                 fileHeader.CreationTime = fileDesc->CreationTime;
             }
         }
 
+        dirDesc->OldParentId = dirDesc->ParentId;
         dirDesc->Parent = &mRecycleBinRoot;
         dirDesc->ParentId = mRecycleBinRoot.Id;
         mRecycleBinRoot.Children.push_back( dirDesc );
 
         mStream.seek(dirDesc->UsedBlocks[0].Start + offsetof(strMainEntryHeader, ParentId), OFS_SEEK_BEGIN);
         mStream.write((char*)&(dirDesc->ParentId), sizeof(unsigned int));
+        mStream.seek(dirDesc->UsedBlocks[0].Start + offsetof(strMainEntryHeader, OldParentId), OFS_SEEK_BEGIN);
+        mStream.write((char*)&(dirDesc->OldParentId), sizeof(unsigned int));
         mStream.flush();
 
         for(unsigned int i = 0;i < saveTrigs.size();i++)
     }
 
 //------------------------------------------------------------------------------------------
-    
+
+    _Ofs::OfsEntryDesc* _Ofs::_findDescById( _Ofs::OfsEntryDesc* base, int id )
+    {
+        std::vector<OfsEntryDesc*> list;
+        OfsEntryDesc* desc;
+
+        for( unsigned int i = 0; i < base->Children.size(); i++)
+        {
+            desc = base->Children[i];
+            if( (desc->Flags & OFS_DIR) && !(desc->Flags & OFS_LINK))
+            {
+                if( desc->Id == id  )
+                    return desc;
+                else
+                    list.push_back( desc );
+            }
+        }
+
+        for( unsigned int i = 0; i < list.size(); i++)
+        {
+            desc = _findDescById( base->Children[i], id );
+            if( desc != NULL ) 
+                return desc;
+        }
+
+        return NULL;
+    }
+
+//------------------------------------------------------------------------------------------
+
+    OfsResult _Ofs::restoreFromRecycleBin(int id)
+    {
+        LOCK_AUTO_MUTEX
+
+        if(!mActive)
+        {
+            OFS_EXCEPT("_Ofs::restoreFromRecycleBin, Operation called on an unmounted file system.");
+            return OFS_IO_ERROR;
+        }
+
+        OfsEntryDesc *sourceDesc = NULL, *destDesc = NULL;
+
+        for( unsigned int i = 0; i < mRecycleBinRoot.Children.size(); i++)
+        {
+            if( mRecycleBinRoot.Children[i]->Id == id )
+            {
+                sourceDesc = mRecycleBinRoot.Children[i];
+                break;
+            }
+        }
+
+        if( sourceDesc == NULL )
+            return OFS_FILE_NOT_FOUND;
+
+        destDesc = _findDescById( &mRootDir, sourceDesc->OldParentId );
+
+        if( destDesc == NULL )
+            destDesc = &mRootDir;
+
+        for( unsigned int i = 0; i < destDesc->Children.size(); i++)
+        {
+            if( destDesc->Children[i]->Name == sourceDesc->Name )
+                return OFS_ACCESS_DENIED;
+        }
+
+        for( unsigned int i = 0; i < mRecycleBinRoot.Children.size(); i++)
+        {
+            if( mRecycleBinRoot.Children[i]->Id == id )
+            {
+                mRecycleBinRoot.Children.erase(mRecycleBinRoot.Children.begin() + i);
+                break;
+            }
+        }
+
+        sourceDesc->OldParentId = ROOT_DIRECTORY_ID;
+        sourceDesc->Parent = destDesc;
+        sourceDesc->ParentId = destDesc->Id;
+        destDesc->Children.push_back( sourceDesc );
+
+        mStream.seek(sourceDesc->UsedBlocks[0].Start + offsetof(strMainEntryHeader, ParentId), OFS_SEEK_BEGIN);
+        mStream.write((char*)&(sourceDesc->ParentId), sizeof(unsigned int));
+        mStream.seek(sourceDesc->UsedBlocks[0].Start + offsetof(strMainEntryHeader, OldParentId), OFS_SEEK_BEGIN);
+        mStream.write((char*)&(sourceDesc->OldParentId), sizeof(unsigned int));
+        mStream.flush();
+
+        return OFS_OK;
+    }
+
+//------------------------------------------------------------------------------------------
+
     void _Ofs::_deleteRecycleBinDesc(OfsEntryDesc *desc)
     {
         unsigned int i;

File Documentation/Ofs_v14_Diag.xls

  • Ignore whitespace
Binary file modified.

File qtOgitor/include/projectfilesview.hxx

View file
  • Ignore whitespace
         bool mActImportFolderEnabled;
         bool mActAddEmptyFolderEnabled;
         bool mActEmptyRecycleBinEnabled;
+        bool mActRestoreFromRecycleBinEnabled;
 };
 
 class ProjectFilesViewWidget : public QWidget
 	void onUnlinkFileSystem( const QString & text );
 	void onSelectionChanged();
     void onEmptyRecycleBin();
+    void onRestoreFromRecycleBin();
 
 Q_SIGNALS:
     void needUpdate();
     QAction*        mActHidden;
     QAction*        mActLinkFileSystem;
     QAction*        mActEmptyRecycleBin;
+    QAction*        mActRestoreFromRecycleBin;
 
     void modifyStats( selectStats& stats, QTreeWidgetItem* item);
 };

File qtOgitor/res/icons/recyclebin_full.svg

View file
  • Ignore whitespace
Old
Old image
New
New image

File qtOgitor/src/ofstreewidget.cpp

View file
  • Ignore whitespace
         QTreeWidgetItem* item = new QTreeWidgetItem((QTreeWidget*)0, QStringList(QString(name.c_str())));
         item->setIcon(0, icon);
         item->setTextColor(0, Qt::black);
-        item->setWhatsThis(0, QString(name.c_str()));
+        item->setWhatsThis(0, QString("%1").arg(list[i].id));
+        item->setToolTip(0, QString(name.c_str()) + QString(" (%1)").arg(list[i].id));
 
         pItem->addChild(item);
     }

File qtOgitor/src/projectfilesview.cpp

View file
  • Ignore whitespace
     mActEmptyRecycleBin->setStatusTip(tr("Delete contents of Recycle Bin"));
     mActEmptyRecycleBin->setIcon(QIcon(":/icons/recyclebin_empty.svg"));
 
+    mActRestoreFromRecycleBin = new QAction(tr("Restore from Recycle Bin"), this);
+    mActRestoreFromRecycleBin->setStatusTip(tr("Restore file/folder to old location"));
+    mActRestoreFromRecycleBin->setIcon(QIcon(":/icons/refresh.svg"));
+
     mActMakeAsset = new QAction(tr("Make scene asset"), this);
     mActMakeAsset->setStatusTip(tr("Make the resource usable as a scene asset"));
     mActMakeAsset->setIcon(QIcon(":/icons/objects.svg"));
     mUnlinkFileSystem->setStatusTip(tr("Remove Link to the selected File System"));
 
     mMenu->addAction(mActEmptyRecycleBin);
+    mMenu->addAction(mActRestoreFromRecycleBin);
     mMenu->addAction(mActAddFolder);
     mMenu->addAction(mActLinkFileSystem);
     mMenu->addMenu(mUnlinkFileSystem);
     connect(mActHidden,         SIGNAL(triggered()),    this,   SLOT(onHidden()));
     connect(mActLinkFileSystem, SIGNAL(triggered()),    this,   SLOT(onLinkFileSystem()));
     connect(mActEmptyRecycleBin, SIGNAL(triggered()),    this,   SLOT(onEmptyRecycleBin()));
+    connect(mActRestoreFromRecycleBin, SIGNAL(triggered()),    this,   SLOT(onRestoreFromRecycleBin()));
 
     mToolBar = new QToolBar();
     mToolBar->setIconSize(QSize(16, 16));
 
 	QList<QTreeWidgetItem*> selItems = mOfsTreeWidget->selectedItems();
 
-    if(selItems.size() == 1)
+    if(selItems.size() == 1 && selItems[0]->parent() != mOfsTreeWidget->topLevelItem(1))
     {
         QString path = selItems[0]->whatsThis(0);
         OFS::OfsPtr& file = Ogitors::OgitorsRoot::getSingletonPtr()->GetProjectFile();
     {
         memset( &stats, 0, sizeof(selectStats) );
 
+        stats.mActRestoreFromRecycleBinEnabled = true;
+
         return;
     }
 
+    stats.mActEmptyRecycleBinEnabled = false;
+    stats.mActRestoreFromRecycleBinEnabled = false;
+
     OFS::_Ofs::NameOfsPtrMap fsLinks;
 
     QString path = item->whatsThis(0);
     stats.mActImportFileEnabled = true;
     stats.mActImportFolderEnabled = true;
     stats.mActAddEmptyFolderEnabled = true;
-    stats.mActEmptyRecycleBinEnabled = false;
+    stats.mActEmptyRecycleBinEnabled = true;
+    stats.mActRestoreFromRecycleBinEnabled = true;
 
     for( int s = 0; s < selItems.size() ; s++ )
     {
     mActImportFolder->setEnabled( stats.mActImportFolderEnabled );
     mActAddFolder->setEnabled( stats.mActAddEmptyFolderEnabled );
     mActEmptyRecycleBin->setVisible( stats.mActEmptyRecycleBinEnabled );
+    mActRestoreFromRecycleBin->setVisible( stats.mActRestoreFromRecycleBinEnabled );
 
     QPoint globalPos = mOfsTreeWidget->mapToGlobal(pos);
     mMenu->exec(globalPos);
     ofsFile->emptyRecycleBin();
 }
 //----------------------------------------------------------------------------------------
+void ProjectFilesViewWidget::onRestoreFromRecycleBin()
+{
+    QStringList selItems = mOfsTreeWidget->getSelectedItems();
+    OFS::OfsPtr& ofsFile = Ogitors::OgitorsRoot::getSingletonPtr()->GetProjectFile();
+
+    if(selItems.size() > 0 && ofsFile.valid())
+    {
+        if(QMessageBox::information(QApplication::activeWindow(), "qtOgitor", tr("Are you sure you want to restore selected files/folders?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
+        {
+            for(int i = 0;i < selItems.size();i++)
+            {
+                int id = selItems.at(i).toInt();
+
+                OFS::OfsResult ret = ofsFile->restoreFromRecycleBin( id );
+
+                if( ret == OFS::OFS_ACCESS_DENIED )
+                {
+                    QMessageBox::information(QApplication::activeWindow(), "qtOgitor", tr("Restore failed for selected item(s) due to name collision."), QMessageBox::Ok);
+                }
+            }
+
+            mOfsTreeWidget->refreshWidget();            
+        }
+    }
+}
+//----------------------------------------------------------------------------------------
 void ProjectFilesViewWidget::onRefresh()
 {
     mOfsTreeWidget->refreshWidget();