Settings: New UI that intergate the selective sync within the account settings

This commit is contained in:
Olivier Goffart 2015-03-27 11:46:03 +01:00
parent dfd9d8725c
commit 426d2338d9
9 changed files with 864 additions and 293 deletions

View file

@ -21,13 +21,10 @@
#include "folderstatusmodel.h" #include "folderstatusmodel.h"
#include "utility.h" #include "utility.h"
#include "application.h" #include "application.h"
#include "owncloudsetupwizard.h"
#include "configfile.h" #include "configfile.h"
#include "ignorelisteditor.h"
#include "account.h" #include "account.h"
#include "accountstate.h" #include "accountstate.h"
#include "quotainfo.h" #include "quotainfo.h"
#include "selectivesyncdialog.h"
#include "creds/abstractcredentials.h" #include "creds/abstractcredentials.h"
#include <math.h> #include <math.h>
@ -37,9 +34,13 @@
#include <QListWidgetItem> #include <QListWidgetItem>
#include <QMessageBox> #include <QMessageBox>
#include <QAction> #include <QAction>
#include <QVBoxLayout>
#include <QTreeView>
#include <QKeySequence> #include <QKeySequence>
#include <QIcon> #include <QIcon>
#include <QVariant> #include <QVariant>
#include <qstringlistmodel.h>
#include <qpropertyanimation.h>
#include "account.h" #include "account.h"
@ -64,10 +65,12 @@ AccountSettings::AccountSettings(QWidget *parent) :
ui->setupUi(this); ui->setupUi(this);
_model = new FolderStatusModel; _model = new FolderStatusModel;
_model->setAccount(_accountState->account());
_model->setParent(this); _model->setParent(this);
FolderStatusDelegate *delegate = new FolderStatusDelegate; FolderStatusDelegate *delegate = new FolderStatusDelegate;
delegate->setParent(this); delegate->setParent(this);
ui->_folderList->header()->hide();
ui->_folderList->setItemDelegate( delegate ); ui->_folderList->setItemDelegate( delegate );
ui->_folderList->setModel( _model ); ui->_folderList->setModel( _model );
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
@ -75,12 +78,13 @@ AccountSettings::AccountSettings(QWidget *parent) :
#else #else
ui->_folderList->setMinimumWidth( 300 ); ui->_folderList->setMinimumWidth( 300 );
#endif #endif
ui->_folderList->setEditTriggers( QAbstractItemView::NoEditTriggers ); connect(ui->_folderList, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(slotCustomContextMenuRequested(QPoint)));
ui->_buttonRemove->setEnabled(false); connect(ui->_folderList, SIGNAL(expanded(QModelIndex)) , this, SLOT(refreshSelectiveSyncStatus()));
ui->_buttonEnable->setEnabled(false); connect(ui->_folderList, SIGNAL(collapsed(QModelIndex)) , this, SLOT(refreshSelectiveSyncStatus()));
ui->_buttonSelectiveSync->setEnabled(false); connect(_model, SIGNAL(dirtyChanged()), this, SLOT(refreshSelectiveSyncStatus()));
ui->_buttonAdd->setEnabled(true); ui->selectiveSyncStatus->hide();
QAction *resetFolderAction = new QAction(this); QAction *resetFolderAction = new QAction(this);
resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5)); resetFolderAction->setShortcut(QKeySequence(Qt::Key_F5));
@ -92,35 +96,59 @@ AccountSettings::AccountSettings(QWidget *parent) :
connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow())); connect(syncNowAction, SIGNAL(triggered()), SLOT(slotSyncCurrentFolderNow()));
addAction(syncNowAction); 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(clicked(QModelIndex)), SLOT(slotFolderActivated(QModelIndex)));
connect(ui->_folderList, SIGNAL(doubleClicked(QModelIndex)),SLOT(slotDoubleClicked(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(); QColor color = palette().highlight().color();
ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name())); ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
ui->connectLabel->setWordWrap(true); ui->connectLabel->setWordWrap(true);
ui->connectLabel->setOpenExternalLinks(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->connectLabel->setText(tr("No account configured."));
ui->_buttonAdd->setEnabled(false);
connect(AccountStateManager::instance(), SIGNAL(accountStateAdded(AccountState*)), connect(AccountStateManager::instance(), SIGNAL(accountStateAdded(AccountState*)),
this, SLOT(slotAccountStateChanged(AccountState*))); this, SLOT(slotAccountStateChanged(AccountState*)));
slotAccountStateChanged(AccountStateManager::instance()->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) void AccountSettings::slotAccountStateChanged(AccountState *newAccountState)
{ {
if (_accountState) { if (_accountState) {
@ -140,40 +168,16 @@ void AccountSettings::slotAccountStateChanged(AccountState *newAccountState)
this, SLOT(slotUpdateQuota(qint64,qint64))); this, SLOT(slotUpdateQuota(qint64,qint64)));
slotUpdateQuota(quotaInfo->lastQuotaTotalBytes(), quotaInfo->lastQuotaUsedBytes()); slotUpdateQuota(quotaInfo->lastQuotaTotalBytes(), quotaInfo->lastQuotaUsedBytes());
} }
} }
void AccountSettings::slotFolderActivated( const QModelIndex& indx ) void AccountSettings::slotFolderActivated( const QModelIndex& indx )
{ {
bool isValid = indx.isValid(); if (indx.data(FolderStatusDelegate::AddButton).toBool()) {
slotAddFolder();
bool haveFolders = ui->_folderList->model()->rowCount() > 0; return;
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);
} }
} }
void AccountSettings::slotAddFolder() void AccountSettings::slotAddFolder()
{ {
FolderMan *folderMan = FolderMan::instance(); FolderMan *folderMan = FolderMan::instance();
@ -204,13 +208,11 @@ void AccountSettings::slotFolderWizardAccepted()
return; return;
Folder *f = folderMan->setupFolderFromConfigFile( alias ); Folder *f = folderMan->setupFolderFromConfigFile( alias );
slotAddFolder( f );
folderMan->setSyncEnabled(true); folderMan->setSyncEnabled(true);
if( f ) { if( f ) {
folderMan->slotScheduleAllFolders(); folderMan->slotScheduleAllFolders();
emit folderChanged(); emit folderChanged();
} }
slotButtonsSetEnabled();
} }
void AccountSettings::slotFolderWizardRejected() void AccountSettings::slotFolderWizardRejected()
@ -221,32 +223,6 @@ void AccountSettings::slotFolderWizardRejected()
folderMan->slotScheduleAllFolders(); 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 ) void AccountSettings::setGeneralErrors( const QStringList& errors )
{ {
_generalErrors = errors; _generalErrors = errors;
@ -339,24 +315,12 @@ void AccountSettings::slotRemoveCurrentFolder()
if( ret == QMessageBox::No ) { if( ret == QMessageBox::No ) {
return; 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 *folderMan = FolderMan::instance();
folderMan->slotRemoveFolder( alias ); folderMan->slotRemoveFolder( alias );
_model->removeRow(row); _model->removeRow(row);
// single folder fix to show add-button and hide remove-button // single folder fix to show add-button and hide remove-button
slotButtonsSetEnabled();
emit folderChanged(); emit folderChanged();
} }
@ -368,6 +332,8 @@ void AccountSettings::slotResetCurrentFolder()
QModelIndex selected = ui->_folderList->selectionModel()->currentIndex(); QModelIndex selected = ui->_folderList->selectionModel()->currentIndex();
if( selected.isValid() ) { if( selected.isValid() ) {
QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString(); QString alias = _model->data( selected, FolderStatusDelegate::FolderAliasRole ).toString();
if (alias.isEmpty())
return;
int ret = QMessageBox::question( 0, tr("Confirm Folder Reset"), 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>" 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. " "<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 ) void AccountSettings::slotDoubleClicked( const QModelIndex& indx )
{ {
if( ! indx.isValid() ) return; if( ! indx.isValid() ) return;
QString alias = _model->data( indx, FolderStatusDelegate::FolderAliasRole ).toString(); QString alias = _model->data( indx, FolderStatusDelegate::FolderAliasRole ).toString();
if (alias.isEmpty()) return;
emit openFolderAlias( alias ); emit openFolderAlias( alias );
} }
@ -421,28 +375,7 @@ void AccountSettings::showConnectionLabel( const QString& message, const QString
ui->connectLabel->setToolTip(QString()); ui->connectLabel->setToolTip(QString());
ui->connectLabel->setStyleSheet(errStyle); ui->connectLabel->setStyleSheet(errStyle);
} }
} ui->accountStatus->setVisible(!message.isEmpty());
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();
} }
void AccountSettings::slotEnableCurrentFolder() void AccountSettings::slotEnableCurrentFolder()
@ -503,8 +436,6 @@ void AccountSettings::slotEnableCurrentFolder()
if( currentlyPaused ) _wasDisabledBefore = true; if( currentlyPaused ) _wasDisabledBefore = true;
slotUpdateFolderState (f); slotUpdateFolderState (f);
// set the button text accordingly.
slotFolderActivated( selected );
} }
} }
@ -525,7 +456,7 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
int row = 0; int row = 0;
if( ! folder ) return; if( ! folder ) return;
#if 0
item = _model->item( row ); item = _model->item( row );
while( item ) { while( item ) {
@ -541,6 +472,7 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
} else { } else {
// the dialog is not visible. // the dialog is not visible.
} }
#endif
} }
void AccountSettings::slotOpenOC() void AccountSettings::slotOpenOC()
@ -551,24 +483,7 @@ void AccountSettings::slotOpenOC()
QStandardItem* AccountSettings::itemForFolder(const QString& folder) QStandardItem* AccountSettings::itemForFolder(const QString& folder)
{ {
QStandardItem *item = NULL; return nullptr;
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;
} }
QString AccountSettings::shortenFilename( const QString& folder, const QString& file ) const 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 ) void AccountSettings::slotSetProgress(const QString& folder, const Progress::Info &progress )
{ {
#if 0
if (!isVisible()) { if (!isVisible()) {
return; // for https://github.com/owncloud/client/issues/2648#issuecomment-71377909 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); overallPercent = qBound(0, overallPercent, 100);
item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent); item->setData( overallPercent, FolderStatusDelegate::SyncProgressOverallPercent);
#endif
} }
void AccountSettings::slotHideProgress() void AccountSettings::slotHideProgress()
{ {
#if 0
QTimer *send_timer = qobject_cast<QTimer*>(this->sender()); QTimer *send_timer = qobject_cast<QTimer*>(this->sender());
QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin(); QHash<QStandardItem*, QTimer*>::const_iterator i = _hideProgressTimers.constBegin();
while (i != _hideProgressTimers.constEnd()) { while (i != _hideProgressTimers.constEnd()) {
@ -717,11 +635,12 @@ void AccountSettings::slotHideProgress()
} }
send_timer->deleteLater(); send_timer->deleteLater();
#endif
} }
void AccountSettings::slotFolderSyncStateChange() void AccountSettings::slotFolderSyncStateChange()
{ {
slotButtonsSetEnabled(); #if 0
Folder* folder = qobject_cast<Folder *>(sender()); Folder* folder = qobject_cast<Folder *>(sender());
if (!folder) return; if (!folder) return;
@ -745,12 +664,14 @@ void AccountSettings::slotFolderSyncStateChange()
} }
timer->start(5000); timer->start(5000);
} }
#endif
} }
void AccountSettings::slotUpdateQuota(qint64 total, qint64 used) void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)
{ {
if( total > 0 ) { if( total > 0 ) {
ui->storageGroupBox->setVisible(true);
ui->quotaProgressBar->setVisible(true); ui->quotaProgressBar->setVisible(true);
ui->quotaInfoLabel->setVisible(true); ui->quotaInfoLabel->setVisible(true);
ui->quotaProgressBar->setEnabled(true); ui->quotaProgressBar->setEnabled(true);
@ -763,22 +684,12 @@ void AccountSettings::slotUpdateQuota(qint64 total, qint64 used)
QString totalStr = Utility::octetsToString(total); QString totalStr = Utility::octetsToString(total);
double percent = used/(double)total*100; double percent = used/(double)total*100;
QString percentStr = Utility::compactFormatDouble(percent, 1); 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 { } else {
ui->quotaProgressBar->setVisible(false); ui->storageGroupBox->setVisible(false);
ui->quotaInfoLabel->setVisible(false); ui->quotaInfoLabel->setVisible(false);
ui->quotaLabel->setText(tr("Currently there is no storage usage information available.")); ui->quotaProgressBar->setMaximum(0);
} _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);
} }
} }
@ -789,7 +700,6 @@ void AccountSettings::slotAccountStateChanged(int state)
AccountPtr account = _accountState->account(); AccountPtr account = _accountState->account();
QUrl safeUrl(account->url()); QUrl safeUrl(account->url());
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
slotButtonsSetEnabled();
FolderMan *folderMan = FolderMan::instance(); FolderMan *folderMan = FolderMan::instance();
foreach (Folder *folder, folderMan->map().values()) { foreach (Folder *folder, folderMan->map().values()) {
slotUpdateFolderState(folder); slotUpdateFolderState(folder);
@ -815,7 +725,6 @@ void AccountSettings::slotAccountStateChanged(int state)
} else { } else {
// ownCloud is not yet configured. // ownCloud is not yet configured.
showConnectionLabel( tr("No %1 connection configured.").arg(Theme::instance()->appNameGUI()) ); showConnectionLabel( tr("No %1 connection configured.").arg(Theme::instance()->appNameGUI()) );
ui->_buttonAdd->setEnabled( false);
} }
} }
@ -824,4 +733,29 @@ AccountSettings::~AccountSettings()
delete ui; 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 } // namespace OCC

