diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 3a12d800a350c..ecd22fe4c8513 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -162,7 +162,7 @@ class MouseCursorChanger : public QObject const auto index = folderList->indexAt(pos); if (model->classify(index) == FolderStatusModel::RootFolder && (FolderStatusDelegate::errorsListRect(folderList->visualRect(index)).contains(pos) || - FolderStatusDelegate::optionsButtonRect(folderList->visualRect(index),folderList->layoutDirection()).contains(pos))) { + FolderStatusDelegate::moreRectPos(folderList->visualRect(index)).contains(pos))) { shape = Qt::PointingHandCursor; } folderList->setCursor(shape); @@ -593,8 +593,8 @@ void AccountSettings::slotSubfolderContextMenuRequested(const QModelIndex& index } } - ac = menu.addAction(tr("Edit Ignored Files")); - connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentLocalIgnoredFiles); + // ac = menu.addAction(tr("Edit Ignored Files")); + // connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentLocalIgnoredFiles); ac = menu.addAction(tr("Create new folder")); connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenMakeFolderDialog); @@ -663,8 +663,8 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos) auto ac = menu->addAction(tr("Open folder")); connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenCurrentFolder); - ac = menu->addAction(tr("Edit Ignored Files")); - connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentIgnoredFiles); + // ac = menu->addAction(tr("Edit Ignored Files")); + // connect(ac, &QAction::triggered, this, &AccountSettings::slotEditCurrentIgnoredFiles); ac = menu->addAction(tr("Create new folder")); connect(ac, &QAction::triggered, this, &AccountSettings::slotOpenMakeFolderDialog); @@ -706,16 +706,16 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos) ac->setDisabled(Theme::instance()->enforceVirtualFilesSyncFolder()); } - if (Theme::instance()->showVirtualFilesOption() && !folder->virtualFilesEnabled() && Vfs::checkAvailability(folder->path())) { - const auto mode = bestAvailableVfsMode(); - if (mode == Vfs::WindowsCfApi || ConfigFile().showExperimentalOptions()) { - ac = menu->addAction(tr("Enable virtual file support %1 …").arg(mode == Vfs::WindowsCfApi ? QString() : tr("(experimental)"))); + // if (Theme::instance()->showVirtualFilesOption() && !folder->virtualFilesEnabled() && Vfs::checkAvailability(folder->path())) { + // const auto mode = bestAvailableVfsMode(); + // if (mode == Vfs::WindowsCfApi || ConfigFile().showExperimentalOptions()) { + // ac = menu->addAction(tr("Enable virtual file support %1 …").arg(mode == Vfs::WindowsCfApi ? QString() : tr("(experimental)"))); // TODO: remove when UX decision is made - ac->setEnabled(!Utility::isPathWindowsDrivePartitionRoot(folder->path())); + // ac->setEnabled(!Utility::isPathWindowsDrivePartitionRoot(folder->path())); // - connect(ac, &QAction::triggered, this, &AccountSettings::slotEnableVfsCurrentFolder); - } - } + // connect(ac, &QAction::triggered, this, &AccountSettings::slotEnableVfsCurrentFolder); + // } + // } menu->popup(treeView->mapToGlobal(pos)); @@ -723,34 +723,34 @@ void AccountSettings::slotCustomContextMenuRequested(const QPoint &pos) void AccountSettings::slotFolderListClicked(const QModelIndex &indx) { - if (indx.data(FolderStatusDelegate::AddButton).toBool()) { + // if (indx.data(FolderStatusDelegate::AddButton).toBool()) { // "Add Folder Sync Connection" - const auto treeView = _ui->_folderList; - const auto pos = treeView->mapFromGlobal(QCursor::pos()); - QStyleOptionViewItem opt; - opt.initFrom(treeView); - const auto btnRect = treeView->visualRect(indx); - const auto btnSize = treeView->itemDelegate(indx)->sizeHint(opt, indx); - const auto actual = QStyle::visualRect(opt.direction, btnRect, QRect(btnRect.topLeft(), btnSize)); - if (!actual.contains(pos)) { - return; - } - - if (indx.flags() & Qt::ItemIsEnabled) { - slotAddFolder(); - } else { - QToolTip::showText( - QCursor::pos(), - _model->data(indx, Qt::ToolTipRole).toString(), - this); - } - return; - } + // const auto treeView = _ui->_folderList; + // const auto pos = treeView->mapFromGlobal(QCursor::pos()); + // QStyleOptionViewItem opt; + // opt.initFrom(treeView); + // const auto btnRect = treeView->visualRect(indx); + // const auto btnSize = treeView->itemDelegate(indx)->sizeHint(opt, indx); + // const auto actual = QStyle::visualRect(opt.direction, btnRect, QRect(btnRect.topLeft(), btnSize)); + // if (!actual.contains(pos)) { + // return; + // } + + // if (indx.flags() & Qt::ItemIsEnabled) { + // slotAddFolder(); + // } else { + // QToolTip::showText( + // QCursor::pos(), + // _model->data(indx, Qt::ToolTipRole).toString(), + // this); + // } + // return; + // } if (_model->classify(indx) == FolderStatusModel::RootFolder) { // tries to find if we clicked on the '...' button. const auto treeView = _ui->_folderList; const auto pos = treeView->mapFromGlobal(QCursor::pos()); - if (FolderStatusDelegate::optionsButtonRect(treeView->visualRect(indx), layoutDirection()).contains(pos)) { + if (FolderStatusDelegate::moreRectPos(treeView->visualRect(indx)).contains(pos)) { slotCustomContextMenuRequested(pos); return; } diff --git a/src/gui/accountsetupcommandlinemanager.cpp b/src/gui/accountsetupcommandlinemanager.cpp index 94388b7ea5f17..416ab59e59689 100644 --- a/src/gui/accountsetupcommandlinemanager.cpp +++ b/src/gui/accountsetupcommandlinemanager.cpp @@ -114,6 +114,6 @@ void AccountSetupCommandLineManager::setupAccountFromCommandLine() _serverUrl.clear(); _remoteDirPath.clear(); _localDirPath.clear(); - _isVfsEnabled = true; + _isVfsEnabled = false; } } diff --git a/src/gui/folderstatusdelegate.cpp b/src/gui/folderstatusdelegate.cpp index d5f5d6e9e1c6c..38722e8433644 100644 --- a/src/gui/folderstatusdelegate.cpp +++ b/src/gui/folderstatusdelegate.cpp @@ -18,6 +18,7 @@ #include "folderstatusmodel.h" #include "folderstatusview.h" #include "folderman.h" +#include "QtGui/qpainterpath.h" #include "accountstate.h" #include #include @@ -93,6 +94,9 @@ QSize FolderStatusDelegate::sizeHint(const QStyleOptionViewItem &option, } } + // Make sure its at least 76 Pixel height + h = std::max(h, 76); + return {0, h}; } @@ -111,12 +115,89 @@ int FolderStatusDelegate::rootFolderHeightWithoutErrors(const QFontMetrics &fm, return h; } +QRect FolderStatusDelegate::moreRectPos(const QRect &rectIndex) +{ + if(rectIndex.isValid()) + { + const int buttonWidth = 88; + const int buttonHeight = 32; + + const int parentWidth = rectIndex.width(); + const int parentHeight = rectIndex.height(); + const int parentX = rectIndex.x(); + const int parentY = rectIndex.y(); + + const int xMoreButton = (parentX + parentWidth - buttonWidth - 16); + const int yMoreButton = ((parentHeight - buttonHeight) / 2) + parentY; + + return QRect(xMoreButton, yMoreButton, buttonWidth, buttonHeight); + } + return{}; +} + void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.data(AddButton).toBool()) { const_cast(option).showDecorationSelected = false; } + const QModelIndex parentIndex = index.parent(); //NMC customization + { + painter->save(); + + //Make sure, we dont draw the "new folder" button, since we have a speccial button for it outside this widget + if(index.data(AddButton).toBool()) + { + return; + } + + const QRect leftRect(0, option.rect.y(), option.rect.x(), option.rect.height()); + + if (option.state & QStyle::State_MouseOver) + { + // Drawing the highlight color #e5e5e5 + painter->fillRect(option.rect, QColor(0xe5, 0xe5, 0xe5)); + + //Now we need to paint the left side, what we disabled in folderstatusview.cpp (drawBranches() function) + painter->fillRect(leftRect, QColor(0xe5, 0xe5, 0xe5)); + } + + if (option.state & QStyle::State_Selected) + { + //Get selection background color + const QColor selectionColor = option.palette.color(QPalette::Highlight); + painter->fillRect(leftRect, selectionColor); + } + + const QTreeView* treeView = qobject_cast(option.widget); + if (treeView) + { + QIcon leftIcon; + QSize iconSize(16,16); + + if (!parentIndex.isValid()) + { + //We are in the root directory, make the icon bigger + iconSize.setHeight(24); + iconSize.setWidth(24); + } + + if (index.isValid() && treeView->isExpanded(index)) + { + // The parent item is expanded + leftIcon = QIcon(QLatin1String(":/client/theme/NMCIcons/collapse-down.svg")); + } + else + { + // The parent item is not expanded + leftIcon = QIcon(QLatin1String(":/client/theme/NMCIcons/collapse-right.svg")); + } + painter->drawPixmap(QPointF(leftRect.width() - iconSize.width(), leftRect.y() + leftRect.height() / 2 - iconSize.height()/2), leftIcon.pixmap(iconSize)); + } + + painter->restore(); + } + QStyledItemDelegate::paint(painter, option, index); auto textAlign = Qt::AlignLeft; @@ -195,7 +276,8 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & iconRect.setBottom(localPathRect.bottom()); iconRect.setWidth(iconRect.height()); - const auto nextToIcon = iconRect.right() + aliasMargin; + // const auto nextToIcon = iconRect.right() + aliasMargin; + const auto nextToIcon = iconRect.right() + std::max(aliasMargin, 16); aliasRect.setLeft(nextToIcon); localPathRect.setLeft(nextToIcon); remotePathRect.setLeft(nextToIcon); @@ -204,8 +286,22 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & auto optionsButtonVisualRect = optionsButtonRect(option.rect, option.direction); - const auto statusPixmap = statusIcon.pixmap(iconSize, iconSize, syncEnabled ? QIcon::Normal : QIcon::Disabled); - painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).left(), iconRect.top(), statusPixmap); + // const auto statusPixmap = statusIcon.pixmap(iconSize, iconSize, syncEnabled ? QIcon::Normal : QIcon::Disabled); + // painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).left(), iconRect.top(), statusPixmap); + + //NMC Customization + if(!parentIndex.isValid()) { + QIcon nmcFolderIcon = QIcon(QLatin1String(":/client/theme/NMCIcons/folderLogo.svg")); + const auto nmcFolderPixmap = nmcFolderIcon.pixmap(iconSize, iconSize, QIcon::Normal); + painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).left(), iconRect.top(), nmcFolderPixmap); + + const QSize statusIconSize(24,24); + const auto statusPixmap = statusIcon.pixmap(statusIconSize.width(), statusIconSize.height(), syncEnabled ? QIcon::Normal : QIcon::Disabled); + painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).right() - statusIconSize.width() * 0.6, iconRect.bottom() - statusIconSize.height() * 0.8, statusPixmap); + } else { + const auto statusPixmap = statusIcon.pixmap(iconSize, iconSize, syncEnabled ? QIcon::Normal : QIcon::Disabled); + painter->drawPixmap(QStyle::visualRect(option.direction, option.rect, iconRect).left(), iconRect.top(), statusPixmap); + } // only show the warning icon if the sync is running. Otherwise its // encoded in the status icon. @@ -292,18 +388,23 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & drawTextBox(infoTexts, QColor(0x4d, 0x4d, 0xba)); } + //NMC Customization, we need these infos already here to adjust the progress bar + const auto currentButtonRectPos = moreRectPos(option.rect); + const int nmcWidth = currentButtonRectPos.x() - nextToIcon - 8; //8 is margin to "More button" + // Sync File Progress Bar: Show it if syncFile is not empty. if (showProgess) { const auto fileNameTextHeight = subFm.boundingRect(tr("File")).height(); constexpr auto barHeight = 7; // same height as quota bar const auto overallWidth = option.rect.right() - aliasMargin - optionsButtonVisualRect.width() - nextToIcon; + Q_UNUSED(overallWidth); painter->save(); // Overall Progress Bar. const auto progressBarRect = QRect(nextToIcon, remotePathRect.top(), - overallWidth - 2 * margin, + nmcWidth, barHeight); QStyleOptionProgressBar progressBarOpt; @@ -335,8 +436,6 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & painter->restore(); } - painter->restore(); - { QStyleOptionToolButton btnOpt; btnOpt.state = option.state; @@ -344,12 +443,50 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem & btnOpt.state |= QStyle::State_Raised; btnOpt.arrowType = Qt::NoArrow; btnOpt.subControls = QStyle::SC_ToolButton; - btnOpt.rect = optionsButtonVisualRect; + // btnOpt.rect = optionsButtonVisualRect; + + // NMC customization + btnOpt.rect = currentButtonRectPos; + // make sure the button is not too far away from the left border + btnOpt.rect.setRight(btnOpt.rect.x() + btnOpt.rect.width() + 4); + + // Create QPainterPath with rounded corners + QPainterPath path; + path.addRoundedRect(btnOpt.rect, 4, 4); // 4 ist der Radius für die abgerundeten Ecken + + // Draw border line + QPen borderPen(QColor(0, 0, 0)); // Beispiel: Schwarzer Rand + borderPen.setWidth(1); + painter->setPen(borderPen); + painter->drawPath(path); + + // Fill the rectangle + painter->fillPath(path, Qt::transparent); + + // Draw the icon in rectangle btnOpt.icon = _iconMore; const auto buttonSize = QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize); btnOpt.iconSize = QSize(buttonSize, buttonSize); QApplication::style()->drawComplexControl(QStyle::CC_ToolButton, &btnOpt, painter); + + // Set icon position + int iconX = btnOpt.rect.x() + btnOpt.rect.width()/5; + int iconY = btnOpt.rect.y() + (btnOpt.rect.height() - btnOpt.iconSize.height()) / 2; + + painter->drawPixmap(iconX, iconY, btnOpt.icon.pixmap(btnOpt.iconSize)); + + // Add text + const QString buttonText = QCoreApplication::translate("", "MORE"); + painter->setFont(btnOpt.font); + int textX = iconX + btnOpt.iconSize.width() + 10; + int textY = iconY; + int textWidth = currentButtonRectPos.x() + currentButtonRectPos.width() - textX; + int textHeight = btnOpt.fontMetrics.height(); + + painter->drawText(QRect(textX, textY, textWidth, textHeight), Qt::AlignLeft | Qt::AlignVCenter, buttonText); } + + painter->restore(); } bool FolderStatusDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, diff --git a/src/gui/folderstatusdelegate.h b/src/gui/folderstatusdelegate.h index a8ed1c41de3b4..ce68ddac43edf 100644 --- a/src/gui/folderstatusdelegate.h +++ b/src/gui/folderstatusdelegate.h @@ -64,6 +64,7 @@ class FolderStatusDelegate : public QStyledItemDelegate static QRect addButtonRect(QRect within, Qt::LayoutDirection direction); static QRect errorsListRect(QRect within); static int rootFolderHeightWithoutErrors(const QFontMetrics &fm, const QFontMetrics &aliasFm); + static QRect moreRectPos(const QRect &rectIndex); public slots: void slotStyleChanged(); @@ -75,6 +76,8 @@ public slots: QPersistentModelIndex _pressedIndex; QIcon _iconMore; + + QStyleOptionViewItem _newOption; }; } // namespace OCC diff --git a/src/gui/folderstatusmodel.cpp b/src/gui/folderstatusmodel.cpp index f712cf92cffdc..550055fd143dc 100644 --- a/src/gui/folderstatusmodel.cpp +++ b/src/gui/folderstatusmodel.cpp @@ -51,13 +51,13 @@ FolderStatusModel::FolderStatusModel(QObject *parent) FolderStatusModel::~FolderStatusModel() = default; -static bool sortByFolderHeader(const FolderStatusModel::SubFolderInfo &lhs, const FolderStatusModel::SubFolderInfo &rhs) -{ - return QString::compare(lhs._folder->shortGuiRemotePathOrAppName(), - rhs._folder->shortGuiRemotePathOrAppName(), - Qt::CaseInsensitive) - < 0; -} +// static bool sortByFolderHeader(const FolderStatusModel::SubFolderInfo &lhs, const FolderStatusModel::SubFolderInfo &rhs) +// { +// return QString::compare(lhs._folder->shortGuiRemotePathOrAppName(), +// rhs._folder->shortGuiRemotePathOrAppName(), +// Qt::CaseInsensitive) +// < 0; +// } void FolderStatusModel::setAccountState(const AccountState *accountState) { @@ -92,7 +92,7 @@ void FolderStatusModel::setAccountState(const AccountState *accountState) } // Sort by header text - std::sort(_folders.begin(), _folders.end(), sortByFolderHeader); + // std::sort(_folders.begin(), _folders.end(), sortByFolderHeader); // Set the root _pathIdx after the sorting for (auto i = 0; i < _folders.size(); ++i) { diff --git a/src/gui/folderstatusview.cpp b/src/gui/folderstatusview.cpp index a353bc49f269a..7aea83626b90f 100644 --- a/src/gui/folderstatusview.cpp +++ b/src/gui/folderstatusview.cpp @@ -14,11 +14,19 @@ #include "folderstatusview.h" #include "folderstatusdelegate.h" +#include "QtCore/qtimer.h" +#include "QtGui/qevent.h" +#include "QtGui/qpainterpath.h" +#include "QtWidgets/qapplication.h" + +#include "QPainter" namespace OCC { FolderStatusView::FolderStatusView(QWidget *parent) : QTreeView(parent) { + // Removes the border + setStyleSheet("QTreeView { border: none; border-width: 0px; border-style: none; border-color: transparent; }"); } QModelIndex FolderStatusView::indexAt(const QPoint &point) const @@ -39,4 +47,34 @@ QRect FolderStatusView::visualRect(const QModelIndex &index) const return rect; } +void FolderStatusView::drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const { + + Q_UNUSED(painter) + Q_UNUSED(rect) + Q_UNUSED(index) + + // Empty, we override this function, to get rid of the left column with the collapse and expand icons. + // It's implemented here, but due to synchronisation, we will implement it in folderstatusdelegate.cpp paint funtion. +} + +void FolderStatusView::paintEvent(QPaintEvent *event) +{ + // it paints rounded corner, Qtreeview does not support the stylesheet setting + QPainter painter(viewport()); + painter.setRenderHint(QPainter::Antialiasing); + + const int radius = 4; + + QRect rect(0, 0, width(), height()); + QPainterPath path; + path.addRoundedRect(rect, radius, radius); + + QPalette palette = QApplication::palette(); + painter.fillRect(rect, palette.window()); + + painter.fillPath(path, Qt::white); + + QTreeView::paintEvent(event); +} + } // namespace OCC diff --git a/src/gui/folderstatusview.h b/src/gui/folderstatusview.h index f123672f69fd7..4aab4a48f5975 100644 --- a/src/gui/folderstatusview.h +++ b/src/gui/folderstatusview.h @@ -32,6 +32,10 @@ class FolderStatusView : public QTreeView [[nodiscard]] QModelIndex indexAt(const QPoint &point) const override; [[nodiscard]] QRect visualRect(const QModelIndex &index) const override; + +protected: + void drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const override; + void paintEvent(QPaintEvent *event) override; }; } // namespace OCC diff --git a/theme/more.svg b/theme/more.svg index 164a1b70345f8..e2f50c80c7483 100644 --- a/theme/more.svg +++ b/theme/more.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + /svg/icon/action/more/default + + + + \ No newline at end of file