Skip to content

Commit e729caa

Browse files
committed
Merge #402 [stable-4.0] [master] 2003-Folderview_Settings_Dialog
2 parents 9ee16f5 + 9b3881f commit e729caa

File tree

7 files changed

+220
-74
lines changed

7 files changed

+220
-74
lines changed

src/gui/accountsettings.cpp

Lines changed: 42 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class MouseCursorChanger : public QObject
156156
const auto index = folderList->indexAt(pos);
157157
if (model->classify(index) == FolderStatusModel::RootFolder &&
158158
(FolderStatusDelegate::errorsListRect(folderList->visualRect(index)).contains(pos) ||
159-
FolderStatusDelegate::optionsButtonRect(folderList->visualRect(index),folderList->layoutDirection()).contains(pos))) {
159+
FolderStatusDelegate::moreRectPos(folderList->visualRect(index)).contains(pos))) {
160160
shape = Qt::PointingHandCursor;
161161
}
162162
folderList->setCursor(shape);
@@ -577,8 +577,9 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index
577577
{
578578
Q_UNUSED(pos);
579579

580-
QMenu menu;
581-
auto ac = menu.addAction(tr("Open folder"));
580+
auto menu = new QMenu(this);
581+
menu->setAttribute(Qt::WA_DeleteOnClose);
582+
auto ac = menu->addAction(tr("Open folder"));
582583
connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenCurrentLocalSubFolder);
583584

584585
const auto fileName = _model->data(index, FolderStatusDelegate::FolderPathRole).toString();
@@ -597,24 +598,21 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index
597598
const auto isExternal = info->_isExternal;
598599

599600
if (!isEncrypted && !isParentEncrypted && !isExternal && isTopFolder) {
600-
ac = menu.addAction(tr("Encrypt"));
601+
ac = menu->addAction(tr("Encrypt"));
601602
connect(ac, &QAction::triggered, [this, info] { slotMarkSubfolderEncrypted(info); });
602603
} else {
603604
// Ignore decrypting for now since it only works with an empty folder
604605
// connect(ac, &QAction::triggered, [this, &info] { slotMarkSubfolderDecrypted(info); });
605606
}
606607
}
607608

608-
ac = menu.addAction(tr("Edit Ignored Files"));
609-
connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentLocalIgnoredFiles);
610-
611-
ac = menu.addAction(tr("Create new folder"));
609+
ac = menu->addAction(tr("Create new folder"));
612610
connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenMakeFolderDialog);
613611
ac->setEnabled(QFile::exists(fileName));
614612

615613
const auto folder = info->_folder;
616614
if (folder && folder->virtualFilesEnabled()) {
617-
auto availabilityMenu = menu.addMenu(tr("Availability"));
615+
auto availabilityMenu = menu->addMenu(tr("Availability"));
618616

619617
// Has '/' suffix convention for paths here but VFS and
620618
// sync engine expects no such suffix
@@ -637,7 +635,23 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index
637635
connect(ac, &QAction::triggered, this, [this, folder, path] { slotSetSubFolderAvailability(folder, path, PinState::OnlineOnly); });
638636
}
639637

640-
menu.exec(QCursor::pos());
638+
const auto highlightColor = palette().highlight().color();
639+
menu->setStyleSheet(QString(R"(
640+
QMenu {
641+
border: 1px solid black;
642+
border-radius: 4px;
643+
padding: 6px;
644+
}
645+
QMenu::item {
646+
padding: 8px;
647+
}
648+
QMenu::item:selected,
649+
QMenu::item:hover {
650+
background-color: %1;
651+
}
652+
)").arg(highlightColor.name(QColor::HexRgb)));
653+
654+
menu->popup(QCursor::pos());
641655
}
642656

643657
void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
@@ -668,16 +682,13 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
668682
return;
669683
}
670684

671-
const auto menu = new QMenu(treeView);
685+
auto menu = new QMenu(treeView);
672686

673687
menu->setAttribute(Qt::WA_DeleteOnClose);
674688

675689
auto ac = menu->addAction(tr("Open folder"));
676690
connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenCurrentFolder);
677691

678-
ac = menu->addAction(tr("Edit Ignored Files"));
679-
connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentIgnoredFiles);
680-
681692
ac = menu->addAction(tr("Create new folder"));
682693
connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenMakeFolderDialog);
683694
ac->setEnabled(QFile::exists(folder->path()));
@@ -714,52 +725,33 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
714725
connect(ac, &QAction::triggered, this, [this]() { slotSetCurrentFolderAvailability(PinState::OnlineOnly); });
715726
}
716727