View file

@ -29,6 +29,7 @@ class QModelIndex;
class QStandardItem; class QStandardItem;
class QNetworkReply; class QNetworkReply;
class QListWidgetItem; class QListWidgetItem;
class QLabel;
namespace OCC { namespace OCC {
@ -37,9 +38,10 @@ class AccountSettings;
} }
class FolderMan; class FolderMan;
class IgnoreListEditor;
class Account; class Account;
class AccountState; class AccountState;
class FolderStatusModel;
class AccountSettings : public QWidget class AccountSettings : public QWidget
{ {
@ -62,27 +64,22 @@ public slots:
void slotUpdateFolderState( Folder* ); void slotUpdateFolderState( Folder* );
void slotDoubleClicked( const QModelIndex& ); void slotDoubleClicked( const QModelIndex& );
void slotSetProgress(const QString& folder, const Progress::Info& progress); void slotSetProgress(const QString& folder, const Progress::Info& progress);
void slotButtonsSetEnabled();
void slotUpdateQuota( qint64,qint64 ); void slotUpdateQuota( qint64,qint64 );
void slotIgnoreFilesEditor();
void slotAccountStateChanged(int state); void slotAccountStateChanged(int state);
void setGeneralErrors( const QStringList& errors ); void setGeneralErrors( const QStringList& errors );
void setFolderList( const Folder::Map& );
protected slots: protected slots:
void slotAddFolder(); void slotAddFolder();
void slotAddFolder( Folder* );
void slotEnableCurrentFolder(); void slotEnableCurrentFolder();
void slotSyncCurrentFolderNow(); void slotSyncCurrentFolderNow();
void slotRemoveCurrentFolder(); void slotRemoveCurrentFolder();
void slotResetCurrentFolder(); void slotResetCurrentFolder();
void slotFolderWizardAccepted(); void slotFolderWizardAccepted();
void slotFolderWizardRejected(); void slotFolderWizardRejected();
void slotOpenAccountWizard();
void slotHideProgress(); void slotHideProgress();
void slotSelectiveSync(); void refreshSelectiveSyncStatus();
private: private:
QString shortenFilename( const QString& folder, const QString& file ) const; QString shortenFilename( const QString& folder, const QString& file ) const;
@ -91,16 +88,18 @@ private:
void showConnectionLabel( const QString& message, const QString& tooltip = QString() ); void showConnectionLabel( const QString& message, const QString& tooltip = QString() );
Ui::AccountSettings *ui; Ui::AccountSettings *ui;
QPointer<IgnoreListEditor> _ignoreEditor;
QStandardItemModel *_model; FolderStatusModel *_model;
QUrl _OCUrl; QUrl _OCUrl;
QHash<QStandardItem*, QTimer*> _hideProgressTimers; QHash<QStandardItem*, QTimer*> _hideProgressTimers;
QStringList _generalErrors; QStringList _generalErrors;
bool _wasDisabledBefore; bool _wasDisabledBefore;
AccountState *_accountState; AccountState *_accountState;
QLabel *_quotaLabel;
private slots: private slots:
void slotFolderSyncStateChange(); void slotFolderSyncStateChange();
void slotAccountStateChanged(AccountState*); void slotAccountStateChanged(AccountState*);
void slotCustomContextMenuRequested(const QPoint&);
}; };
} // namespace OCC } // namespace OCC

