Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/gui/FoldersGui/accountfolderscontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,15 +221,16 @@ void AccountFoldersController::updateActions()
_showInSystemFolder->setEnabled(_currentFolder && QFileInfo::exists(_currentFolder->path()));

if (_showInBrowser)
_showInBrowser->setEnabled(_currentFolder && _currentFolder->isAvailable());
_showInBrowser->setEnabled(_currentFolder && _currentFolder->isConnected() && _currentFolder->isAvailable());

_forceSync->setEnabled(_currentFolder && _currentFolder->canSync());
_forceSync->setText(_currentFolder && _currentFolder->isSyncRunning() ? tr("Restart sync") : tr("Force sync now"));

_pauseSync->setText(_currentFolder && _currentFolder->syncPaused() ? tr("Resume sync") : tr("Pause sync"));
// is this enough? I think we need to keep it enabled even if sync is running so the user can effectively cancel it + pause. as who knows. maybe
// they made a mistake when adding the folder or whatever
_pauseSync->setEnabled(_currentFolder && _currentFolder->isAvailable());
// this is a bit nuanced: we want to enable pause if the folder is disconnected as this is always a safe operation. if it *is* connected
// we only want to enabled the action if the folder is available. If the folder is not available pause makes no sense as there is nothing to sync to
// as the space is missing, server side.
_pauseSync->setEnabled(_currentFolder && (!_currentFolder->isConnected() || _currentFolder->isAvailable()));

_removeSync->setEnabled(_currentFolder);

Expand All @@ -242,7 +243,7 @@ void AccountFoldersController::updateActions()
}

if (_chooseSync)
_chooseSync->setEnabled(_currentFolder && _currentFolder->isAvailable() && !_currentFolder->virtualFilesEnabled());
_chooseSync->setEnabled(_currentFolder && _currentFolder->isConnected() && _currentFolder->isAvailable() && !_currentFolder->virtualFilesEnabled());
}

void OCC::AccountFoldersController::onShowInSystemFolder()
Expand Down
35 changes: 30 additions & 5 deletions src/gui/FoldersGui/accountfoldersview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ AccountFoldersView::AccountFoldersView(QWidget *parent)
: QWidget{parent}
{
// important to know: the parent in this ctr is always null because the widget is instantiated by the ui impl. it leaves the parent
// null presumably because it adds it to a stacked widget after ctr which takes ownership. The issue with this is that you *can't*
// null, presumably because it adds it to a stacked widget after ctr which takes ownership as parent. The issue with this is that you *can't*
// do anything relative to the parent in this construction setup because it is not known at time of construction.
// this makes setting the palette pretty icky

_itemMenu = new QMenu(this);
_itemMenu->setAccessibleName(tr("Sync options menu"));

Expand All @@ -63,25 +63,47 @@ void AccountFoldersView::buildView()
mainLayout->addLayout(buttonLineLayout);

_treeView = new QTreeView(this);
_treeView->setObjectName("accountFoldersTreeView");
_treeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// I'm not sure always off is good but that's what we currently have
_treeView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
_treeView->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
_treeView->setIndentation(0);
// indentation is "required" to show the expanders on folder when there are errors
// from experimentation, I think 10 is the min indent we can get away with but I may increase it as it doesn't look quite right
_treeView->setIndentation(10);
_treeView->setItemsExpandable(true);
_treeView->setExpandsOnDoubleClick(true);
_treeView->setSelectionMode(QAbstractItemView::SingleSelection);
_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
_treeView->setAllColumnsShowFocus(true);

// this should allow error items to paint fully just using the default impl
//_treeView->setWordWrap(true);
// ha! no that does not work at all...google says it's been broken for at least 15 years.
// nice job guys.

_treeView->header()->setSectionsMovable(false);
_treeView->setHeaderHidden(true);

// this method of correcting the row selection color to match the app button highlight does not work when user has changed system settings (the color sticks
// with the color that matched the system settings on creation of the view, which is bad. this color correcion has been moved to the item delegates for now
// because we can always grab the true current color on paint.
// TODO: #60 - we really need to implement full palettes for both light and dark mode. my rec would be to use a QStyle sub but will
// make a decision when the time comes.
QStyleOptionButton buttonStyle;
QPalette treePalette = _treeView->palette();
treePalette.setColor(QPalette::Highlight, buttonStyle.palette.color(QPalette::Highlight));
_treeView->setPalette(treePalette);


FolderItemDelegate *delegate = new FolderItemDelegate(_treeView);
_treeView->setItemDelegateForColumn(0, delegate);
// note this is not the normal ellipses character, it's vertically centered instead of positioned at font baseline. This is better
// for this button than normal ellipses
ButtonDelegate *buttonDel = new ButtonDelegate("⋯", _treeView);
buttonDel->setMenu(_itemMenu);
_treeView->setItemDelegateForColumn(1, buttonDel);

_treeView->setColumnWidth(1, 60);
// this works but only when the button item is current. this means I have to set the button column to current each time row selection
// changes but it works well so far. Still needs some tweaks to ensure the edit mode stays active when you click around in the same row.
// sometimes the button disappears. Note that using AllEditTriggers does not improve things but with all triggers you can trigger the menu
Expand All @@ -94,6 +116,7 @@ void AccountFoldersView::buildView()
mainLayout->addWidget(_treeView);

_syncedFolderCountLabel = new QLabel("placeholder for sync count", this);
_syncedFolderCountLabel->setObjectName("syncedFolderCount");
_syncedFolderCountLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
mainLayout->addWidget(_syncedFolderCountLabel, 0, Qt::AlignLeft);

Expand All @@ -114,7 +137,9 @@ void AccountFoldersView::setItemModels(QStandardItemModel *model, QItemSelection
QHeaderView *header = _treeView->header();
header->setStretchLastSection(false);
header->setSectionResizeMode(0, QHeaderView::Stretch);
header->setSectionResizeMode(1, QHeaderView::Fixed);
// if the resize mode is Fixed, for inexplicable reasons the delegate size hint is completely ignored, and the cell
// width is fixed at 100px
header->setSectionResizeMode(1, QHeaderView::ResizeToContents);
}

void AccountFoldersView::setSyncedFolderCount(int synced, int total)
Expand Down
54 changes: 29 additions & 25 deletions src/gui/FoldersGui/buttondelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "buttondelegate.h"

#include "resources.h"
#include <QPainter>
#include <QPushButton>

Expand All @@ -26,45 +27,47 @@ ButtonDelegate::ButtonDelegate(const QString &text, QObject *parent)
// note we will update the widget parent in the first createEditor as that passes the correct parent for the pop
// we can't really get the "right" parent here, and reusing the button is simpler and I'd guess slightly more efficient
// than creating it over and over in create editor.

_button = new QPushButton(_buttonText);
_button->setObjectName("buttonDelegateButton");
_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// I think this only needs to be set in the underlying item.
//_button->setAccessibleName("Folder options");
//_button->setAccessibleDescription("Menu button with folder options. Hit the space key to auto-pop the menu");

_button->setAutoFillBackground(true);
// have to explicitly align center or the text goes left when a menu is added
// also the font size is set based on the idea that the text is "..." - we may want to adapt this in future
_button->setStyleSheet({"font: bold 18px; text-align:center;"});
}

void ButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
// we have to override the default selection color for item views which is "dark-blue"
// use the default button highlight color instead to make it more cohesive
// note we can't just set the palette on the tree view as that won't update automatically when system color changes :/
QStyleOptionViewItem localOpt(option);
QStyleOptionViewItem opt(option);
QStyleOptionButton buttonStyle;
localOpt.palette.setColor(QPalette::Highlight, buttonStyle.palette.color(QPalette::Highlight));
drawBackground(painter, localOpt, index);
opt.palette.setColor(QPalette::Highlight, buttonStyle.palette.color(QPalette::Highlight));
drawBackground(painter, opt, index);

painter->save();
QFont f = painter->font();
f.setBold(true);
f.setPixelSize(18);
painter->setFont(f);
painter->drawText(option.rect, Qt::AlignCenter, _buttonText);
// this rigamarole is "needed" because if I set the button to autoFillBackground (which is super normal) there are weird artifacts of
// the window color above and below the button. No idea. This is on mac at least. The fix is to not paint the text dots if the button
// is showing on the current cell, as if we paint them there is bleed through visibility of the text under the button since we apparently
// autoFillBackground has to be off :/
if (!_button->isVisible() || !option.rect.contains(_button->pos())) {
QFont f = painter->font();
f.setBold(true);
f.setPixelSize(18);
painter->setFont(f);
painter->drawText(option.rect, Qt::AlignCenter, _buttonText);
}

painter->setPen(QPen(QBrush("#807F7F7F"), 1));
painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
QRect r = option.rect;
r.setRight(r.right() - 10);
painter->drawLine(r.bottomLeft(), r.bottomRight());
painter->restore();

drawFocus(painter, option, option.rect);
}

QSize ButtonDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QSize size = QItemDelegate::sizeHint(option, index);
return QSize(75, size.height());
QSize baseSize = QItemDelegate::sizeHint(option, index);
int width = _button->sizeHint().width();
return QSize(width + 20, baseSize.height());
}

QWidget *ButtonDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
Expand All @@ -90,11 +93,12 @@ void ButtonDelegate::destroyEditor(QWidget *widget, const QModelIndex &index) co

void ButtonDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index);
Q_ASSERT(editor == _button);
// make the button just a bit smaller so you can really see it's a button and not just a full cell "block".
QRect adaptedRect(option.rect);
adaptedRect.adjust(5, 5, -5, -5);
_button->setGeometry(adaptedRect);

int xOffset = (option.rect.width() - _button->width()) / 2;
int yOffset = (option.rect.height() - _button->height()) / 2;
_button->move(option.rect.left() + xOffset, option.rect.top() + yOffset);
}

void ButtonDelegate::setMenu(QMenu *menu)
Expand Down
48 changes: 18 additions & 30 deletions src/gui/FoldersGui/folderitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ FolderItem::FolderItem(Folder *folder)

setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);

_updater = new FolderItemUpdater(this, nullptr);
_updater = new FolderItemUpdater(this);
updateStatusString();
}

Expand All @@ -58,15 +58,18 @@ void FolderItem::setProgress(const ProgressInfo &progress)
return;
}

if (progress.totalSize() == 0)
if (progress.totalSize() == 0) {
// nothing is going to happen so ditch - with vfs this will always be the case?
return;
}

// completed size is literal - meaning if there was nothing to actually sync,
// total size = 0
// this can happen if there are no files/folders in a space
// or of the space is already 100% up to date, so no diffs, or if there is nothing to "move" between server/client (move or delete)
_totalSize = progress.totalSize();
_completedSize = progress.completedSize();
//_percentComplete = progress.refresh();
refresh();
}

Expand All @@ -80,7 +83,7 @@ QString FolderItem::statusIconName() const
if (!_folder || !_folder->accountState())
return {};
SyncResult status = _folder->syncResult();
if (!_folder->accountState()->isConnected()) {
if (!_folder->isConnected()) {
status.setStatus(SyncResult::Status::Offline);
} else if (_folder->syncPaused() || NetworkInformation::instance()->isBehindCaptivePortal()
|| (NetworkInformation::instance()->isMetered() && ConfigFile().pauseSyncWhenMetered())) {
Expand All @@ -94,7 +97,7 @@ QString FolderItem::statusAsString() const
if (!_folder || !_folder->accountState())
return {};

if (!_folder->accountState()->isConnected())
if (!_folder->isConnected())
return tr("Offline");

// this can get out of sorts wrt sync state if we were offline then go on - no sync is ever attempted if the folder is already
Expand Down Expand Up @@ -126,7 +129,7 @@ QString FolderItem::statusAsString() const
case SyncResult::Offline:
return tr("Offline");
case SyncResult::NotYetStarted:
return tr("About to sync");
return tr("Sync pending");
case SyncResult::SyncRunning: {
QString completedFormatted = Utility::octetsToString(_completedSize);
QString totalFormatted = Utility::octetsToString(_totalSize);
Expand Down Expand Up @@ -173,15 +176,15 @@ QVariant FolderItem::data(int role) const
case Qt::DisplayRole:
return _folder->displayName();
case Qt::DecorationRole:
/* if (_folder && _folder->space() && _folder->space()->image()) {
// this is not working but I have no idea why!
// the image is not null but won't paint, even in the default impl
// so just using the app icon to get the delegate working for now
QIcon spaceIcon = _folder->space()->image()->image();
if (!spaceIcon.isNull())
return spaceIcon;
}*/
return Theme::instance()->applicationIcon();
if (_folder && _folder->space() && _folder->space()->image()) {
// this is not working but I have no idea why!
// the image is not null but won't paint, even in the default impl
// so just using the app icon to get the delegate working for now
QIcon spaceIcon = _folder->space()->image()->image();
if (!spaceIcon.isNull())
return spaceIcon;
}
return Resources::getCoreIcon("folder-sync");
case FolderItemRoles::StatusIconRole:
return Resources::getCoreIcon(statusIconName());
case FolderItemRoles::StatusStringRole:
Expand All @@ -196,23 +199,8 @@ QVariant FolderItem::data(int role) const
// everything will be sorted in descending order, multiply the priority by 100 and prefer A over Z by applying a negative factor
return QVariant::fromValue(
_folder->sortPriority() * 100 - (_folder->displayName().isEmpty() ? 0 : static_cast<int64_t>(_folder->displayName().at(0).toLower().unicode())));
/* case Roles::Quota: {
qint64 used{};
qint64 total{};

if (auto *space = f->space()) {
const auto quota = space->drive().getQuota();
if (quota.isValid()) {
used = quota.getUsed();
total = quota.getTotal();
}
}
/*

if (total <= 0) {
return {};
}
return tr("%1 of %2 used").arg(Utility::octetsToString(used), Utility::octetsToString(total));
}
case Roles::AccessibleDescriptionRole: {
QStringList desc = {f->displayName(), Utility::enumToDisplayName(f->syncResult().status())};
desc << getErrors();
Expand Down
Loading