717-
if (const auto mode = bestAvailableVfsMode();
718-
!Theme::instance()->disableVirtualFilesSyncFolder() &&
719-
Theme::instance()->showVirtualFilesOption() && !folder->virtualFilesEnabled() && Vfs::checkAvailability(folder->path(), mode)) {
720-
if (mode == Vfs::WindowsCfApi || ConfigFile().showExperimentalOptions()) {
721-
ac = menu->addAction(tr("Enable virtual file support %1 …").arg(mode == Vfs::WindowsCfApi ? QString() : tr("(experimental)")));
722-
// TODO: remove when UX decision is made
723-
ac->setEnabled(!Utility::isPathWindowsDrivePartitionRoot(folder->path()));
724-
//
725-
connect(ac, &QAction::triggered, this, &AccountSettings::slotEnableVfsCurrentFolder);
726-
}
727-
}
728+
const auto highlightColor = palette().highlight().color();
728729

730+
menu->setStyleSheet(QString(R"(
731+
QMenu {
732+
border: 1px solid black;
733+
border-radius: 4px;
734+
padding: 6px;
735+
}
736+
QMenu::item {
737+
padding: 8px;
738+
}
739+
QMenu::item:selected,
740+
QMenu::item:hover {
741+
background-color: %1;
742+
}
743+
)").arg(highlightColor.name(QColor::HexRgb)));
729744

730-
menu->popup(treeView->mapToGlobal(pos));
745+
menu->popup(treeView->viewport()->mapToGlobal(pos));
731746
}
732747

733748
void AccountSettings::slotFolderListClicked(const QModelIndex &indx)
734749
{
735-
if (indx.data(FolderStatusDelegate::AddButton).toBool()) {
736-
// "Add Folder Sync Connection"
737-
const auto treeView = _ui->_folderList;
738-
const auto pos = treeView->mapFromGlobal(QCursor::pos());
739-
QStyleOptionViewItem opt;
740-
opt.initFrom(treeView);
741-
const auto btnRect = treeView->visualRect(indx);
742-
const auto btnSize = treeView->itemDelegateForIndex(indx)->sizeHint(opt, indx);
743-
const auto actual = QStyle::visualRect(opt.direction, btnRect, QRect(btnRect.topLeft(), btnSize));
744-
if (!actual.contains(pos)) {
745-
return;
746-
}
747-
748-
if (indx.flags() & Qt::ItemIsEnabled) {
749-
slotAddFolder();
750-
} else {
751-
QToolTip::showText(
752-
QCursor::pos(),
753-
_model->data(indx, Qt::ToolTipRole).toString(),
754-
this);
755-
}
756-
return;
757-
}
758750
if (_model->classify(indx) == FolderStatusModel::RootFolder) {
759751
// tries to find if we clicked on the '...' button.
760752
const auto treeView = _ui->_folderList;
761753
const auto pos = treeView->mapFromGlobal(QCursor::pos());
762-
if (FolderStatusDelegate::optionsButtonRect(treeView->visualRect(indx), layoutDirection()).contains(pos)) {
754+
if (FolderStatusDelegate::moreRectPos(treeView->visualRect(indx)).contains(pos)) {
763755
slotCustomContextMenuRequested(pos);
764756
return;
765757
}

src/gui/accountsetupcommandlinemanager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,6 @@ void AccountSetupCommandLineManager::setupAccountFromCommandLine()
105105
_serverUrl.clear();
106106
_remoteDirPath.clear();
107107
_localDirPath.clear();
108-
_isVfsEnabled = true;
108+
_isVfsEnabled = false;
109109
}
110110
}

src/gui/folderstatusdelegate.cpp

Lines changed: 131 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include <QFileIconProvider>
1616
#include <QPainter>
17+
#include <QPainterPath>
18+
#include <QRect>
1719
#include <QApplication>
1820
#include <QMouseEvent>
1921
#include <QStyleFactory>
@@ -83,9 +85,28 @@ QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem &option,
8385
}
8486
}
8587

88+
// Make sure its at least 76 Pixel high
89+
h = std::max(h, 76);
90+
8691
return {0, h};
8792
}
8893

94+
QRect FolderStatusDelegate::moreRectPos(const QRect &rectIndex)
95+
{
96+
if (rectIndex.isValid())
97+
{
98+
constexpr int buttonWidth = 88;
99+
constexpr int buttonHeight = 32;
100+
constexpr int margin = 16;
101+
102+
const int xMoreButton = rectIndex.right() - buttonWidth - margin;
103+
const int yMoreButton = rectIndex.center().y() - (buttonHeight / 2);
104+
105+
return QRect(xMoreButton, yMoreButton, buttonWidth, buttonHeight);
106+
}
107+
return {};
108+
}
109+
89110
int FolderStatusDelegate::rootFolderHeightWithoutErrors(const QFontMetrics &fm, const QFontMetrics &aliasFm)
90111
{
91112
const int aliasMargin = aliasFm.height() / 2;
@@ -107,6 +128,56 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
107128
const_cast<QStyleOptionViewItem &>(option).showDecorationSelected = false;
108129
}
109130

131+
const QModelIndex parentIndex = index.parent(); // NMC customization
132+
{
133+
painter->save();
134+
135+
// Verhindere das Zeichnen des "Neuer Ordner"-Buttons
136+
if (index.data(AddButton).toBool()) {
137+
return;
138+
}
139+
140+
const QRect leftRect(0, option.rect.y(), option.rect.x(), option.rect.height());
141+
142+
if (option.state & QStyle::State_MouseOver) {
143+
QColor hoverColor = QApplication::palette().color(QPalette::Mid);
144+
painter->fillRect(option.rect, hoverColor);
145+
painter->fillRect(leftRect, hoverColor);
146+
}
147+
148+
if (option.state & QStyle::State_Selected) {
149+
// Auswahlhintergrundfarbe abrufen
150+
const QColor selectionColor = option.palette.color(QPalette::Highlight);
151+
painter->fillRect(option.rect, selectionColor);
152+
painter->fillRect(leftRect, selectionColor);
153+
}
154+
155+
const QTreeView* treeView = qobject_cast<const QTreeView*>(option.widget);
156+
if (treeView) {
157+
QIcon leftIcon;
158+
QSize iconSize(16, 16);
159+
160+
if (!parentIndex.isValid()) {
161+
// Wir befinden uns im Stammverzeichnis, also Icon vergrößern
162+
iconSize = QSize(24, 24);
163+
}
164+
165+
if (index.isValid() && treeView->isExpanded(index)) {
166+
// Das übergeordnete Element ist erweitert
167+
leftIcon = QIcon(Theme::createColorAwareIcon(QStringLiteral(":/client/theme/NMCIcons/collapse-down.svg")));
168+
} else {
169+
// Das übergeordnete Element ist nicht erweitert
170+
leftIcon = QIcon(Theme::createColorAwareIcon(QStringLiteral(":/client/theme/NMCIcons/collapse-right.svg")));
171+
}
172+
173+
const QPoint iconPos(leftRect.width() - iconSize.width(),
174+
leftRect.y() + leftRect.height() / 2 - iconSize.height() / 2);
175+
painter->drawPixmap(iconPos, leftIcon.pixmap(iconSize));
176+
}
177+
178+
painter->restore();
179+
}
180+
110181
QStyledItemDelegate::paint(painter, option, index);
111182

112183
auto textAlign = Qt::AlignLeft;
@@ -183,19 +254,28 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
183254
iconRect.setBottom(localPathRect.bottom());
184255
iconRect.setWidth(iconRect.height());
185256

186-
const auto nextToIcon = iconRect.right() + aliasMargin;
257+
const auto nextToIcon = iconRect.right() + std::max(aliasMargin, 16);
187258
aliasRect.setLeft(nextToIcon);
188259
localPathRect.setLeft(nextToIcon);
189260
remotePathRect.setLeft(nextToIcon);
190261

262+
const auto iconSize = iconRect.width();
263+
191264
auto optionsButtonVisualRect = optionsButtonRect(option.rect, option.direction);
192265

193-
statusIcon.paint(
194-
painter,
195-
QStyle::visualRect(option.direction, option.rect, iconRect),
196-
Qt::AlignCenter,
197-
syncEnabled ? QIcon::Normal : QIcon::Disabled
198-
);
266+
// NMC Customization
267+
if (!parentIndex.isValid()) {
268+
QIcon nmcFolderIcon = QIcon(QLatin1String(":/client/theme/NMCIcons/folderLogo.svg"));
269+
const auto nmcFolderPixmap = nmcFolderIcon.pixmap(iconSize, iconSize, QIcon::Normal);
270+
painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).left(), iconRect.top(), nmcFolderPixmap);
271+
272+
const QSize statusIconSize(24,24);
273+
const auto statusPixmap = statusIcon.pixmap(statusIconSize.width(), statusIconSize.height(), syncEnabled ? QIcon::Normal : QIcon::Disabled);
274+
painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).right() - statusIconSize.width() * 0.6, iconRect.bottom() - statusIconSize.height() * 0.8, statusPixmap);
275+
} else {
276+
const auto statusPixmap = statusIcon.pixmap(iconSize, iconSize, syncEnabled ? QIcon::Normal : QIcon::Disabled);
277+
painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).left(), iconRect.top(), statusPixmap);
278+
}
199279

200280
auto palette = option.palette;
201281

@@ -267,18 +347,23 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
267347
drawTextBox(infoTexts, QColor(0x4d, 0x4d, 0xba));
268348
}
269349

350+
// NMC customization: we need these infos already here to adjust the progress bar
351+
const QRect currentButtonRectPos = moreRectPos(option.rect);
352+
const int nmcWidth = currentButtonRectPos.x() - nextToIcon - 8; // 8 is the margin to "More" button
353+
270354
// Sync File Progress Bar: Show it if syncFile is not empty.
271355
if (showProgess) {
272356
const auto fileNameTextHeight = subFm.boundingRect(tr("File")).height();
273357
constexpr auto barHeight = 7; // same height as quota bar
274358
const auto overallWidth = option.rect.right() - aliasMargin - optionsButtonVisualRect.width() - nextToIcon;
359+
Q_UNUSED(overallWidth);
275360

276361
painter->save();
277362

278363
// Overall Progress Bar.
279364
const auto progressBarRect = QRect(nextToIcon,
280365
remotePathRect.top(),
281-
overallWidth - 2 * margin,
366+
nmcWidth,
282367
barHeight);
283368

284369
QStyleOptionProgressBar progressBarOpt;
@@ -310,21 +395,55 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
310395
painter->restore();
311396
}
312397

313-
painter->restore();
314-
315398
{
316399
QStyleOptionToolButton btnOpt;
317400
btnOpt.state = option.state;
318401
btnOpt.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
319402
btnOpt.state |= QStyle::State_Raised;
320403
btnOpt.arrowType = Qt::NoArrow;
321404
btnOpt.subControls = QStyle::SC_ToolButton;
322-
btnOpt.rect = optionsButtonVisualRect;
405+
//NMC customization
406+
btnOpt.rect = currentButtonRectPos;
407+
//make sure the button is not too far away from the left border
408+
btnOpt.rect.setRight(btnOpt.rect.x() + btnOpt.rect.width() + 4);
409+
410+
// Create QPainterPath with rounded corners
411+
QPainterPath path;
412+
path.addRoundedRect(btnOpt.rect, 4, 4); // 4 ist der Radius für die abgerundeten Ecken
413+
414+
// Draw border line
415+
QPen borderPen(QColor(0, 0, 0)); // Beispiel: Schwarzer Rand
416+
borderPen.setWidth(1);
417+
painter->setPen(borderPen);
418+
painter->drawPath(path);
419+
420+
// Fill the rectangle
421+
painter->fillPath(path, Qt::transparent);
422+
423+
// Draw the icon in rectangle
323424
btnOpt.icon = _iconMore;
324425
const auto buttonSize = QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize);
325426
btnOpt.iconSize = QSize(buttonSize, buttonSize);
326-
QApplication::style()->drawComplexControl(QStyle::CC_ToolButton, &btnOpt, painter);
427+
428+
// Set icon position
429+
int iconX = btnOpt.rect.x() + btnOpt.rect.width()/5;
430+
int iconY = btnOpt.rect.y() + (btnOpt.rect.height() - btnOpt.iconSize.height()) / 2;
431+
432+
painter->drawPixmap(iconX, iconY, btnOpt.icon.pixmap(btnOpt.iconSize));
433+
434+
//Add text
435+
const QString buttonText = QCoreApplication::translate("", "MORE");
436+
painter->setFont(btnOpt.font);
437+
painter->setPen(option.palette.color(QPalette::ButtonText));
438+
int textX = iconX + btnOpt.iconSize.width() + 10;
439+
int textY = iconY;
440+
int textWidth = currentButtonRectPos.x() + currentButtonRectPos.width() - textX;
441+
int textHeight = btnOpt.fontMetrics.height();
442+
443+
painter->drawText(QRect(textX, textY, textWidth, textHeight), Qt::AlignLeft | Qt::AlignVCenter, buttonText);
327444
}
445+
446+
painter->restore();
328447
}
329448

330449
bool FolderStatusDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,

0 commit comments

Comments
 (0)