mirror of
https://github.com/nextcloud/desktop.git
synced 2024-12-14 17:51:41 +03:00
Settings: New UI that intergate the selective sync within the account settings
This commit is contained in:
parent
dfd9d8725c
commit
426d2338d9
9 changed files with 864 additions and 293 deletions
|
@ -21,13 +21,10 @@
|
|||
#include "folderstatusmodel.h"
|
||||
#include "utility.h"
|
||||
#include "application.h"
|
||||
#include "owncloudsetupwizard.h"
|
||||
#include "configfile.h"
|
||||
#include "ignorelisteditor.h"
|
||||
#include "account.h"
|
||||
#include "accountstate.h"
|
||||
#include "quotainfo.h"
|
||||
#include "selectivesyncdialog.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
|
||||
#include <math.h>
|
||||
|
@ -37,9 +34,13 @@
|
|||
#include <QListWidgetItem>
|
||||
#include <QMessageBox>
|
||||
#include <QAction>
|
||||
#include <QVBoxLayout>
|
||||
#include <QTreeView>
|
||||
#include <QKeySequence>
|
||||
#include <QIcon>
|
||||
#include <QVariant>
|
||||
#include <qstringlistmodel.h>
|
||||
#include <qpropertyanimation.h>
|
||||
|
||||
#include "account.h"
|
||||
|
||||
|
@ -64,10 +65,12 @@ AccountSettings::AccountSettings(QWidget *parent) :
|
|||
ui->setupUi(this);
|
||||
|
||||
_model = new FolderStatusModel;
|
||||
_model->setAccount(_accountState->account());
|
||||
_model->setParent(this);
|
||||
FolderStatusDelegate *delegate = new FolderStatusDelegate;
|
||||
delegate->setParent(this);
|
||||
|
||||
ui->_folderList->header()->hide();
|
||||
ui->_folderList->setItemDelegate( delegate );
|
||||
ui->_folderList->setModel( _model );
|
||||
#if defined(Q_OS_MAC)
|
||||
|
@ -75,12 +78,13 @@ AccountSettings::AccountSettings(QWidget *parent) :
|
|||
#else
|
||||
ui->_folderList->setMinimumWidth( 300 );
|
||||
#endif
|
||||
ui->_folderList->setEditTriggers( QAbstractItemView::NoEditTriggers );
|
||||
connect(ui->_folderList, SIGNAL(customContextMenuRequested(QPoint)),
|
||||
this, SLOT(slotCustomContextMenuRequested(QPoint)));
|
||||
|
||||
ui->_buttonRemove->setEnabled(false);
|
||||
ui->_buttonEnable->setEnabled(false);
|
||||
ui->_buttonSelectiveSync->setEnabled(false);
|
||||
ui->_buttonAdd->setEnabled(true);
|
||||
connect(ui->_folderList, SIGNAL(expanded(QModelIndex)) , this, SLOT(refreshSelectiveSyncStatus()));
|
||||
connect(ui->_folderList, SIGNAL(collapsed(QModelIndex)) , this, SLOT(refreshSelectiveSyncStatus()));
|
||||
connect(_model, SIGNAL(dirtyChanged()), this, SLOT(refreshSelectiveSyncStatus()));
|
||||
ui->selectiveSyncStatus->hide();
|
||||
|
||||
QAction *resetFolderAction = new QAction(this);
|
||||
resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5));
|
||||
|
@ -92,35 +96,59 @@ AccountSettings::AccountSettings(QWidget *parent) :
|
|||
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow()));
|
||||
addAction(syncNowAction);
|
||||
|
||||
connect(ui->_buttonRemove, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentFolder()));
|
||||
connect(ui->_buttonEnable, SIGNAL(clicked()), this, SLOT(slotEnableCurrentFolder()));
|
||||
connect(ui->_buttonAdd, SIGNAL(clicked()), this, SLOT(slotAddFolder()));
|
||||
connect(ui->_buttonSelectiveSync, SIGNAL(clicked()), this, SLOT(slotSelectiveSync()));
|
||||
connect(ui->modifyAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard()));
|
||||
connect(ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));;
|
||||
|
||||
connect(ui->_folderList, SIGNAL(clicked(QModelIndex)), SLOT(slotFolderActivated(QModelIndex)));
|
||||
connect(ui->_folderList, SIGNAL(doubleClicked(QModelIndex)),SLOT(slotDoubleClicked(QModelIndex)));
|
||||
|
||||
connect(ui->selectiveSyncApply, SIGNAL(clicked()), _model, SLOT(slotApplySelectiveSync()));
|
||||
connect(ui->selectiveSyncCancel, SIGNAL(clicked()), _model, SLOT(resetFolders()));
|
||||
connect(FolderMan::instance(), SIGNAL(folderListLoaded(Folder::Map)), _model, SLOT(resetFolders()));
|
||||
connect(this, SIGNAL(folderChanged()), _model, SLOT(resetFolders()));
|
||||
|
||||
|
||||
QColor color = palette().highlight().color();
|
||||
ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
|
||||
ui->connectLabel->setWordWrap(true);
|
||||
ui->connectLabel->setOpenExternalLinks(true);
|
||||
ui->quotaLabel->setWordWrap(true);
|
||||
QFont smallFont = ui->quotaInfoLabel->font();
|
||||
smallFont.setPointSize(smallFont.pointSize() * 0.8);
|
||||
ui->quotaInfoLabel->setFont(smallFont);
|
||||
|
||||
_quotaLabel = new QLabel(ui->quotaProgressBar);
|
||||
(new QVBoxLayout(ui->quotaProgressBar))->addWidget(_quotaLabel);
|
||||
|
||||
ui->connectLabel->setText(tr("No account configured."));
|
||||
ui->_buttonAdd->setEnabled(false);
|
||||
|
||||
connect(AccountStateManager::instance(), SIGNAL(accountStateAdded(AccountState*)),
|
||||
this, SLOT(slotAccountStateChanged(AccountState*)));
|
||||
slotAccountStateChanged(AccountStateManager::instance()->accountState());
|
||||
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
connect(folderMan, SIGNAL(folderListLoaded(Folder::Map)),
|
||||
this, SLOT(setFolderList(Folder::Map)));
|
||||
setFolderList(FolderMan::instance()->map());
|
||||
}
|
||||
|
||||
void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QTreeView *tv = ui->_folderList;
|
||||
QModelIndex index = tv->indexAt(pos);
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString alias = _model->data( index, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
if (alias.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
tv->setCurrentIndex(index);
|
||||
bool folderPaused = _model->data( index, FolderStatusDelegate::FolderSyncPaused).toBool();
|
||||
|
||||
QMenu *menu = new QMenu(tv);
|
||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(menu->addAction(tr("Remove folder")), SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotRemoveCurrentFolder()));
|
||||
connect(menu->addAction(folderPaused ? tr("Resume") : tr("Pause")), SIGNAL(triggered(bool)),
|
||||
this, SLOT(slotEnableCurrentFolder()));
|
||||
menu->exec(tv->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
|
||||
void AccountSettings::slotAccountStateChanged(AccountState *newAccountState)
|
||||
{
|
||||
if (_accountState) {
|
||||
|
@ -140,40 +168,16 @@ void AccountSettings::slotAccountStateChanged(AccountState *newAccountState)
|
|||
this, SLOT(slotUpdateQuota(qint64,qint64)));
|
||||
slotUpdateQuota(quotaInfo->lastQuotaTotalBytes(), quotaInfo->lastQuotaUsedBytes());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AccountSettings::slotFolderActivated( const QModelIndex& indx )
|
||||
{
|
||||
bool isValid = indx.isValid();
|
||||
|
||||
bool haveFolders = ui->_folderList->model()->rowCount() > 0;
|
||||
|
||||
ui->_buttonRemove->setEnabled(isValid);
|
||||
if( Theme::instance()->singleSyncFolder() ) {
|
||||
// only one folder synced folder allowed.
|
||||
ui->_buttonAdd->setVisible(!haveFolders);
|
||||
} else {
|
||||
ui->_buttonAdd->setVisible(true);
|
||||
}
|
||||
bool isConnected = _accountState && _accountState->isConnected();
|
||||
ui->_buttonAdd->setEnabled(isConnected);
|
||||
ui->_buttonEnable->setEnabled( isValid );
|
||||
ui->_buttonSelectiveSync->setEnabled(isConnected && isValid);
|
||||
|
||||
if ( isValid ) {
|
||||
bool folderPaused = _model->data( indx, FolderStatusDelegate::FolderSyncPaused).toBool();
|
||||
if ( !folderPaused) {
|
||||
ui->_buttonEnable->setText( tr( "Pause" ) );
|
||||
} else {
|
||||
ui->_buttonEnable->setText( tr( "Resume" ) );
|
||||
}
|
||||
ui->_buttonEnable->setEnabled(isConnected);
|
||||
if (indx.data(FolderStatusDelegate::AddButton).toBool()) {
|
||||
slotAddFolder();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AccountSettings::slotAddFolder()
|
||||
{
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
|
@ -204,13 +208,11 @@ void AccountSettings::slotFolderWizardAccepted()
|
|||
return;
|
||||
|
||||
Folder *f = folderMan->setupFolderFromConfigFile( alias );
|
||||
slotAddFolder( f );
|
||||
folderMan->setSyncEnabled(true);
|
||||
if( f ) {
|
||||
folderMan->slotScheduleAllFolders();
|
||||
emit folderChanged();
|
||||
}
|
||||
slotButtonsSetEnabled();
|
||||
}
|
||||
|
||||
void AccountSettings::slotFolderWizardRejected()
|
||||
|
@ -221,32 +223,6 @@ void AccountSettings::slotFolderWizardRejected()
|
|||
folderMan->slotScheduleAllFolders();
|
||||
}
|
||||
|
||||
void AccountSettings::slotOpenAccountWizard()
|
||||
{
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
topLevelWidget()->close();
|
||||
}
|
||||
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0);
|
||||
}
|
||||
|
||||
void AccountSettings::slotAddFolder( Folder *folder )
|
||||
{
|
||||
if( ! folder || folder->alias().isEmpty() ) return;
|
||||
|
||||
QStandardItem *item = new QStandardItem();
|
||||
folderToModelItem( item, folder, _accountState && _accountState->isConnectedOrMaintenance());
|
||||
_model->appendRow( item );
|
||||
// in order to update the enabled state of the "Sync now" button
|
||||
connect(folder, SIGNAL(syncStateChange()), this, SLOT(slotFolderSyncStateChange()), Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void AccountSettings::slotButtonsSetEnabled()
|
||||
{
|
||||
QModelIndex selected = ui->_folderList->currentIndex();
|
||||
|
||||
slotFolderActivated(selected);
|
||||
}
|
||||
|
||||
void AccountSettings::setGeneralErrors( const QStringList& errors )
|
||||
{
|
||||
_generalErrors = errors;
|
||||
|
@ -339,24 +315,12 @@ void AccountSettings::slotRemoveCurrentFolder()
|
|||
if( ret == QMessageBox::No ) {
|
||||
return;
|
||||
}
|
||||
/* Remove the selected item from the timer hash. */
|
||||
QStandardItem *item = NULL;
|
||||
if( selected.isValid() )
|
||||
item = _model->itemFromIndex(selected);
|
||||
|
||||
if( selected.isValid() && item && _hideProgressTimers.contains(item) ) {
|
||||
QTimer *t = _hideProgressTimers[item];
|
||||
t->stop();
|
||||
_hideProgressTimers.remove(item);
|
||||
delete(t);
|
||||
}
|
||||
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
folderMan->slotRemoveFolder( alias );
|
||||
_model->removeRow(row);
|
||||
|
||||
// single folder fix to show add-button and hide remove-button
|
||||
slotButtonsSetEnabled();
|
||||
|
||||
emit folderChanged();
|
||||
}
|
||||
|
@ -368,6 +332,8 @@ void AccountSettings::slotResetCurrentFolder()
|
|||
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
|
||||
if( selected.isValid() ) {
|
||||
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
if (alias.isEmpty())
|
||||
return;
|
||||
int ret = QMessageBox::question( 0, tr("Confirm Folder Reset"),
|
||||
tr("<p>Do you really want to reset folder <i>%1</i> and rebuild your client database?</p>"
|
||||
"<p><b>Note:</b> This function is designed for maintenance purposes only. "
|
||||
|
@ -385,23 +351,11 @@ void AccountSettings::slotResetCurrentFolder()
|
|||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotSelectiveSync()
|
||||
{
|
||||
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
|
||||
if( selected.isValid() ) {
|
||||
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
Folder *f = folderMan->folder(alias);
|
||||
if (f) {
|
||||
(new SelectiveSyncDialog(AccountManager::instance()->account(), f, this))->open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotDoubleClicked( const QModelIndex& indx )
|
||||
{
|
||||
if( ! indx.isValid() ) return;
|
||||
QString alias = _model->data( indx, FolderStatusDelegate::FolderAliasRole ).toString();
|
||||
if (alias.isEmpty()) return;
|
||||
|
||||
emit openFolderAlias( alias );
|
||||
}
|
||||
|
@ -421,28 +375,7 @@ void AccountSettings::showConnectionLabel( const QString& message, const QString
|
|||
ui->connectLabel->setToolTip(QString());
|
||||
ui->connectLabel->setStyleSheet(errStyle);
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::setFolderList( const Folder::Map &folders )
|
||||
{
|
||||
_model->clear();
|
||||
|
||||
foreach(QTimer *t, _hideProgressTimers) {
|
||||
t->stop();
|
||||
delete t;
|
||||
}
|
||||
_hideProgressTimers.clear();
|
||||
|
||||
foreach( Folder *f, folders ) {
|
||||
slotAddFolder( f );
|
||||
}
|
||||
|
||||
QModelIndex idx = _model->index(0, 0);
|
||||
if (idx.isValid()) {
|
||||
ui->_folderList->setCurrentIndex(idx);
|
||||
}
|
||||
slotButtonsSetEnabled();
|
||||
|
||||
ui->accountStatus->setVisible(!message.isEmpty());
|
||||
}
|
||||
|
||||
void AccountSettings::slotEnableCurrentFolder()
|
||||
|
@ -503,8 +436,6 @@ void AccountSettings::slotEnableCurrentFolder()
|
|||
if( currentlyPaused ) _wasDisabledBefore = true;
|
||||
|
||||
slotUpdateFolderState (f);
|
||||
// set the button text accordingly.
|
||||
slotFolderActivated( selected );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,7 +456,7 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
|
|||
int row = 0;
|
||||
|
||||
if( ! folder ) return;
|
||||
|
||||
#if 0
|
||||
item = _model->item( row );
|
||||
|
||||
while( item ) {
|
||||
|
@ -541,6 +472,7 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
|
|||
} else {
|
||||
// the dialog is not visible.
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AccountSettings::slotOpenOC()
|
||||
|
@ -551,24 +483,7 @@ void AccountSettings::slotOpenOC()
|
|||
|
||||
QStandardItem* AccountSettings::itemForFolder(const QString& folder)
|
||||
{
|
||||
QStandardItem *item = NULL;
|
||||
|
||||
if( folder.isEmpty() ) {
|
||||
return item;
|
||||
}
|
||||
|
||||
int row = 0;
|
||||
|
||||
item = _model->item( row );
|
||||
|
||||
while( item ) {
|
||||
if( item->data( FolderStatusDelegate::FolderAliasRole ) == folder ) {
|
||||
// its the item to update!
|
||||
break;
|
||||
}
|
||||
item = _model->item( ++row );
|
||||
}
|
||||
return item;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString AccountSettings::shortenFilename( const QString& folder, const QString& file ) const
|
||||
|
@ -593,6 +508,7 @@ QString AccountSettings::shortenFilename( const QString& folder, const QString&
|
|||
|
||||
void AccountSettings::slotSetProgress(const QString& folder, const Progress::Info &progress )
|
||||
{
|
||||
#if 0
|
||||
if (!isVisible()) {
|
||||
return; // for https://github.com/owncloud/client/issues/2648#issuecomment-71377909
|
||||
}
|
||||
|
@ -686,10 +602,12 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
|
|||
}
|
||||
overallPercent = qBound(0, overallPercent, 100);
|
||||
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AccountSettings::slotHideProgress()
|
||||
{
|
||||
#if 0
|
||||
QTimer *send_timer = qobject_cast<QTimer*>(this->sender());
|
||||
QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin();
|
||||
while (i != _hideProgressTimers.constEnd()) {
|
||||
|
@ -717,11 +635,12 @@ void AccountSettings::slotHideProgress()
|
|||
}
|
||||
|
||||
send_timer->deleteLater();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AccountSettings::slotFolderSyncStateChange()
|
||||
{
|
||||
slotButtonsSetEnabled();
|
||||
#if 0
|
||||
Folder* folder = qobject_cast<Folder *>(sender());
|
||||
if (!folder) return;
|
||||
|
||||
|
@ -745,12 +664,14 @@ void AccountSettings::slotFolderSyncStateChange()
|
|||
}
|
||||
timer->start(5000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)
|
||||
{
|
||||
if( total > 0 ) {
|
||||
ui->storageGroupBox->setVisible(true);
|
||||
ui->quotaProgressBar->setVisible(true);
|
||||
ui->quotaInfoLabel->setVisible(true);
|
||||
ui->quotaProgressBar->setEnabled(true);
|
||||
|
@ -763,22 +684,12 @@ void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)
|
|||
QString totalStr = Utility::octetsToString(total);
|
||||
double percent = used/(double)total*100;
|
||||
QString percentStr = Utility::compactFormatDouble(percent, 1);
|
||||
ui->quotaLabel->setText(tr("%1 (%3%) of %2 server space in use.").arg(usedStr, totalStr, percentStr));
|
||||
_quotaLabel->setText(tr("%1 (%3%) of %2 server space in use.").arg(usedStr, totalStr, percentStr));
|
||||
} else {
|
||||
ui->quotaProgressBar->setVisible(false);
|
||||
ui->storageGroupBox->setVisible(false);
|
||||
ui->quotaInfoLabel->setVisible(false);
|
||||
ui->quotaLabel->setText(tr("Currently there is no storage usage information available."));
|
||||
}
|
||||
}
|
||||
|
||||
void AccountSettings::slotIgnoreFilesEditor()
|
||||
{
|
||||
if (_ignoreEditor.isNull()) {
|
||||
_ignoreEditor = new IgnoreListEditor(this);
|
||||
_ignoreEditor->setAttribute( Qt::WA_DeleteOnClose, true );
|
||||
_ignoreEditor->open();
|
||||
} else {
|
||||
ownCloudGui::raiseDialog(_ignoreEditor);
|
||||
ui->quotaProgressBar->setMaximum(0);
|
||||
_quotaLabel->setText(tr("Currently there is no storage usage information available."));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,7 +700,6 @@ void AccountSettings::slotAccountStateChanged(int state)
|
|||
AccountPtr account = _accountState->account();
|
||||
QUrl safeUrl(account->url());
|
||||
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
|
||||
slotButtonsSetEnabled();
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
foreach (Folder *folder, folderMan->map().values()) {
|
||||
slotUpdateFolderState(folder);
|
||||
|
@ -815,7 +725,6 @@ void AccountSettings::slotAccountStateChanged(int state)
|
|||
} else {
|
||||
// ownCloud is not yet configured.
|
||||
showConnectionLabel( tr("No %1 connection configured.").arg(Theme::instance()->appNameGUI()) );
|
||||
ui->_buttonAdd->setEnabled( false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -824,4 +733,29 @@ AccountSettings::~AccountSettings()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void AccountSettings::refreshSelectiveSyncStatus()
|
||||
{
|
||||
ui->selectiveSyncApply->setEnabled(_model->isDirty());
|
||||
ui->selectiveSyncCancel->setEnabled(_model->isDirty());
|
||||
bool shouldBeVisible = _model->isDirty();
|
||||
for (int i = 0; !shouldBeVisible && i < _model->rowCount(); ++i) {
|
||||
if (ui->_folderList->isExpanded(_model->index(i)))
|
||||
shouldBeVisible = true;
|
||||
}
|
||||
bool wasVisible = ui->selectiveSyncApply->isVisible();
|
||||
if (wasVisible != shouldBeVisible) {
|
||||
QSize hint = ui->selectiveSyncStatus->sizeHint();
|
||||
if (shouldBeVisible) {
|
||||
ui->selectiveSyncStatus->setMaximumHeight(0);
|
||||
ui->selectiveSyncStatus->setVisible(true);
|
||||
}
|
||||
auto anim = new QPropertyAnimation(ui->selectiveSyncStatus, "maximumHeight", ui->selectiveSyncStatus);
|
||||
anim->setEndValue(shouldBeVisible ? hint.height() : 0);
|
||||
anim->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
if (!shouldBeVisible) {
|
||||
connect(anim, SIGNAL(finished()), ui->selectiveSyncStatus, SLOT(hide()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
|
|
@ -29,6 +29,7 @@ class QModelIndex;
|
|||
class QStandardItem;
|
||||
class QNetworkReply;
|
||||
class QListWidgetItem;
|
||||
class QLabel;
|
||||
|
||||
namespace OCC {
|
||||
|
||||
|
@ -37,9 +38,10 @@ class AccountSettings;
|
|||
}
|
||||
|
||||
class FolderMan;
|
||||
class IgnoreListEditor;
|
||||
|
||||
class Account;
|
||||
class AccountState;
|
||||
class FolderStatusModel;
|
||||
|
||||
class AccountSettings : public QWidget
|
||||
{
|
||||
|
@ -62,27 +64,22 @@ public slots:
|
|||
void slotUpdateFolderState( Folder* );
|
||||
void slotDoubleClicked( const QModelIndex& );
|
||||
void slotSetProgress(const QString& folder, const Progress::Info& progress);
|
||||
void slotButtonsSetEnabled();
|
||||
|
||||
void slotUpdateQuota( qint64,qint64 );
|
||||
void slotIgnoreFilesEditor();
|
||||
void slotAccountStateChanged(int state);
|
||||
|
||||
void setGeneralErrors( const QStringList& errors );
|
||||
void setFolderList( const Folder::Map& );
|
||||
|
||||
protected slots:
|
||||
void slotAddFolder();
|
||||
void slotAddFolder( Folder* );
|
||||
void slotEnableCurrentFolder();
|
||||
void slotSyncCurrentFolderNow();
|
||||
void slotRemoveCurrentFolder();
|
||||
void slotResetCurrentFolder();
|
||||
void slotFolderWizardAccepted();
|
||||
void slotFolderWizardRejected();
|
||||
void slotOpenAccountWizard();
|
||||
void slotHideProgress();
|
||||
void slotSelectiveSync();
|
||||
void refreshSelectiveSyncStatus();
|
||||
|
||||
private:
|
||||
QString shortenFilename( const QString& folder, const QString& file ) const;
|
||||
|
@ -91,16 +88,18 @@ private:
|
|||
void showConnectionLabel( const QString& message, const QString& tooltip = QString() );
|
||||
|
||||
Ui::AccountSettings *ui;
|
||||
QPointer<IgnoreListEditor> _ignoreEditor;
|
||||
QStandardItemModel *_model;
|
||||
|
||||
FolderStatusModel *_model;
|
||||
QUrl _OCUrl;
|
||||
QHash<QStandardItem*, QTimer*> _hideProgressTimers;
|
||||
QStringList _generalErrors;
|
||||
bool _wasDisabledBefore;
|
||||
AccountState *_accountState;
|
||||
QLabel *_quotaLabel;
|
||||
private slots:
|
||||
void slotFolderSyncStateChange();
|
||||
void slotAccountStateChanged(AccountState*);
|
||||
void slotCustomContextMenuRequested(const QPoint&);
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
|
|
@ -6,21 +6,16 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>615</width>
|
||||
<height>422</height>
|
||||
<width>469</width>
|
||||
<height>652</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="syncStatusGroupBox">
|
||||
<property name="title">
|
||||
<string>Account to Synchronize</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="accountStatus" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="SslButton" name="sslButton">
|
||||
|
@ -37,70 +32,45 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="connectLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Connected with <server> as <user></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QListView" name="_folderList"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="_buttonAdd">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Folder...</string>
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="_buttonEnable">
|
||||
<property name="text">
|
||||
<string>Pause</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="_buttonRemove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="_buttonSelectiveSync">
|
||||
<property name="text">
|
||||
<string>Choose What to Sync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="storageGroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Storage Usage</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="quotaProgressBar">
|
||||
<property name="enabled">
|
||||
|
@ -117,17 +87,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="quotaLabel">
|
||||
<property name="text">
|
||||
<string>Retrieving usage information...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="quotaInfoLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><b>Note:</b> Some folders, including network mounted or shared folders, might have different limits.</string>
|
||||
<string>Some folders, including network mounted or shared folders, might have different limits.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
@ -137,26 +106,76 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="maintenanceGroupBox">
|
||||
<property name="title">
|
||||
<string>Account Maintenance</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="ignoredFilesButton">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QTreeView" name="_folderList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>5</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit Ignored Files</string>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="modifyAccountButton">
|
||||
<widget class="QWidget" name="selectiveSyncStatus" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="selectiveSyncCancel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Modify Account</string>
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="selectiveSyncApply">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Unchecked folders will be <b>removed</b> from your local file system and will not be synchronized to this computer anymore</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
*/
|
||||
|
||||
#include "folderstatusmodel.h"
|
||||
#include "folderman.h"
|
||||
#include "utility.h"
|
||||
#include <theme.h>
|
||||
#include <account.h>
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
|
@ -21,17 +24,42 @@
|
|||
#include <QtWidgets>
|
||||
#endif
|
||||
|
||||
Q_DECLARE_METATYPE(QPersistentModelIndex)
|
||||
|
||||
namespace OCC {
|
||||
|
||||
FolderStatusModel::FolderStatusModel()
|
||||
:QStandardItemModel()
|
||||
{
|
||||
static const char propertyParentIndexC[] = "oc_parentIndex";
|
||||
|
||||
FolderStatusModel::FolderStatusModel(QObject *parent)
|
||||
:QAbstractItemModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex& ) const
|
||||
FolderStatusModel::~FolderStatusModel()
|
||||
{ }
|
||||
|
||||
|
||||
void FolderStatusModel::setAccount(const AccountPtr& account)
|
||||
{
|
||||
beginResetModel();
|
||||
_dirty = false;
|
||||
_folders.clear();
|
||||
_account = account;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex &index ) const
|
||||
{
|
||||
switch (classify(index)) {
|
||||
case AddButton:
|
||||
return Qt::ItemIsEnabled;
|
||||
case RootFolder:
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
case SubFolder:
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
|
||||
|
@ -41,9 +69,432 @@ QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
if (role == Qt::EditRole)
|
||||
return QVariant();
|
||||
else
|
||||
return QStandardItemModel::data(index,role);
|
||||
|
||||
switch(classify(index)) {
|
||||
case AddButton:
|
||||
if (role == FolderStatusDelegate::AddButton)
|
||||
return QVariant(true);
|
||||
return QVariant();
|
||||
case SubFolder:
|
||||
{
|
||||
const auto &x = static_cast<SubFolderInfo *>(index.internalPointer())->_subs[index.row()];
|
||||
switch (role) {
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::DisplayRole:
|
||||
return x._name;
|
||||
case Qt::CheckStateRole:
|
||||
return x._checked;
|
||||
case Qt::DecorationRole:
|
||||
return QFileIconProvider().icon(QFileIconProvider::Folder);
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
case RootFolder:
|
||||
break;
|
||||
}
|
||||
|
||||
auto folderList = FolderMan::instance()->map().values();
|
||||
auto f = folderList.at(index.row());
|
||||
if (!f)
|
||||
return QVariant();
|
||||
|
||||
bool accountConnected = true; // FIXME
|
||||
|
||||
switch (role) {
|
||||
case FolderStatusDelegate::FolderPathRole : return f->nativePath();
|
||||
case FolderStatusDelegate::FolderSecondPathRole : return f->remotePath();
|
||||
case FolderStatusDelegate::FolderAliasRole : return f->alias();
|
||||
case FolderStatusDelegate::FolderSyncPaused : return f->syncPaused();
|
||||
case FolderStatusDelegate::FolderAccountConnected : return accountConnected;
|
||||
case Qt::ToolTipRole:
|
||||
return Theme::instance()->statusHeaderText(f->syncResult().status());
|
||||
case FolderStatusDelegate::FolderStatusIconRole:
|
||||
if ( accountConnected ) {
|
||||
auto theme = Theme::instance();
|
||||
auto status = f->syncResult().status();
|
||||
if( f->syncPaused() ) {
|
||||
return theme->folderDisabledIcon( );
|
||||
} else {
|
||||
if( status == SyncResult::SyncPrepare ) {
|
||||
return theme->syncStateIcon(SyncResult::SyncRunning);
|
||||
} else if( status == SyncResult::Undefined ) {
|
||||
return theme->syncStateIcon( SyncResult::SyncRunning);
|
||||
} else {
|
||||
// kepp the previous icon for the prepare phase.
|
||||
if( status == SyncResult::Problem) {
|
||||
return theme->syncStateIcon( SyncResult::Success);
|
||||
} else {
|
||||
return theme->syncStateIcon( status );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Theme::instance()->folderOfflineIcon();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool FolderStatusModel::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if(role == Qt::CheckStateRole) {
|
||||
auto info = infoForIndex(index);
|
||||
Qt::CheckState checked = static_cast<Qt::CheckState>(value.toInt());
|
||||
|
||||
if (info && info->_checked != checked) {
|
||||
info->_checked = checked;
|
||||
if (checked == Qt::Checked) {
|
||||
// If we are checked, check that we may need to check the parent as well if
|
||||
// all the sibilings are also checked
|
||||
QModelIndex parent = index.parent();
|
||||
auto parentInfo = infoForIndex(parent);
|
||||
if (parentInfo && parentInfo->_checked != Qt::Checked) {
|
||||
bool hasUnchecked = false;
|
||||
foreach(const auto &sub, parentInfo->_subs) {
|
||||
if (sub._checked != Qt::Checked) {
|
||||
hasUnchecked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasUnchecked) {
|
||||
setData(parent, Qt::Checked, Qt::CheckStateRole);
|
||||
} else if (parentInfo->_checked == Qt::Unchecked) {
|
||||
setData(parent, Qt::PartiallyChecked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
// also check all the children
|
||||
for (int i = 0; i < info->_subs.count(); ++i) {
|
||||
if (info->_subs[i]._checked != Qt::Checked) {
|
||||
setData(index.child(i, 0), Qt::Checked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checked == Qt::Unchecked) {
|
||||
QModelIndex parent = index.parent();
|
||||
auto parentInfo = infoForIndex(parent);
|
||||
if (parentInfo && parentInfo->_checked == Qt::Checked) {
|
||||
setData(parent, Qt::PartiallyChecked, Qt::CheckStateRole);
|
||||
}
|
||||
|
||||
// Uncheck all the children
|
||||
for (int i = 0; i < info->_subs.count(); ++i) {
|
||||
if (info->_subs[i]._checked != Qt::Unchecked) {
|
||||
setData(index.child(i, 0), Qt::Unchecked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checked == Qt::PartiallyChecked) {
|
||||
QModelIndex parent = index.parent();
|
||||
auto parentInfo = infoForIndex(parent);
|
||||
if (parentInfo && parentInfo->_checked != Qt::PartiallyChecked) {
|
||||
setData(parent, Qt::PartiallyChecked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
_dirty = true;
|
||||
emit dirtyChanged();
|
||||
dataChanged(index, index, QVector<int>() << role);
|
||||
return true;
|
||||
}
|
||||
return QAbstractItemModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
|
||||
int FolderStatusModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int FolderStatusModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
return FolderMan::instance()->map().count() + 1;
|
||||
}
|
||||
|
||||
auto info = infoForIndex(parent);
|
||||
if (!info)
|
||||
return 0;
|
||||
return info->_subs.count();
|
||||
}
|
||||
|
||||
FolderStatusModel::ItemType FolderStatusModel::classify(const QModelIndex& index) const
|
||||
{
|
||||
if (index.internalPointer()) {
|
||||
return SubFolder;
|
||||
}
|
||||
//FIXME:
|
||||
auto folderList = FolderMan::instance()->map(); //.values();
|
||||
if (index.row() < folderList.count()) {
|
||||
return RootFolder;
|
||||
}
|
||||
return AddButton;
|
||||
}
|
||||
|
||||
FolderStatusModel::SubFolderInfo* FolderStatusModel::infoForIndex(const QModelIndex& index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
if (auto parentInfo = index.internalPointer()) {
|
||||
return &static_cast<SubFolderInfo*>(parentInfo)->_subs[index.row()];
|
||||
} else {
|
||||
auto folders = FolderMan::instance()->map(); // FIXME
|
||||
if (index.row() >= folders.count()) {
|
||||
// AddButton
|
||||
return 0;
|
||||
}
|
||||
if (_folders.size() <= index.row()) {
|
||||
_folders.resize(index.row() + 1);
|
||||
}
|
||||
auto info = &_folders[index.row()];
|
||||
if (info->_pathIdx.isEmpty()) {
|
||||
info->_pathIdx << index.row();
|
||||
info->_name = folders.values().at(index.row())->alias();
|
||||
info->_path = "/";
|
||||
info->_folder = folders.values().at(index.row());
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QModelIndex FolderStatusModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
if (!parent.isValid()) {
|
||||
return createIndex(row, column, nullptr);
|
||||
}
|
||||
switch(classify(parent)) {
|
||||
case AddButton: return QModelIndex();
|
||||
case RootFolder:
|
||||
if (_folders.count() <= parent.row())
|
||||
return QModelIndex(); // should not happen
|
||||
return createIndex(row, column, const_cast<SubFolderInfo *>(&_folders[parent.row()]));
|
||||
case SubFolder:
|
||||
//return QModelIndex();
|
||||
if (static_cast<SubFolderInfo*>(parent.internalPointer())->_subs.count() <= parent.row())
|
||||
return QModelIndex(); // should not happen
|
||||
if (static_cast<SubFolderInfo*>(parent.internalPointer())->_subs.at(parent.row())._subs.count() <= row)
|
||||
return QModelIndex(); // should not happen
|
||||
return createIndex(row, column, &static_cast<SubFolderInfo*>(parent.internalPointer())->_subs[parent.row()]);
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex FolderStatusModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
if (!child.isValid()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
switch(classify(child)) {
|
||||
case RootFolder:
|
||||
case AddButton:
|
||||
return QModelIndex();
|
||||
case SubFolder:
|
||||
break;
|
||||
}
|
||||
auto pathIdx = static_cast<SubFolderInfo*>(child.internalPointer())->_subs[child.row()]._pathIdx;
|
||||
int i = 1;
|
||||
Q_ASSERT(pathIdx.at(0) < _folders.count());
|
||||
if (pathIdx.count() == 2) {
|
||||
return createIndex(pathIdx.at(0), 0, nullptr);
|
||||
}
|
||||
|
||||
const SubFolderInfo *info = &_folders[pathIdx.at(0)];
|
||||
while (i < pathIdx.count() - 2) {
|
||||
Q_ASSERT(pathIdx.at(i) < info->_subs.count());
|
||||
info = &info->_subs[pathIdx.at(i)];
|
||||
++i;
|
||||
}
|
||||
return createIndex(pathIdx.at(i), 0, const_cast<SubFolderInfo *>(info));
|
||||
}
|
||||
|
||||
bool FolderStatusModel::hasChildren(const QModelIndex& parent) const
|
||||
{
|
||||
if (!parent.isValid())
|
||||
return true;
|
||||
|
||||
auto info = infoForIndex(parent);
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
if (!info->_fetched)
|
||||
return true;
|
||||
|
||||
if (info->_subs.isEmpty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FolderStatusModel::canFetchMore(const QModelIndex& parent) const
|
||||
{
|
||||
auto info = infoForIndex(parent);
|
||||
if (!info || info->_fetched || info->_fetching)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FolderStatusModel::fetchMore(const QModelIndex& parent)
|
||||
{
|
||||
auto info = infoForIndex(parent);
|
||||
if (!info || info->_fetched || info->_fetching)
|
||||
return;
|
||||
|
||||
info->_fetching = true;
|
||||
LsColJob *job = new LsColJob(_account, info->_folder->remotePath() + "/" + info->_path, this);
|
||||
job->setProperties(QList<QByteArray>() << "resourcetype" << "quota-used-bytes");
|
||||
connect(job, SIGNAL(directoryListingSubfolders(QStringList)),
|
||||
SLOT(slotUpdateDirectories(QStringList)));
|
||||
job->start();
|
||||
job->setProperty(propertyParentIndexC , QVariant::fromValue<QPersistentModelIndex>(parent));
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotUpdateDirectories(const QStringList &list_)
|
||||
{
|
||||
auto job = qobject_cast<LsColJob *>(sender());
|
||||
Q_ASSERT(job);
|
||||
QModelIndex idx = qvariant_cast<QPersistentModelIndex>(job->property(propertyParentIndexC));
|
||||
if (!idx.isValid()) {
|
||||
return;
|
||||
}
|
||||
auto parentInfo = infoForIndex(idx);
|
||||
|
||||
auto list = list_;
|
||||
list.removeFirst(); // remove the parent item
|
||||
|
||||
beginInsertRows(idx, 0, list.count());
|
||||
|
||||
QUrl url = parentInfo->_folder->remoteUrl();
|
||||
QString pathToRemove = url.path();
|
||||
if (!pathToRemove.endsWith('/'))
|
||||
pathToRemove += '/';
|
||||
|
||||
parentInfo->_fetched = true;
|
||||
parentInfo->_fetching = false;
|
||||
|
||||
int i = 0;
|
||||
foreach (QString path, list) {
|
||||
SubFolderInfo newInfo;
|
||||
newInfo._folder = parentInfo->_folder;
|
||||
newInfo._pathIdx = parentInfo->_pathIdx;
|
||||
newInfo._pathIdx << i++;
|
||||
auto size = job ? job->_sizes.value(path) : 0;
|
||||
newInfo._size = size;
|
||||
path.remove(pathToRemove);
|
||||
newInfo._path = path;
|
||||
newInfo._name = path.split('/', QString::SkipEmptyParts).last();
|
||||
|
||||
if (path.isEmpty())
|
||||
continue;
|
||||
|
||||
if (parentInfo->_checked == Qt::Unchecked) {
|
||||
newInfo._checked = Qt::Unchecked;
|
||||
} else {
|
||||
auto *f = FolderMan::instance()->map().values().at(parentInfo->_pathIdx.first());
|
||||
foreach(const QString &str , f->selectiveSyncBlackList()) {
|
||||
if (str == path || str == QLatin1String("/")) {
|
||||
newInfo._checked = Qt::Unchecked;
|
||||
break;
|
||||
} else if (str.startsWith(path)) {
|
||||
newInfo._checked = Qt::PartiallyChecked;
|
||||
}
|
||||
}
|
||||
}
|
||||
parentInfo->_subs.append(newInfo);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
/*void SelectiveSyncTreeView::slotLscolFinishedWithError(QNetworkReply *r)
|
||||
{
|
||||
if (r->error() == QNetworkReply::ContentNotFoundError) {
|
||||
_loading->setText(tr("No subfolders currently on the server."));
|
||||
} else {
|
||||
_loading->setText(tr("An error occured while loading the list of sub folders."));
|
||||
}
|
||||
_loading->resize(_loading->sizeHint()); // because it's not in a layout
|
||||
}*/
|
||||
|
||||
QStringList FolderStatusModel::createBlackList(FolderStatusModel::SubFolderInfo *root,
|
||||
const QStringList &oldBlackList) const
|
||||
{
|
||||
if (!root) return QStringList();
|
||||
|
||||
switch(root->_checked) {
|
||||
case Qt::Unchecked:
|
||||
return QStringList(root->_path);
|
||||
case Qt::Checked:
|
||||
return QStringList();
|
||||
case Qt::PartiallyChecked:
|
||||
break;
|
||||
}
|
||||
|
||||
QStringList result;
|
||||
if (root->_fetched) {
|
||||
for (int i = 0; i < root->_subs.count(); ++i) {
|
||||
result += createBlackList(&root->_subs[i], oldBlackList);
|
||||
}
|
||||
} else {
|
||||
// We did not load from the server so we re-use the one from the old black list
|
||||
QString path = root->_path;
|
||||
foreach (const QString & it, oldBlackList) {
|
||||
if (it.startsWith(path))
|
||||
result += it;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FolderStatusModel::slotApplySelectiveSync()
|
||||
{
|
||||
if (!_dirty)
|
||||
return;
|
||||
auto folderList = FolderMan::instance()->map().values(); //FIXME
|
||||
|
||||
for (int i = 0; i < folderList.count(); ++i) {
|
||||
if (i >= _folders.count()) break;
|
||||
if (!_folders[i]._fetched) continue;
|
||||
auto folder = folderList.at(i);
|
||||
|
||||
auto oldBlackList = folder->selectiveSyncBlackList();
|
||||
QStringList blackList = createBlackList(&_folders[i], oldBlackList);
|
||||
folder->setSelectiveSyncBlackList(blackList);
|
||||
|
||||
// FIXME: Use ConfigFile
|
||||
QSettings settings(folder->configFile(), QSettings::IniFormat);
|
||||
settings.beginGroup(FolderMan::escapeAlias(folder->alias()));
|
||||
settings.setValue("blackList", blackList);
|
||||
FolderMan *folderMan = FolderMan::instance();
|
||||
auto blackListSet = blackList.toSet();
|
||||
auto oldBlackListSet = oldBlackList.toSet();
|
||||
auto changes = (oldBlackListSet - blackListSet) + (blackListSet - oldBlackListSet);
|
||||
if (!changes.isEmpty()) {
|
||||
if (folder->isBusy()) {
|
||||
folder->slotTerminateSync();
|
||||
}
|
||||
//The part that changed should not be read from the DB on next sync because there might be new folders
|
||||
// (the ones that are no longer in the blacklist)
|
||||
foreach(const auto &it, changes) {
|
||||
folder->journalDb()->avoidReadFromDbOnNextSync(it);
|
||||
}
|
||||
folderMan->slotScheduleSync(folder->alias());
|
||||
}
|
||||
}
|
||||
|
||||
resetFolders();
|
||||
}
|
||||
|
||||
|
||||
void FolderStatusModel::resetFolders()
|
||||
{
|
||||
setAccount(_account);
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================
|
||||
|
||||
|
@ -62,6 +513,12 @@ FolderStatusDelegate::~FolderStatusDelegate()
|
|||
QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
|
||||
const QModelIndex & index) const
|
||||
{
|
||||
|
||||
if (static_cast<const FolderStatusModel *>(index.model())->classify(index) != FolderStatusModel::RootFolder) {
|
||||
return QStyledItemDelegate::sizeHint(option, index);
|
||||
}
|
||||
|
||||
|
||||
Q_UNUSED(option)
|
||||
QFont aliasFont = option.font;
|
||||
QFont font = option.font;
|
||||
|
@ -101,8 +558,17 @@ QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
|
|||
void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (qvariant_cast<bool>(index.data(AddButton))) {
|
||||
painter->drawText(option.rect, "[+ Add Folder]");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QStyledItemDelegate::paint(painter,option,index);
|
||||
|
||||
if (static_cast<const FolderStatusModel *>(index.model())->classify(index) != FolderStatusModel::RootFolder) {
|
||||
return;
|
||||
}
|
||||
painter->save();
|
||||
|
||||
QFont aliasFont = option.font;
|
||||
|
@ -141,7 +607,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
|||
QRect iconRect = option.rect;
|
||||
QRect aliasRect = option.rect;
|
||||
|
||||
iconRect.setLeft( aliasMargin );
|
||||
iconRect.setLeft( option.rect.left() + aliasMargin );
|
||||
iconRect.setTop( iconRect.top() + aliasMargin ); // (iconRect.height()-iconsize.height())/2);
|
||||
|
||||
// alias box
|
||||
|
@ -313,11 +779,14 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
|
|||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
bool FolderStatusDelegate::editorEvent ( QEvent * /*event*/, QAbstractItemModel * /*model*/, const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/ )
|
||||
bool FolderStatusDelegate::editorEvent ( QEvent * event, QAbstractItemModel * model,
|
||||
const QStyleOptionViewItem & option, const QModelIndex & index )
|
||||
{
|
||||
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,16 +17,72 @@
|
|||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QStandardItemModel>
|
||||
#include <accountfwd.h>
|
||||
|
||||
#ifndef Q_DECL_OVERRIDE
|
||||
#define Q_DECL_OVERRIDE
|
||||
#endif
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class FolderStatusModel : public QStandardItemModel
|
||||
{
|
||||
public:
|
||||
FolderStatusModel();
|
||||
virtual Qt::ItemFlags flags( const QModelIndex& ) const Q_DECL_OVERRIDE;
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
class Folder;
|
||||
|
||||
class FolderStatusModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FolderStatusModel(QObject * parent = 0);
|
||||
~FolderStatusModel();
|
||||
void setAccount(const OCC::AccountPtr& account);
|
||||
|
||||
Qt::ItemFlags flags( const QModelIndex& ) const Q_DECL_OVERRIDE;
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
QModelIndex parent(const QModelIndex& child) const Q_DECL_OVERRIDE;
|
||||
bool canFetchMore(const QModelIndex& parent) const Q_DECL_OVERRIDE;
|
||||
void fetchMore(const QModelIndex& parent) Q_DECL_OVERRIDE;
|
||||
bool hasChildren(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
|
||||
|
||||
struct SubFolderInfo {
|
||||
// QWeakPointer<SubFolderInfo> parent;
|
||||
QString _name;
|
||||
QString _path;
|
||||
QVector<int> _pathIdx;
|
||||
int _size = 0;
|
||||
bool _fetched = false; // If we did the LSCOL for this folder already
|
||||
bool _fetching = false;
|
||||
QVector<SubFolderInfo> _subs;
|
||||
Qt::CheckState _checked = Qt::Checked;
|
||||
Folder *_folder;
|
||||
};
|
||||
|
||||
mutable QVector<SubFolderInfo> _folders;
|
||||
|
||||
enum ItemType { RootFolder, SubFolder, AddButton, SelectiveSyncText };
|
||||
ItemType classify(const QModelIndex &index) const;
|
||||
SubFolderInfo *infoForIndex(const QModelIndex &index) const;
|
||||
|
||||
bool isDirty() { return _dirty; }
|
||||
|
||||
public slots:
|
||||
void slotApplySelectiveSync();
|
||||
void resetFolders();
|
||||
|
||||
private slots:
|
||||
void slotUpdateDirectories(const QStringList &);
|
||||
|
||||
private:
|
||||
QStringList createBlackList(OCC::FolderStatusModel::SubFolderInfo* root,
|
||||
const QStringList& oldBlackList) const;
|
||||
AccountPtr _account;
|
||||
bool _dirty = false;
|
||||
|
||||
signals:
|
||||
void dirtyChanged();
|
||||
};
|
||||
|
||||
class FolderStatusDelegate : public QStyledItemDelegate
|
||||
|
@ -51,7 +107,9 @@ class FolderStatusDelegate : public QStyledItemDelegate
|
|||
SyncProgressItemString,
|
||||
AddProgressSpace,
|
||||
WarningCount,
|
||||
SyncRunning
|
||||
SyncRunning,
|
||||
|
||||
AddButton
|
||||
};
|
||||
void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const Q_DECL_OVERRIDE;
|
||||
QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const Q_DECL_OVERRIDE;
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
#include "application.h"
|
||||
#include "utility.h"
|
||||
#include "configfile.h"
|
||||
#include "owncloudsetupwizard.h"
|
||||
|
||||
|
||||
#include "updater/updater.h"
|
||||
#include "updater/ocupdater.h"
|
||||
#include "ignorelisteditor.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
@ -68,6 +71,9 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
|
|||
QString themeDir = QString::fromLatin1(":/client/theme/%1/")
|
||||
.arg(Theme::instance()->systrayIconFlavor(true));
|
||||
_ui->monoIconsCheckBox->setVisible(QDir(themeDir).exists());
|
||||
|
||||
connect(_ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));
|
||||
connect(_ui->addAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard()));
|
||||
}
|
||||
|
||||
GeneralSettings::~GeneralSettings()
|
||||
|
@ -119,4 +125,24 @@ void GeneralSettings::slotToggleOptionalDesktopNotifications(bool enable)
|
|||
cfgFile.setOptionalDesktopNotifications(enable);
|
||||
}
|
||||
|
||||
void GeneralSettings::slotIgnoreFilesEditor()
|
||||
{
|
||||
if (_ignoreEditor.isNull()) {
|
||||
_ignoreEditor = new IgnoreListEditor(this);
|
||||
_ignoreEditor->setAttribute( Qt::WA_DeleteOnClose, true );
|
||||
_ignoreEditor->open();
|
||||
} else {
|
||||
ownCloudGui::raiseDialog(_ignoreEditor);
|
||||
}
|
||||
}
|
||||
|
||||
void GeneralSettings::slotOpenAccountWizard()
|
||||
{
|
||||
if (QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
topLevelWidget()->close();
|
||||
}
|
||||
OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace OCC
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
#define MIRALL_GENERALSETTINGS_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
namespace OCC {
|
||||
class IgnoreListEditor;
|
||||
|
||||
namespace Ui {
|
||||
class GeneralSettings;
|
||||
|
@ -36,11 +37,15 @@ private slots:
|
|||
void slotToggleLaunchOnStartup(bool);
|
||||
void slotToggleOptionalDesktopNotifications(bool);
|
||||
void slotUpdateInfo();
|
||||
void slotIgnoreFilesEditor();
|
||||
void slotOpenAccountWizard();
|
||||
|
||||
|
||||
private:
|
||||
void loadMiscSettings();
|
||||
|
||||
Ui::GeneralSettings *_ui;
|
||||
QPointer<IgnoreListEditor> _ignoreEditor;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>468</width>
|
||||
<height>249</height>
|
||||
<width>599</width>
|
||||
<height>429</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -41,13 +41,76 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="ignoredFilesButton">
|
||||
<property name="text">
|
||||
<string>Edit Ignored Files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="crashreporterCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show crash reporter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="addAccountButton">
|
||||
<property name="text">
|
||||
<string>Add an Account</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -410,7 +410,5 @@ qint64 SelectiveSyncDialog::estimatedSize()
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue