[vlc-devel] [PATCH 3/4] Qt GUI: implemented cloud tab.

Paweł Wegner pawel.wegner95 at gmail.com
Wed Oct 19 19:50:58 CEST 2016


---
 modules/gui/qt/components/open_panels.cpp | 183 ++++++++++++++++++++++++++++++
 modules/gui/qt/components/open_panels.hpp |  43 +++++++
 modules/gui/qt/dialogs/open.cpp           |  12 ++
 modules/gui/qt/dialogs/open.hpp           |   2 +
 modules/gui/qt/menus.cpp                  |   2 +
 modules/gui/qt/ui/open_cloud.ui           |  39 -------
 6 files changed, 242 insertions(+), 39 deletions(-)

diff --git a/modules/gui/qt/components/open_panels.cpp b/modules/gui/qt/components/open_panels.cpp
index 3d0f6d9..2232dbe 100644
--- a/modules/gui/qt/components/open_panels.cpp
+++ b/modules/gui/qt/components/open_panels.cpp
@@ -53,6 +53,7 @@
 #include <QUrl>
 #include <QMimeData>
 #include <QDropEvent>
+#include <QDesktopServices>
 
 #define I_DEVICE_TOOLTIP \
     I_DIR_OR_FOLDER( N_("Select a device or a VIDEO_TS directory"), \
@@ -1403,17 +1404,199 @@ void CaptureOpenPanel::advancedDialog()
     module_config_free( p_config );
 }
 
+#ifdef WITH_LIBCLOUDSTORAGE
+
+using cloudstorage::IItem;
+using cloudstorage::ICloudProvider;
+
+namespace
+{
+class CloudCallback : public cloudstorage::ICloudProvider::ICallback
+{
+public:
+    Status userConsentRequired(const ICloudProvider& provider) override
+    {
+        QDesktopServices::openUrl(QUrl(provider.authorizeLibraryUrl().c_str()));
+        return Status::WaitForAuthorizationCode;
+    }
+
+    void accepted(const ICloudProvider&) override
+    {
+    }
+
+    void declined(const ICloudProvider&) override
+    {
+    }
+
+    void error(const ICloudProvider&,
+               const std::string&) override
+    {
+    }
+};
+} // namespace
 
 CloudOpenPanel::CloudOpenPanel( QWidget *parent, intf_thread_t *t ) :
                                   OpenPanel( parent, t )
 {
+    cloudStorage = cloudstorage::ICloudStorage::create();
+    QWidget* selectProvider = new QWidget(this);
+    QVBoxLayout* selectProviderLayout = new QVBoxLayout;
+    for (auto t : cloudStorage->providers())
+    {
+        QSettings settings;
+        std::string token = settings.value(t->name().c_str()).toString().toStdString();
+        t->initialize({token, std::unique_ptr<CloudCallback>(new CloudCallback),
+                       nullptr, nullptr, nullptr, {}});
+        QPushButton* button = new QPushButton(t->name().c_str());
+        selectProviderLayout->addWidget(button);
+        connect(button, &QPushButton::pressed, this, &CloudOpenPanel::buttonClicked);
+    }
+    selectProvider->setLayout(selectProviderLayout);
+    QListView* selectFile = new QListView(this);
+    selectFile->setModel(&directoryModel);
+    connect(selectFile, &QListView::doubleClicked, this, &CloudOpenPanel::itemClicked);
+    QHBoxLayout* mainLayout = new QHBoxLayout(this);
+    mainLayout->addWidget(selectProvider);
+    mainLayout->addWidget(selectFile);
+    setLayout(mainLayout);
     ui.setupUi(this);
 }
 
+CloudOpenPanel::~CloudOpenPanel()
+{
+    save();
+}
+
+void CloudOpenPanel::save()
+{
+    if (currentProvider)
+    {
+        QSettings settings;
+        settings.setValue(currentProvider->name().c_str(), currentProvider->token().c_str());
+    }
+}
+
 void CloudOpenPanel::clear()
 {
 }
 
