Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable-3.14] nmc/2003-Folderview_Settings_Dialog_New #316

Open
wants to merge 1 commit into
base: stable-3.14
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ set(CMAKE_XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME YES)

set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")

set(NMC_RCC_FILE "nmctheme_v1.rcc")
configure_file(${CMAKE_SOURCE_DIR}/${NMC_RCC_FILE} "${BIN_OUTPUT_DIRECTORY}/${NMC_RCC_FILE}" COPYONLY)

include(${CMAKE_SOURCE_DIR}/NEXTCLOUD.cmake)

set(QT_VERSION_MAJOR "6")
Expand Down Expand Up @@ -341,6 +344,7 @@ configure_file(version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
if(BUILD_OWNCLOUD_OSX_BUNDLE)
install(FILES sync-exclude.lst DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/)
configure_file(sync-exclude.lst bin/${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/sync-exclude.lst COPYONLY)
install(FILES nmctheme_v1.rcc DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/)
elseif(BUILD_CLIENT)
install( FILES sync-exclude.lst DESTINATION ${SYSCONFDIR}/${APPLICATION_SHORTNAME} )
configure_file(sync-exclude.lst bin/sync-exclude.lst COPYONLY)
Expand Down
Binary file added nmctheme_v1.rcc
Binary file not shown.
8 changes: 8 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ find_package(Qt${QT_MAJOR_VERSION} REQUIRED COMPONENTS Widgets Svg Qml Quick Qui
find_package(KF6Archive REQUIRED)
find_package(KF6GuiAddons)

#NMC change, its needed to find the ui file in a different location than the header file
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/src/gui")

if (NOT TARGET Qt::GuiPrivate)
message(FATAL_ERROR "Could not find GuiPrivate component of Qt. It might be shipped as a separate package, please check that.")
endif()
Expand Down Expand Up @@ -251,6 +254,10 @@ set(client_SRCS
wizard/linklabel.cpp
)

file(GLOB NMC_FILES "nmcgui/*")
set(NMC_SRCS ${NMC_FILES})
list(APPEND client_SRCS ${NMC_SRCS})

if (WITH_WEBENGINE)
list(APPEND client_SRCS
wizard/webviewpage.h
Expand Down Expand Up @@ -618,6 +625,7 @@ if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
install(FILES ${VISUAL_ELEMENTS} DESTINATION bin/visualelements)
install(FILES "${theme_dir}/${APPLICATION_EXECUTABLE}.VisualElementsManifest.xml" DESTINATION bin)
install(FILES ${client_I18N} DESTINATION i18n)
install(FILES ${CMAKE_SOURCE_DIR}/nmctheme_v1.rcc DESTINATION bin)
endif()

# we may not add MACOSX_BUNDLE here, if not building one
Expand Down
72 changes: 36 additions & 36 deletions src/gui/accountsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -595,8 +595,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);
Expand Down Expand Up @@ -665,8 +665,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);
Expand Down Expand Up @@ -708,51 +708,51 @@ 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));
}

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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/gui/accountsetupcommandlinemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,6 @@ void AccountSetupCommandLineManager::setupAccountFromCommandLine()
_serverUrl.clear();
_remoteDirPath.clear();
_localDirPath.clear();
_isVfsEnabled = true;
_isVfsEnabled = false;
}
}
151 changes: 144 additions & 7 deletions src/gui/folderstatusdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "folderstatusmodel.h"
#include "folderstatusview.h"
#include "folderman.h"
#include "QtGui/qpainterpath.h"
#include "accountstate.h"
#include <theme.h>
#include <account.h>
Expand Down Expand Up @@ -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};
}

Expand All @@ -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<QStyleOptionViewItem &>(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<const QTreeView*>(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;
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -335,21 +436,57 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
painter->restore();
}

painter->restore();

{
QStyleOptionToolButton btnOpt;
btnOpt.state = option.state;
btnOpt.state &= ~(QStyle::State_Selected | QStyle::State_HasFocus);
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,
Expand Down
Loading