Skip to content

Commit 3c40cdf

Browse files
committed
Merge #394 [master] 2003-Folderview_Settings_Dialog
2 parents aa2e2f0 + ef29d8c commit 3c40cdf

File tree

8 files changed

+227
-75
lines changed

8 files changed

+227
-75
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);
@@ -575,8 +575,9 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index
575575
{
576576
Q_UNUSED(pos);
577577

578-
QMenu menu;
579-
auto ac = menu.addAction(tr("Open folder"));
578+
auto menu = new QMenu(this);
579+
menu->setAttribute(Qt::WA_DeleteOnClose);
580+
auto ac = menu->addAction(tr("Open folder"));
580581
connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenCurrentLocalSubFolder);
581582

582583
const auto fileName = _model->data(index, FolderStatusDelegate::FolderPathRole).toString();
@@ -595,24 +596,21 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index
595596
const auto isExternal = info->_isExternal;
596597

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

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

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

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

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

641655
void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
@@ -666,16 +680,13 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
666680
return;
667681
}
668682

669-
const auto menu = new QMenu(treeView);
683+
auto menu = new QMenu(treeView);
670684

671685
menu->setAttribute(Qt::WA_DeleteOnClose);
672686

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

676-
ac = menu->addAction(tr("Edit Ignored Files"));
677-
connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentIgnoredFiles);
678-
679690
ac = menu->addAction(tr("Create new folder"));
680691
connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenMakeFolderDialog);
681692
ac->setEnabled(QFile::exists(folder->path()));
@@ -716,52 +727,33 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos)
716727
ac->setDisabled(Theme::instance()->enforceVirtualFilesSyncFolder());
717728
}
718729

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

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

732-
menu->popup(treeView->mapToGlobal(pos));
747+
menu->popup(treeView->viewport()->mapToGlobal(pos));
733748
}
734749

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

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)