+void CloudOpenPanel::keyPressEvent(QKeyEvent *e)
+{
+    OpenPanel::keyPressEvent(e);
+    if (!e->isAccepted() && e->key() == Qt::Key_Backspace)
+    {
+        if (!directoryStack.empty())
+        {
+            currentDirectory = directoryStack.back();
+            directoryStack.pop_back();
+            listDirectory();
+        }
+        else
+        {
+            directoryModel.clear();
+            currentDirectory = nullptr;
+            currentProvider = nullptr;
+        }
+        e->accept();
+    }
+}
+
+void CloudOpenPanel::buttonClicked()
+{
+    save();
+    directoryStack.clear();
+    QPushButton* button = static_cast<QPushButton*>(sender());
+    currentProvider = cloudStorage->provider(button->text().toStdString());
+    currentDirectory = currentProvider->rootDirectory();
+    listDirectory();
+}
+
+void CloudOpenPanel::itemClicked(const QModelIndex& index)
+{
+    auto item = directoryModel.get(index.row());
+    if (item->type() == cloudstorage::IItem::FileType::Directory)
+    {
+        directoryStack.push_back(currentDirectory);
+        currentDirectory = item;
+        listDirectory();
+    }
+    else
+    {
+        itemDataRequest = currentProvider->getItemDataAsync(item->id(), [this](IItem::Pointer i) {
+            if (!i) return;
+            QStringList list;
+            list << i->url().c_str();
+            emit methodChanged( qfu( "network-caching" ) );
+            emit mrlUpdated(list, "");
+        });
+    }
+}
+
+void CloudOpenPanel::listDirectory()
+{
+    directoryModel.clear();
+    listDirectoryRequest = currentProvider->listDirectoryAsync(currentDirectory,
+                                                               [this](const std::vector<cloudstorage::IItem::Pointer>& d) {
+        for (auto i : d)
+            directoryModel.addItem(i);
+    });
+}
+
 void CloudOpenPanel::updateMRL()
 {
 }
+
+void DirectoryModel::addItem(IItem::Pointer item) {
+  beginInsertRows(QModelIndex(), rowCount(), rowCount());
+  {
+    QMutexLocker lock(&mutex);
+    list.push_back(item);
+  }
+  endInsertRows();
+}
+
+IItem::Pointer DirectoryModel::get(int idx) const
+{
+    QMutexLocker lock(&mutex);
+    return list[idx];
+}
+
+QVariant DirectoryModel::getName(int idx) const
+{
+    QMutexLocker lock(&mutex);
+    return QString::fromStdString(list[idx]->filename());
+}
+
+QVariant DirectoryModel::getIcon(int idx) const
+{
+    QMutexLocker lock(&mutex);
+    auto item = list[idx];
+    if (item->type() == IItem::FileType::Directory)
+        return QFileIconProvider().icon(QFileIconProvider::Folder);
+    else
+        return QFileIconProvider().icon(QFileIconProvider::File);
+}
+
+void DirectoryModel::clear()
+{
+    beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
+    list.clear();
+    endRemoveRows();
+}
+
+int DirectoryModel::rowCount(const QModelIndex &) const
+{
+    QMutexLocker lock(&mutex);
+    return list.size();
+}
+
+QVariant DirectoryModel::data(const QModelIndex &index, int role) const
+{
+    if (role == Qt::DisplayRole)
+        return getName(index.row());
+    else if (role == Qt::DecorationRole)
+        return getIcon(index.row());
+    return QVariant();
+}
+
+#endif
diff --git a/modules/gui/qt/components/open_panels.hpp b/modules/gui/qt/components/open_panels.hpp
index af61c6b..6bd55a7 100644
--- a/modules/gui/qt/components/open_panels.hpp
+++ b/modules/gui/qt/components/open_panels.hpp
@@ -41,9 +41,17 @@
 #include "ui/open_cloud.h"
 
 #include <QFileDialog>
+#include <QMutex>
 
 #include <limits.h>
 
