diff options
author | Hannah von Reth <hannah.vonreth@owncloud.com> | 2022-02-24 16:51:15 +0300 |
---|---|---|
committer | Fabian Müller <80399010+fmoc@users.noreply.github.com> | 2022-04-13 17:21:25 +0300 |
commit | 6c2a0ea867f75dc36a997b829bdf2424bcb101d5 (patch) | |
tree | 372aa7b7f20d483759f2e370b89df22d57a2690a /src | |
parent | 4033411ffadb7d9491fafe89a2dc72f47173897e (diff) |
Allow to add Folder sync pairs based on spaces
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/gui/accountsettings.cpp | 7 | ||||
-rw-r--r-- | src/gui/folderstatusdelegate.cpp | 10 | ||||
-rw-r--r-- | src/gui/folderstatusdelegate.h | 6 | ||||
-rw-r--r-- | src/gui/folderstatusmodel.cpp | 6 | ||||
-rw-r--r-- | src/gui/folderwizard/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/gui/folderwizard/folderwizard.cpp | 51 | ||||
-rw-r--r-- | src/gui/folderwizard/folderwizard.h | 13 | ||||
-rw-r--r-- | src/gui/folderwizard/spacespage.cpp | 45 | ||||
-rw-r--r-- | src/gui/folderwizard/spacespage.h | 45 | ||||
-rw-r--r-- | src/gui/folderwizard/spacespage.ui | 32 | ||||
-rw-r--r-- | src/gui/models/expandingheaderview.cpp | 4 | ||||
-rw-r--r-- | src/gui/spaces/CMakeLists.txt | 14 | ||||
-rw-r--r-- | src/gui/spaces/spacesbrowser.cpp | 78 | ||||
-rw-r--r-- | src/gui/spaces/spacesbrowser.h | 49 | ||||
-rw-r--r-- | src/gui/spaces/spacesbrowser.ui | 52 | ||||
-rw-r--r-- | src/gui/spaces/spacesmodel.cpp | 147 | ||||
-rw-r--r-- | src/gui/spaces/spacesmodel.h | 55 |
18 files changed, 597 insertions, 26 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index c84d7864e..c337c6e36 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -118,7 +118,7 @@ add_subdirectory(folderwizard) add_library(owncloudCore STATIC ${final_src}) set_target_properties(owncloudCore PROPERTIES AUTOUIC ON AUTORCC ON) target_link_libraries(owncloudCore PUBLIC Qt5::Widgets Qt5::Network Qt5::Xml - libsync newwizard folderwizard) + libsync newwizard folderwizard spaces) target_compile_definitions(owncloudCore PUBLIC QT_USE_QSTRINGBUILDER QT_MESSAGELOGCONTEXT # enable function name and line number in debug output @@ -126,6 +126,10 @@ target_compile_definitions(owncloudCore QT_NO_FOREACH ) + +add_subdirectory(spaces) + + add_subdirectory(socketapi) target_include_directories(owncloudCore PUBLIC diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 520a8dc5a..c4f111bac 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -412,12 +412,14 @@ void AccountSettings::slotAddFolder() FolderMan *folderMan = FolderMan::instance(); folderMan->setSyncEnabled(false); // do not start more syncs. - FolderWizard *folderWizard = new FolderWizard(_accountState->account(), this); + FolderWizard *folderWizard = new FolderWizard(_accountState->account(), ocApp()->gui()->settingsDialog()); folderWizard->setAttribute(Qt::WA_DeleteOnClose); + folderWizard->resize(ocApp()->gui()->settingsDialog()->sizeHintForChild()); connect(folderWizard, &QDialog::accepted, this, &AccountSettings::slotFolderWizardAccepted); connect(folderWizard, &QDialog::rejected, this, &AccountSettings::slotFolderWizardRejected); folderWizard->open(); + ocApp()->gui()->raiseDialog(folderWizard); } @@ -428,8 +430,7 @@ void AccountSettings::slotFolderWizardAccepted() qCInfo(lcAccountSettings) << "Folder wizard completed"; - // TODO: spaces - auto definition = FolderDefinition::createNewFolderDefinition(_accountState->account()->davUrl()); + auto definition = FolderDefinition::createNewFolderDefinition(folderWizard->davUrl()); definition.setLocalPath(folderWizard->field(QLatin1String("sourceFolder")).toString()); definition.setTargetPath(folderWizard->property("targetPath").toString()); diff --git a/src/gui/folderstatusdelegate.cpp b/src/gui/folderstatusdelegate.cpp index a970c4f25..2a8ccf53f 100644 --- a/src/gui/folderstatusdelegate.cpp +++ b/src/gui/folderstatusdelegate.cpp @@ -41,9 +41,9 @@ FolderStatusDelegate::FolderStatusDelegate() { } -QString FolderStatusDelegate::addFolderText() +QString FolderStatusDelegate::addFolderText(bool useSpaces) { - return tr("Add Folder Sync Connection"); + return !useSpaces ? tr("Add Folder Sync Connection") : tr("Add a space"); } // allocate each item size in listview. @@ -62,7 +62,7 @@ QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem &option, QFontMetrics fm(qApp->font("QPushButton")); QStyleOptionButton opt; static_cast<QStyleOption &>(opt) = option; - opt.text = addFolderText(); + opt.text = addFolderText(index.data(FolderStatusDelegate::IsUsingSpaces).toBool()); return QApplication::style()->sizeFromContents( QStyle::CT_PushButton, &opt, fm.size(Qt::TextSingleLine, opt.text)) .expandedTo(QApplication::globalStrut()) @@ -109,6 +109,8 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & { QStyledItemDelegate::paint(painter, option, index); + const bool useSpaces = index.data(FolderStatusDelegate::IsUsingSpaces).toBool(); + auto textAlign = Qt::AlignLeft; QFont aliasFont = makeAliasFont(option.font); @@ -131,7 +133,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & static_cast<QStyleOption &>(opt) = option; opt.state &= ~QStyle::State_Selected; opt.state |= QStyle::State_Raised; - opt.text = addFolderText(); + opt.text = addFolderText(useSpaces); opt.rect.setWidth(qMin(opt.rect.width(), hint.width())); opt.rect.adjust(0, aliasMargin, 0, -aliasMargin); opt.rect = QStyle::visualRect(option.direction, option.rect, opt.rect); diff --git a/src/gui/folderstatusdelegate.h b/src/gui/folderstatusdelegate.h index 63dc22132..0532974e7 100644 --- a/src/gui/folderstatusdelegate.h +++ b/src/gui/folderstatusdelegate.h @@ -47,8 +47,8 @@ public: AddButton, // 1 = enabled; 2 = disabled FolderSyncText, - - IsReady // boolean + IsReady, // boolean + IsUsingSpaces // boolean }; void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override; QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override; @@ -62,7 +62,7 @@ public: static int rootFolderHeightWithoutErrors(const QFontMetrics &fm, const QFontMetrics &aliasFm); private: - static QString addFolderText(); + static QString addFolderText(bool useSapces); }; } // namespace OCC diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp index c7d12e807..788e07bd0 100644 --- a/src/gui/folderstatusmodel.cpp +++ b/src/gui/folderstatusmodel.cpp @@ -142,6 +142,10 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const if (role == Qt::EditRole) return QVariant(); + // independent of the index + if (role == FolderStatusDelegate::IsUsingSpaces) { + return _accountState->account()->capabilities().spacesSupport().enabled; + } switch (classify(index)) { case AddButton: { if (role == FolderStatusDelegate::AddButton) { @@ -150,7 +154,7 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const if (!_accountState->isConnected()) { return tr("You need to be connected to add a folder"); } - return tr("Click this button to add a folder to synchronize."); + return _accountState->account()->capabilities().spacesSupport().enabled ? tr("Click this button to add a space.") : tr("Click this button to add a folder to synchronize."); } return QVariant(); } diff --git a/src/gui/folderwizard/CMakeLists.txt b/src/gui/folderwizard/CMakeLists.txt index 8785b39e9..d3089fe66 100644 --- a/src/gui/folderwizard/CMakeLists.txt +++ b/src/gui/folderwizard/CMakeLists.txt @@ -2,6 +2,9 @@ add_library(folderwizard OBJECT folderwizard.cpp folderwizardsourcepage.ui folderwizardtargetpage.ui + + spacespage.cpp + spacespage.ui ) target_link_libraries(folderwizard PUBLIC Qt5::Widgets libsync) diff --git a/src/gui/folderwizard/folderwizard.cpp b/src/gui/folderwizard/folderwizard.cpp index 160c91e27..b515b0a6b 100644 --- a/src/gui/folderwizard/folderwizard.cpp +++ b/src/gui/folderwizard/folderwizard.cpp @@ -17,6 +17,8 @@ #include "ui_folderwizardsourcepage.h" #include "ui_folderwizardtargetpage.h" +#include "spacespage.h" + #include "account.h" #include "common/asserts.h" #include "configfile.h" @@ -28,6 +30,7 @@ #include "gui/accountstate.h" #include "gui/folderman.h" #include "gui/selectivesyncdialog.h" +#include "gui/spaces/spacesmodel.h" #include <QCheckBox> #include <QDesktopServices> @@ -81,9 +84,6 @@ FolderWizardLocalPath::FolderWizardLocalPath(const AccountPtr &account, QWidget connect(_ui->localFolderChooseBtn, &QAbstractButton::clicked, this, &FolderWizardLocalPath::slotChooseLocalFolder); _ui->localFolderChooseBtn->setToolTip(tr("Click to select a local folder to sync.")); - QString defaultPath = QDir::homePath() + QLatin1Char('/') + Theme::instance()->appName(); - defaultPath = FolderMan::instance()->findGoodPathForNewSyncFolder(defaultPath); - _ui->localFolderLineEdit->setText(QDir::toNativeSeparators(defaultPath)); _ui->localFolderLineEdit->setToolTip(tr("Enter the path to the local folder.")); _ui->warnLabel->setTextFormat(Qt::RichText); @@ -98,6 +98,7 @@ FolderWizardLocalPath::~FolderWizardLocalPath() void FolderWizardLocalPath::initializePage() { _ui->warnLabel->hide(); + _ui->localFolderLineEdit->setText(QDir::toNativeSeparators(static_cast<FolderWizard *>(wizard())->destination())); } void FolderWizardLocalPath::cleanupPage() @@ -212,7 +213,7 @@ void FolderWizardRemotePath::slotCreateRemoteFolder(const QString &folder) fullPath += QLatin1Char('/') + folder; // TODO: legacy - MkColJob *job = new MkColJob(_account, _account->davUrl(), fullPath, {}, this); + MkColJob *job = new MkColJob(_account, static_cast<FolderWizard *>(wizard())->davUrl(), fullPath, {}, this); /* check the owncloud configuration file and query the ownCloud */ connect(job, &MkColJob::finishedWithoutError, this, &FolderWizardRemotePath::slotCreateRemoteFolderFinished); @@ -327,7 +328,7 @@ bool FolderWizardRemotePath::selectByPath(QString path) void FolderWizardRemotePath::slotUpdateDirectories(const QStringList &list) { - QString webdavFolder = QUrl(_account->davUrl()).path(); + QString webdavFolder = static_cast<FolderWizard *>(wizard())->davUrl().path(); QTreeWidgetItem *root = _ui->folderTreeWidget->topLevelItem(0); if (!root) { @@ -411,8 +412,7 @@ void FolderWizardRemotePath::slotTypedPathFound(const QStringList &subpaths) LsColJob *FolderWizardRemotePath::runLsColJob(const QString &path) { - // TODO: legacy - LsColJob *job = new LsColJob(_account, _account->davUrl(), path, this); + LsColJob *job = new LsColJob(_account, static_cast<FolderWizard *>(wizard())->davUrl(), path, this); job->setProperties(QList<QByteArray>() << "resourcetype"); connect(job, &LsColJob::directoryListingSubfolders, this, &FolderWizardRemotePath::slotUpdateDirectories); @@ -585,19 +585,28 @@ void FolderWizardSelectiveSync::virtualFilesCheckboxClicked() FolderWizard::FolderWizard(AccountPtr account, QWidget *parent, Qt::WindowFlags flags) : QWizard(parent, flags) + , _account(account) , _folderWizardSourcePage(new FolderWizardLocalPath(account)) - , _folderWizardTargetPage(nullptr) , _folderWizardSelectiveSyncPage(new FolderWizardSelectiveSync(account)) { setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + if (account->capabilities().spacesSupport().enabled) { + _spacesPage = new SpacesPage(account, this); + setPage(Page_Space, _spacesPage); + _spacesPage->installEventFilter(this); + } setPage(Page_Source, _folderWizardSourcePage); _folderWizardSourcePage->installEventFilter(this); - if (!Theme::instance()->singleSyncFolder()) { + // for now spaces are meant to be synced as a whole + if (!account->capabilities().spacesSupport().enabled && !Theme::instance()->singleSyncFolder()) { _folderWizardTargetPage = new FolderWizardRemotePath(account); setPage(Page_Target, _folderWizardTargetPage); _folderWizardTargetPage->installEventFilter(this); } - setPage(Page_SelectiveSync, _folderWizardSelectiveSyncPage); + if (!account->capabilities().spacesSupport().enabled) { + // TODO: add spaces support to selective sync + setPage(Page_SelectiveSync, _folderWizardSelectiveSyncPage); + } setWindowTitle(tr("Add Folder Sync Connection")); setOptions(QWizard::CancelButtonOnLeft); @@ -609,6 +618,28 @@ FolderWizard::~FolderWizard() { } +QUrl FolderWizard::davUrl() const +{ + if (_account->capabilities().spacesSupport().enabled) { + auto url = _spacesPage->selectedSpace(Spaces::SpacesModel::Columns::WebDavUrl).toUrl(); + if (!url.path().endsWith(QLatin1Char('/'))) { + url.setPath(url.path() + QLatin1Char('/')); + } + return url; + } + return _account->davUrl(); +} + +QString FolderWizard::destination() const +{ + QString defaultPath = QDir::homePath() + QLatin1Char('/') + Theme::instance()->appName(); + if (_account->capabilities().spacesSupport().enabled) { + // TODO: account whide home + defaultPath = QDir::homePath() + QLatin1Char('/') + _spacesPage->selectedSpace(Spaces::SpacesModel::Columns::Name).toString(); + }; + return FolderMan::instance()->findGoodPathForNewSyncFolder(defaultPath); +} + bool FolderWizard::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::LayoutRequest) { diff --git a/src/gui/folderwizard/folderwizard.h b/src/gui/folderwizard/folderwizard.h index 1cf591ace..c1a9f9485 100644 --- a/src/gui/folderwizard/folderwizard.h +++ b/src/gui/folderwizard/folderwizard.h @@ -146,6 +146,7 @@ class FolderWizard : public QWizard Q_OBJECT public: enum { + Page_Space, Page_Source, Page_Target, Page_SelectiveSync @@ -154,13 +155,19 @@ public: explicit FolderWizard(AccountPtr account, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); ~FolderWizard() override; + QUrl davUrl() const; + + QString destination() const; + bool eventFilter(QObject *watched, QEvent *event) override; void resizeEvent(QResizeEvent *event) override; private: - FolderWizardLocalPath *_folderWizardSourcePage; - FolderWizardRemotePath *_folderWizardTargetPage; - FolderWizardSelectiveSync *_folderWizardSelectiveSyncPage; + AccountPtr _account; + class SpacesPage *_spacesPage; + FolderWizardLocalPath *_folderWizardSourcePage = nullptr; + FolderWizardRemotePath *_folderWizardTargetPage = nullptr; + FolderWizardSelectiveSync *_folderWizardSelectiveSyncPage = nullptr; }; diff --git a/src/gui/folderwizard/spacespage.cpp b/src/gui/folderwizard/spacespage.cpp new file mode 100644 index 000000000..e9af3dc39 --- /dev/null +++ b/src/gui/folderwizard/spacespage.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include "spacespage.h" +#include "ui_spacespage.h" + +#include <QModelIndex> + +using namespace OCC; + +SpacesPage::SpacesPage(AccountPtr acc, QWidget *parent) + : QWizardPage(parent) + , ui(new Ui::SpacesPage) +{ + ui->setupUi(this); + + ui->widget->setAccount(acc); + + connect(ui->widget, &Spaces::SpacesBrowser::selectionChanged, this, &QWizardPage::completeChanged); +} + +SpacesPage::~SpacesPage() +{ + delete ui; +} + +bool OCC::SpacesPage::isComplete() const +{ + return ui->widget->currentSpace().isValid(); +} + +QVariant OCC::SpacesPage::selectedSpace(Spaces::SpacesModel::Columns column) const +{ + return ui->widget->currentSpace().siblingAtColumn(static_cast<int>(column)).data(); +} diff --git a/src/gui/folderwizard/spacespage.h b/src/gui/folderwizard/spacespage.h new file mode 100644 index 000000000..850c86608 --- /dev/null +++ b/src/gui/folderwizard/spacespage.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#pragma once + +#include "gui/spaces/spacesmodel.h" + +#include "accountfwd.h" + +#include <QWizardPage> + + +namespace Ui { +class SpacesPage; +} + +namespace OCC { +class SpacesPage : public QWizardPage +{ + Q_OBJECT + +public: + explicit SpacesPage(AccountPtr acc, QWidget *parent = nullptr); + ~SpacesPage(); + + bool isComplete() const override; + + + QVariant selectedSpace(Spaces::SpacesModel::Columns column) const; + +private: + Ui::SpacesPage *ui; +}; + +}
\ No newline at end of file diff --git a/src/gui/folderwizard/spacespage.ui b/src/gui/folderwizard/spacespage.ui new file mode 100644 index 000000000..2a0b44154 --- /dev/null +++ b/src/gui/folderwizard/spacespage.ui @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SpacesPage</class> + <widget class="QWizardPage" name="SpacesPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>362</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>WizardPage</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="OCC::Spaces::SpacesBrowser" name="widget" native="true"/> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>OCC::Spaces::SpacesBrowser</class> + <extends>QWidget</extends> + <header>gui/spaces/spacesbrowser.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/gui/models/expandingheaderview.cpp b/src/gui/models/expandingheaderview.cpp index 3457d3f63..7bc5e3fd1 100644 --- a/src/gui/models/expandingheaderview.cpp +++ b/src/gui/models/expandingheaderview.cpp @@ -75,5 +75,7 @@ void ExpandingHeaderView::resizeColumns(bool reset) void ExpandingHeaderView::addResetActionToMenu(QMenu *menu) { - menu->addAction(tr("Reset column sizes"), this, [this] { resizeColumns(true); }); + menu->addAction(tr("Reset column sizes"), this, [this] { + resizeColumns(true); + }); } diff --git a/src/gui/spaces/CMakeLists.txt b/src/gui/spaces/CMakeLists.txt new file mode 100644 index 000000000..8485e7816 --- /dev/null +++ b/src/gui/spaces/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(spaces OBJECT + spacesmodel.cpp spacesbrowser.cpp spacesbrowser.ui) +target_link_libraries(spaces PUBLIC Qt5::Widgets libsync) +set_target_properties(spaces PROPERTIES AUTOUIC ON AUTORCC ON) +target_compile_definitions(spaces + PRIVATE QT_NO_CAST_TO_ASCII + QT_NO_CAST_FROM_ASCII + QT_NO_URL_CAST_FROM_STRING + QT_NO_CAST_FROM_BYTEARRAY + QT_USE_QSTRINGBUILDER + QT_MESSAGELOGCONTEXT # enable function name and line number in debug output + QT_DEPRECATED_WARNINGS + QT_NO_FOREACH +) diff --git a/src/gui/spaces/spacesbrowser.cpp b/src/gui/spaces/spacesbrowser.cpp new file mode 100644 index 000000000..a237bed68 --- /dev/null +++ b/src/gui/spaces/spacesbrowser.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include "spacesbrowser.h" +#include "ui_spacesbrowser.h" + +#include "spacesmodel.h" + +#include "graphapi/drives.h" + +#include "gui/models/expandingheaderview.h" + +#include <QCursor> +#include <QMenu> + +using namespace OCC::Spaces; + +SpacesBrowser::SpacesBrowser(QWidget *parent) + : QWidget(parent) + , ui(new Ui::SpacesBrowser) +{ + ui->setupUi(this); + _model = new SpacesModel(this); + ui->tableView->setModel(_model); + + connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SpacesBrowser::selectionChanged); + + ui->tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + auto header = new OCC::ExpandingHeaderView(QStringLiteral("SpacesBrowserHeader"), ui->tableView); + ui->tableView->setHorizontalHeader(header); + header->setExpandingColumn(static_cast<int>(SpacesModel::Columns::Name)); + header->hideSection(static_cast<int>(SpacesModel::Columns::WebDavUrl)); + // not used yet + header->hideSection(static_cast<int>(SpacesModel::Columns::WebUrl)); + header->setContextMenuPolicy(Qt::CustomContextMenu); + connect(header, &QHeaderView::customContextMenuRequested, header, [header, this] { + auto menu = new QMenu(this); + menu->setAttribute(Qt::WA_DeleteOnClose); + header->addResetActionToMenu(menu); + menu->popup(QCursor::pos()); + }); +} + +SpacesBrowser::~SpacesBrowser() +{ + delete ui; +} + +void SpacesBrowser::setAccount(OCC::AccountPtr acc) +{ + _acc = acc; + if (acc) { + QTimer::singleShot(0, this, [this] { + auto drive = new OCC::GraphApi::Drives(_acc); + connect(drive, &OCC::GraphApi::Drives::finishedSignal, [drive, this] { + _model->setData(_acc, drive->drives()); + show(); + }); + drive->start(); + }); + } +} + +QModelIndex SpacesBrowser::currentSpace() +{ + const auto spaces = ui->tableView->selectionModel()->selectedRows(); + return spaces.isEmpty() ? QModelIndex {} : spaces.first(); +} diff --git a/src/gui/spaces/spacesbrowser.h b/src/gui/spaces/spacesbrowser.h new file mode 100644 index 000000000..12c950339 --- /dev/null +++ b/src/gui/spaces/spacesbrowser.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#pragma once + +#include "account.h" + +#include <QWidget> + +namespace Ui { +class SpacesBrowser; +} + +namespace OCC::Spaces { +class SpacesModel; + +class SpacesBrowser : public QWidget +{ + Q_OBJECT + +public: + explicit SpacesBrowser(QWidget *parent = nullptr); + ~SpacesBrowser(); + + void setAccount(OCC::AccountPtr acc); + + QModelIndex currentSpace(); + +Q_SIGNALS: + void selectionChanged(); + +private: + Ui::SpacesBrowser *ui; + + OCC::AccountPtr _acc; + SpacesModel *_model; +}; + +}
\ No newline at end of file diff --git a/src/gui/spaces/spacesbrowser.ui b/src/gui/spaces/spacesbrowser.ui new file mode 100644 index 000000000..b4c6fe224 --- /dev/null +++ b/src/gui/spaces/spacesbrowser.ui @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SpacesBrowser</class> + <widget class="QWidget" name="SpacesBrowser"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QTableView" name="tableView"> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <attribute name="horizontalHeaderVisible"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderHighlightSections"> + <bool>false</bool> + </attribute> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/gui/spaces/spacesmodel.cpp b/src/gui/spaces/spacesmodel.cpp new file mode 100644 index 000000000..924d84384 --- /dev/null +++ b/src/gui/spaces/spacesmodel.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#include "spacesmodel.h" + +#include "networkjobs.h" + +#include <QPixmap> + +namespace { +constexpr QSize ImageSizeC(128, 128); +} + +using namespace OCC::Spaces; + +SpacesModel::SpacesModel(QObject *parent) + : QAbstractTableModel(parent) +{ +} + +QVariant SpacesModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal) { + const auto actionRole = static_cast<Columns>(section); + switch (role) { + case Qt::DisplayRole: + switch (actionRole) { + case Columns::Name: + return tr("Name"); + case Columns::Description: + return tr("Description"); + case Columns::WebUrl: + return tr("Web URL"); + case Columns::WebDavUrl: + return tr("Web Dav URL"); + case Columns::Image: + return tr("Image"); + case Columns::ColumnCount: + Q_UNREACHABLE(); + break; + } + } + } + return QAbstractTableModel::headerData(section, orientation, role); +} + +int SpacesModel::rowCount(const QModelIndex &parent) const +{ + Q_ASSERT(checkIndex(parent)); + if (parent.isValid()) + return 0; + return static_cast<int>(_data.size()); +} + +int SpacesModel::columnCount(const QModelIndex &parent) const +{ + Q_ASSERT(checkIndex(parent)); + if (parent.isValid()) { + return 0; + } + return static_cast<int>(Columns::ColumnCount); +} + +QVariant SpacesModel::data(const QModelIndex &index, int role) const +{ + Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)); + + const auto column = static_cast<Columns>(index.column()); + const auto &item = _data.at(index.row()); + switch (role) { + case Qt::DisplayRole: + switch (column) { + case Columns::Name: + return item.getName(); + case Columns::Description: + return item.getDescription(); + case Columns::WebUrl: + return item.getWebUrl(); + case Columns::WebDavUrl: + return item.getRoot().getWebDavUrl(); + case Columns::Image: { + const auto &special = item.getSpecial(); + const auto img = std::find_if(special.cbegin(), special.cend(), [](OpenAPI::OAIDriveItem it) { + return it.getSpecialFolder().getName() == QLatin1String("image"); + }); + return img == special.cend() ? QString() : img->getWebDavUrl(); + } + case Columns::ColumnCount: + Q_UNREACHABLE(); + break; + } + break; + case Qt::DecorationRole: + switch (column) { + case Columns::Image: { + auto it = _images.find(item.getId()); + if (it != _images.cend()) { + return QVariant::fromValue(*it); + } + const auto imgUrl = data(index, Qt::DisplayRole); + if (!imgUrl.isValid()) { + return {}; + } + // TODO: placeholder + _images[item.getId()] = QPixmap(); + auto davUrl = QUrl(item.getRoot().getWebDavUrl()); + auto path = imgUrl.toString().remove(item.getRoot().getWebDavUrl()); + auto job = new OCC::SimpleNetworkJob(_acc, davUrl, path, "GET", {}, {}, nullptr); + connect(job, &OCC::SimpleNetworkJob::finishedSignal, this, [job, id = item.getId(), index, this] { + QPixmap img; + qDebug() << img.loadFromData(job->reply()->readAll()); + img = img.scaled(ImageSizeC, Qt::KeepAspectRatio); + _images[id] = img; + Q_EMIT const_cast<SpacesModel *>(this)->dataChanged(index, index, { Qt::DecorationRole }); + }); + job->start(); + return _images[item.getId()]; + } break; + } + case Qt::SizeHintRole: { + switch (column) { + case Columns::Image: { + return ImageSizeC; + } + } + } + } + return {}; +} + +void SpacesModel::setData(OCC::AccountPtr acc, const QList<OpenAPI::OAIDrive> &data) +{ + beginResetModel(); + _acc = acc; + _data = data; + endResetModel(); +} diff --git a/src/gui/spaces/spacesmodel.h b/src/gui/spaces/spacesmodel.h new file mode 100644 index 000000000..8f40cd9e7 --- /dev/null +++ b/src/gui/spaces/spacesmodel.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) by Hannah von Reth <hannah.vonreth@owncloud.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#pragma once + +#include "accountfwd.h" + +#include <graphapi/drives.h> + +#include <QAbstractItemModel> + +namespace OCC::Spaces { +class SpacesModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + enum class Columns { + Image, + Name, + Description, + WebUrl, + WebDavUrl, + + ColumnCount + }; + Q_ENUM(Columns) + explicit SpacesModel(QObject *parent = nullptr); + + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + void setData(OCC::AccountPtr acc, const QList<OpenAPI::OAIDrive> &data); + +private: + QList<OpenAPI::OAIDrive> _data; + + mutable QMap<QString, QPixmap> _images; + OCC::AccountPtr _acc; +}; +}
\ No newline at end of file |