View file

@ -6,21 +6,16 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>615</width> <width>469</width>
<height>422</height> <height>652</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QVBoxLayout" name="verticalLayout">
<item row="0" column="0" colspan="2"> <item>
<widget class="QGroupBox" name="syncStatusGroupBox"> <widget class="QWidget" name="accountStatus" native="true">
<property name="title">
<string>Account to Synchronize</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="SslButton" name="sslButton"> <widget class="SslButton" name="sslButton">
@ -37,70 +32,45 @@
</item> </item>
<item> <item>
<widget class="QLabel" name="connectLabel"> <widget class="QLabel" name="connectLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Connected with &lt;server&gt; as &lt;user&gt;</string> <string>Connected with &lt;server&gt; as &lt;user&gt;</string>
</property> </property>
</widget> </widget>
</item> </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> <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"> <property name="text">
<string>Add Folder...</string> <string>Delete</string>
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item>
<widget class="QGroupBox" name="storageGroupBox"> <widget class="QGroupBox" name="storageGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title"> <property name="title">
<string>Storage Usage</string> <string>Storage Usage</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QProgressBar" name="quotaProgressBar"> <widget class="QProgressBar" name="quotaProgressBar">
<property name="enabled"> <property name="enabled">
@ -117,17 +87,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="quotaLabel">
<property name="text">
<string>Retrieving usage information...</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="quotaInfoLabel"> <widget class="QLabel" name="quotaInfoLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>&lt;b&gt;Note:&lt;/b&gt; 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>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -137,26 +106,76 @@
</layout> </layout>
</widget> </widget>
</item> </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> <item>
<widget class="QPushButton" name="ignoredFilesButton"> <widget class="QTreeView" name="_folderList">
<property name="enabled"> <property name="sizePolicy">
<bool>true</bool> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>5</verstretch>
</sizepolicy>
</property> </property>
<property name="text"> <property name="contextMenuPolicy">
<string>Edit Ignored Files</string> <enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="animated">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<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"> <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 &lt;b&gt;removed&lt;/b&gt; from your local file system and will not be synchronized to this computer anymore</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>