+#ifdef WITH_LIBCLOUDSTORAGE
+  #include <ICloudStorage.h>
+  #include <ICloudProvider.h>
+  #include <IRequest.h>
+  #include <IItem.h>
+#endif
+
 #define setSpinBoxFreq( spinbox ){ spinbox->setRange ( 0, INT_MAX ); \
     spinbox->setAccelerated( true ); }
 
@@ -231,17 +239,52 @@ private slots:
     void advancedDialog();
 };
 
+class DirectoryModel : public QAbstractListModel {
+public:
+    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex& index, int) const override;
+    void addItem(cloudstorage::IItem::Pointer item);
+    cloudstorage::IItem::Pointer get(int) const;
+    QVariant getName(int) const;
+    QVariant getIcon(int) const;
+    void clear();
+
+private:
+    mutable QMutex mutex;
+    std::vector<cloudstorage::IItem::Pointer> list;
+};
+
+#ifdef WITH_LIBCLOUDSTORAGE
 class CloudOpenPanel : public OpenPanel
 {
     Q_OBJECT
 public:
     CloudOpenPanel( QWidget *, intf_thread_t * );
+    ~CloudOpenPanel();
+
+    void save();
     void clear();
+
+protected:
+    void keyPressEvent(QKeyEvent*) override;
+
 private:
     Ui::OpenCloud ui;
+    DirectoryModel directoryModel;
+    cloudstorage::ICloudStorage::Pointer cloudStorage;
+    cloudstorage::ICloudProvider::Pointer currentProvider;
+    cloudstorage::IItem::Pointer currentDirectory;
+    cloudstorage::ICloudProvider::ListDirectoryRequest::Pointer listDirectoryRequest;
+    cloudstorage::ICloudProvider::GetItemDataRequest::Pointer itemDataRequest;
+    std::vector<cloudstorage::IItem::Pointer> directoryStack;
+
+    void buttonClicked();
+    void itemClicked(const QModelIndex&);
+    void listDirectory();
 
 public slots:
     void updateMRL();
 };
+#endif
 
 #endif
diff --git a/modules/gui/qt/dialogs/open.cpp b/modules/gui/qt/dialogs/open.cpp
index 3856099..2625393 100644
--- a/modules/gui/qt/dialogs/open.cpp
+++ b/modules/gui/qt/dialogs/open.cpp
@@ -84,7 +84,9 @@ OpenDialog::OpenDialog( QWidget *parent,
     discOpenPanel    = new DiscOpenPanel( this, p_intf );
     netOpenPanel     = new NetOpenPanel( this, p_intf );
     captureOpenPanel = new CaptureOpenPanel( this, p_intf );
+#ifdef WITH_LIBCLOUDSTORAGE
     cloudOpenPanel   = new CloudOpenPanel( this, p_intf );
+#endif
 
     /* Insert the tabs */
     ui.Tab->insertTab( OPEN_FILE_TAB, fileOpenPanel, QIcon( ":/type/file-asym" ),
@@ -95,8 +97,10 @@ OpenDialog::OpenDialog( QWidget *parent,
                        qtr( "&Network" ) );
     ui.Tab->insertTab( OPEN_CAPTURE_TAB, captureOpenPanel,
                        QIcon( ":/type/capture-card" ), qtr( "Capture &Device" ) );
+#ifdef WITH_LIBCLOUDSTORAGE
     ui.Tab->insertTab( OPEN_CLOUD_TAB, cloudOpenPanel, QIcon( ":/type/cloud" ),
                        qtr( "&Cloud" ) );
+#endif
 
     /* Hide the Slave input widgets */
     ui.slaveLabel->hide();
@@ -144,6 +148,10 @@ OpenDialog::OpenDialog( QWidget *parent,
              this, updateMRL( const QStringList&, const QString& ) );
     CONNECT( captureOpenPanel, mrlUpdated( const QStringList&, const QString& ),
              this, updateMRL( const QStringList&, const QString& ) );
+#ifdef WITH_LIBCLOUDSTORAGE
+    CONNECT( cloudOpenPanel, mrlUpdated( const QStringList&, const QString& ),
+             this, updateMRL( const QStringList&, const QString& ) );
+#endif
 
     CONNECT( fileOpenPanel, methodChanged( const QString& ),
              this, newCachingMethod( const QString& ) );
@@ -153,6 +161,10 @@ OpenDialog::OpenDialog( QWidget *parent,
              this, newCachingMethod( const QString& ) );
     CONNECT( captureOpenPanel, methodChanged( const QString& ),
              this, newCachingMethod( const QString& ) );
+#ifdef WITH_LIBCLOUDSTORAGE
+    CONNECT( cloudOpenPanel, methodChanged( const QString& ),
+             this, newCachingMethod( const QString& ) );
+#endif
 
     /* Advanced frame Connects */
     CONNECT( ui.slaveCheckbox, toggled( bool ), this, updateMRL() );
diff --git a/modules/gui/qt/dialogs/open.hpp b/modules/gui/qt/dialogs/open.hpp
index 6932851..f292760 100644
--- a/modules/gui/qt/dialogs/open.hpp
+++ b/modules/gui/qt/dialogs/open.hpp
@@ -99,7 +99,9 @@ private:
     NetOpenPanel *netOpenPanel;
     DiscOpenPanel *discOpenPanel;
     CaptureOpenPanel *captureOpenPanel;
+#ifdef WITH_LIBCLOUDSTORAGE
     CloudOpenPanel *cloudOpenPanel;
+#endif
 
     int i_action_flag;
     bool b_pl;
diff --git a/modules/gui/qt/menus.cpp b/modules/gui/qt/menus.cpp
index c70a315..78563ff 100644
--- a/modules/gui/qt/menus.cpp
+++ b/modules/gui/qt/menus.cpp
@@ -370,8 +370,10 @@ QMenu *VLCMenuBar::FileMenu( intf_thread_t *p_intf, QWidget *parent, MainInterfa
         ":/type/network", SLOT( openNetDialog() ), "Ctrl+N" );
     addDPStaticEntry( menu, qtr( "Open &Capture Device..." ),
         ":/type/capture-card", SLOT( openCaptureDialog() ), "Ctrl+C" );
+#ifdef WITH_LIBCLOUDSTORAGE
     addDPStaticEntry( menu, qtr( "Open Cloud File..."),
         ":/type/cloud", SLOT( openCloudDialog() ) );
+#endif
 
     addDPStaticEntry( menu, qtr( "Open &Location from clipboard" ),
                       NULL, SLOT( openUrlDialog() ), "Ctrl+V" );
diff --git a/modules/gui/qt/ui/open_cloud.ui b/modules/gui/qt/ui/open_cloud.ui
index 1401402..9844411 100644
--- a/modules/gui/qt/ui/open_cloud.ui
+++ b/modules/gui/qt/ui/open_cloud.ui
@@ -13,45 +13,6 @@
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <widget class="QPushButton" name="pushButton">
-   <property name="geometry">
-    <rect>
-     <x>20</x>
-     <y>20</y>
-     <width>99</width>
-     <height>27</height>
-    </rect>
-   </property>
-   <property name="text">
-    <string>GoogleDrive</string>
-   </property>
-  </widget>
-  <widget class="QPushButton" name="pushButton_2">
-   <property name="geometry">
-    <rect>
-     <x>20</x>
-     <y>50</y>
-     <width>99</width>
-     <height>27</height>
-    </rect>
-   </property>
-   <property name="text">
-    <string>OneDrive</string>
-   </property>
-  </widget>
-  <widget class="QPushButton" name="pushButton_3">
-   <property name="geometry">
-    <rect>
-     <x>20</x>
-     <y>80</y>
-     <width>99</width>
-     <height>27</height>
-    </rect>
-   </property>
-   <property name="text">
-    <string>Dropbox</string>
-   </property>
-  </widget>
  </widget>
  <resources/>
  <connections/>
-- 
2.9.3



More information about the vlc-devel mailing list