View file

@ -13,7 +13,10 @@
*/ */
#include "folderstatusmodel.h" #include "folderstatusmodel.h"
#include "folderman.h"
#include "utility.h" #include "utility.h"
#include <theme.h>
#include <account.h>
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -21,17 +24,42 @@
#include <QtWidgets> #include <QtWidgets>
#endif #endif
Q_DECLARE_METATYPE(QPersistentModelIndex)
namespace OCC { namespace OCC {
FolderStatusModel::FolderStatusModel() static const char propertyParentIndexC[] = "oc_parentIndex";
:QStandardItemModel()
{
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; 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 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) if (role == Qt::EditRole)
return QVariant(); 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 , QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
const QModelIndex & index) const const QModelIndex & index) const
{ {
if (static_cast<const FolderStatusModel *>(index.model())->classify(index) != FolderStatusModel::RootFolder) {
return QStyledItemDelegate::sizeHint(option, index);
}
Q_UNUSED(option) Q_UNUSED(option)
QFont aliasFont = option.font; QFont aliasFont = option.font;
QFont font = option.font; QFont font = option.font;
@ -101,8 +558,17 @@ QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem & option ,
void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const const QModelIndex &index) const
{ {
if (qvariant_cast<bool>(index.data(AddButton))) {
painter->drawText(option.rect, "[+ Add Folder]");
return;
}
QStyledItemDelegate::paint(painter,option,index); QStyledItemDelegate::paint(painter,option,index);
if (static_cast<const FolderStatusModel *>(index.model())->classify(index) != FolderStatusModel::RootFolder) {
return;
}
painter->save(); painter->save();
QFont aliasFont = option.font; QFont aliasFont = option.font;
@ -141,7 +607,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
QRect iconRect = option.rect; QRect iconRect = option.rect;
QRect aliasRect = 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); iconRect.setTop( iconRect.top() + aliasMargin ); // (iconRect.height()-iconsize.height())/2);
// alias box // alias box
@ -313,11 +779,14 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
painter->restore(); painter->restore();
} }
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; return false;
} }

View file

@ -17,16 +17,72 @@
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <accountfwd.h>
#ifndef Q_DECL_OVERRIDE
#define Q_DECL_OVERRIDE
#endif
namespace OCC { namespace OCC {
class FolderStatusModel : public QStandardItemModel class Folder;
{
public:
FolderStatusModel();
virtual Qt::ItemFlags flags( const QModelIndex& ) const Q_DECL_OVERRIDE;
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
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 class FolderStatusDelegate : public QStyledItemDelegate
@ -51,7 +107,9 @@ class FolderStatusDelegate : public QStyledItemDelegate
SyncProgressItemString, SyncProgressItemString,
AddProgressSpace, AddProgressSpace,
WarningCount, WarningCount,
SyncRunning SyncRunning,
AddButton
}; };
void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const Q_DECL_OVERRIDE; void paint( QPainter*, const QStyleOptionViewItem&, const QModelIndex& ) const Q_DECL_OVERRIDE;
QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const Q_DECL_OVERRIDE; QSize sizeHint( const QStyleOptionViewItem&, const QModelIndex& ) const Q_DECL_OVERRIDE;

View file

@ -19,9 +19,12 @@
#include "application.h" #include "application.h"
#include "utility.h" #include "utility.h"
#include "configfile.h" #include "configfile.h"
#include "owncloudsetupwizard.h"
#include "updater/updater.h" #include "updater/updater.h"
#include "updater/ocupdater.h" #include "updater/ocupdater.h"
#include "ignorelisteditor.h"
#include "config.h" #include "config.h"
@ -68,6 +71,9 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
QString themeDir = QString::fromLatin1(":/client/theme/%1/") QString themeDir = QString::fromLatin1(":/client/theme/%1/")
.arg(Theme::instance()->systrayIconFlavor(true)); .arg(Theme::instance()->systrayIconFlavor(true));
_ui->monoIconsCheckBox->setVisible(QDir(themeDir).exists()); _ui->monoIconsCheckBox->setVisible(QDir(themeDir).exists());
connect(_ui->ignoredFilesButton, SIGNAL(clicked()), SLOT(slotIgnoreFilesEditor()));
connect(_ui->addAccountButton, SIGNAL(clicked()), SLOT(slotOpenAccountWizard()));
} }
GeneralSettings::~GeneralSettings() GeneralSettings::~GeneralSettings()
@ -119,4 +125,24 @@ void GeneralSettings::slotToggleOptionalDesktopNotifications(bool enable)
cfgFile.setOptionalDesktopNotifications(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 } // namespace OCC

View file

@ -15,9 +15,10 @@
#define MIRALL_GENERALSETTINGS_H #define MIRALL_GENERALSETTINGS_H
#include <QWidget> #include <QWidget>
#include <QPointer>
namespace OCC { namespace OCC {
class IgnoreListEditor;
namespace Ui { namespace Ui {
class GeneralSettings; class GeneralSettings;
@ -36,11 +37,15 @@ private slots:
void slotToggleLaunchOnStartup(bool); void slotToggleLaunchOnStartup(bool);
void slotToggleOptionalDesktopNotifications(bool); void slotToggleOptionalDesktopNotifications(bool);
void slotUpdateInfo(); void slotUpdateInfo();
void slotIgnoreFilesEditor();
void slotOpenAccountWizard();
private: private:
void loadMiscSettings(); void loadMiscSettings();
Ui::GeneralSettings *_ui; Ui::GeneralSettings *_ui;
QPointer<IgnoreListEditor> _ignoreEditor;
}; };

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>468</width> <width>599</width>
<height>249</height> <height>429</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -41,13 +41,76 @@
</property> </property>
</widget> </widget>
</item> </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"> <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"> <widget class="QCheckBox" name="crashreporterCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string>Show crash reporter</string> <string>Show crash reporter</string>
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
</item> </item>

View file

@ -410,7 +410,5 @@ qint64 SelectiveSyncDialog::estimatedSize()
} }
} }