Skip to content

Commit

Permalink
Added ability to use compact buttons for 'MenuButtonPopup' tool butto…
Browse files Browse the repository at this point in the history
…ns. But text and icon are poorly aligned to nearby buttons. Also, small style tweaks.
  • Loading branch information
SeriousAlexej committed Mar 9, 2018
1 parent 539ad87 commit d053f2b
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 13 deletions.
1 change: 1 addition & 0 deletions examples/Test/tabtoolbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"groupHeight":75,
"groupRowCount":3,
"specialTab":true,
"compactButtons":false,
"cornerActions":[
"actionHelp"
],
Expand Down
2 changes: 2 additions & 0 deletions include/TabToolbar/Group.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ class TT_API Group : public QFrame
void AddSeparator();
SubGroup* AddSubGroup(SubGroup::Align align);
void AddWidget(QWidget* widget);
void UseCompactButtons(bool use);

private:
QFrame* CreateSeparator();

QHBoxLayout* innerLayout;
bool useCompactButtons;
};

}
Expand Down
2 changes: 2 additions & 0 deletions src/TabToolbar/Builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ TabToolbar* Builder::CreateTabToolbar(const QString& configPath)
const int groupHeight = root["groupHeight"].toInt();
const int groupRowCount = root["groupRowCount"].toInt();
const bool hasSpecialTab = root["specialTab"].toBool();
const bool compactButtons = root.contains("compactButtons") ? root["compactButtons"].toBool() : false;
TabToolbar* tt = new TabToolbar((QWidget*)parent(), groupHeight, groupRowCount);

auto CreateCustomWidget = [this, tt](const QString& name, const QJsonObject& item)
Expand Down Expand Up @@ -134,6 +135,7 @@ TabToolbar* Builder::CreateTabToolbar(const QString& configPath)
const QString groupDisplayName = groupObject["displayName"].toString();
const QString groupName = groupObject["name"].toString();
Group* group = page->AddGroup(groupDisplayName);
group->UseCompactButtons(compactButtons);
guiWidgets[groupName] = group;

const QJsonArray content = groupObject["content"].toArray();
Expand Down
2 changes: 2 additions & 0 deletions src/TabToolbar/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ set(SRC_LIST
${INCROOT}/Page.h
${SRCROOT}/Builder.cpp
${INCROOT}/Builder.h
${SRCROOT}/CompactToolButton.cpp
${SRCROOT}/CompactToolButton.h
${SRCROOT}/Group.cpp
${INCROOT}/Group.h
${SRCROOT}/SubGroup.cpp
Expand Down
191 changes: 191 additions & 0 deletions src/TabToolbar/CompactToolButton.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
TabToolbar - a small utility library for Qt, providing tabbed toolbars
Copyright (C) 2018 Oleksii Sierov
TabToolbar is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TabToolbar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TabToolbar. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QAction>
#include <QMenu>
#include <QToolButton>
#include <QPainter>
#include <QVBoxLayout>
#include <QStyle>
#include <QApplication>
#include <QLinearGradient>
#include <TabToolbar/TabToolbar.h>
#include <TabToolbar/StyleTools.h>
#include "CompactToolButton.h"

namespace
{
class TTHover : public QObject
{
public:
TTHover(tt::CompactToolButton* parent, QToolButton* up, QToolButton* down) :
QObject(parent),
toolButton(parent),
upButton(up),
downButton(down)
{
}

protected:
bool eventFilter(QObject* watched, QEvent* event) override
{
if(event->type() == QEvent::HoverLeave)
{
toolButton->SetHoverType(tt::CompactToolButton::Hover::None);
}
else if(event->type() == QEvent::HoverEnter)
{
if(watched == upButton)
toolButton->SetHoverType(tt::CompactToolButton::Hover::Top);
else if(watched == downButton)
toolButton->SetHoverType(tt::CompactToolButton::Hover::Bottom);
}
if(watched == upButton)
{
if(event->type() == QEvent::Hide)
downButton->hide();
else if(event->type() == QEvent::Show)
downButton->show();
else if(event->type() == QEvent::EnabledChange)
downButton->setEnabled(upButton->isEnabled());
}
return QObject::eventFilter(watched, event);
}

private:
tt::CompactToolButton* toolButton;
QToolButton* upButton;
QToolButton* downButton;
};
}

namespace tt
{

CompactToolButton::CompactToolButton(QAction* action, QMenu* menu, QWidget* parent) :
QFrame(parent),
borderColor(Qt::transparent)
{
const int iconSize = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
upButton = new QToolButton(this);
upButton->setProperty("TTInternal", QVariant(true));
upButton->setAutoRaise(true);
upButton->setDefaultAction(action);
upButton->setIconSize(QSize(iconSize, iconSize));
upButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);

QVBoxLayout* l = new QVBoxLayout(this);
l->setMargin(0);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
l->setDirection(QBoxLayout::TopToBottom);

upButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
upButton->setPopupMode(QToolButton::DelayedPopup);
l->addWidget(upButton);

downButton = new QToolButton(this);
downButton->setProperty("TTInternal", QVariant(true));
downButton->setAutoRaise(true);
downButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
downButton->setPopupMode(QToolButton::InstantPopup);
downButton->setMinimumHeight(25);
downButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
downButton->setText(action->text());
if(menu)
{
downButton->setMenu(menu);
QObject::connect(menu, &QMenu::aboutToHide, this, [this]{ SetHoverType(Hover::None); });
}
l->addWidget(downButton);
setLayout(l);

TTHover* hover = new TTHover(this, upButton, downButton);
upButton->installEventFilter(hover);
downButton->installEventFilter(hover);

QTimer::singleShot(500, [this] { GetBorderColor(); });
}

void CompactToolButton::SetHoverType(Hover type)
{
hoverType = type;
update();
}

bool CompactToolButton::event(QEvent* e)
{
if(e->type() == QEvent::StyleChange)
QTimer::singleShot(500, [this] { GetBorderColor(); update(); });
return QFrame::event(e);
}

void CompactToolButton::paintEvent(QPaintEvent*)
{
if(hoverType == Hover::None || !upButton->isEnabled())
return;

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, false);
painter.setBrush(Qt::NoBrush);

QRect rect(0, 1, width()-1, height()-3);

QLinearGradient gradient;
gradient.setColorAt(0.0f, Qt::transparent);
gradient.setColorAt(downButton->height()*1.0f/rect.height(), borderColor);
gradient.setColorAt(1.0f, borderColor);

if(hoverType == Hover::Bottom)
{
gradient.setStart(0.0f, rect.height());
gradient.setFinalStop(0.0f, 0.0f);
}
else
{
gradient.setStart(0.0f, 0.0f);
gradient.setFinalStop(0.0f, rect.height());
}
QPen pen(QBrush(gradient), 1.0f);
painter.setPen(pen);

painter.drawRect(rect);
}

void CompactToolButton::GetBorderColor()
{
QObject* par = this;
do
{
par = par->parent();
const TabToolbar* toolbar = dynamic_cast<TabToolbar*>(par);
if(toolbar)
{
borderColor = Qt::transparent;
const QString style = toolbar->GetStyle();
if(!style.isEmpty())
{
auto styleParams = tt::CreateStyle(style);
if(!styleParams->BorderColor.empty())
borderColor = tt::CreateStyle(style)->BorderColor;
}
return;
}
} while(par);
}

}
60 changes: 60 additions & 0 deletions src/TabToolbar/CompactToolButton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
TabToolbar - a small utility library for Qt, providing tabbed toolbars
Copyright (C) 2018 Oleksii Sierov
TabToolbar is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
TabToolbar is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TabToolbar. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TT_COMPACT_TOOL_BUTTON_H
#define TT_COMPACT_TOOL_BUTTON_H
#include <QFrame>
#include <QColor>

class QAction;
class QMenu;
class QToolButton;

namespace tt
{

class CompactToolButton: public QFrame
{
Q_OBJECT
public:
enum class Hover
{
Top,
Bottom,
None
};

CompactToolButton(QAction* action, QMenu* menu, QWidget* parent = nullptr);
virtual ~CompactToolButton() = default;

void SetHoverType(Hover type);

protected:
bool event(QEvent* e) override;
void paintEvent(QPaintEvent*) override;
void GetBorderColor();

private:
Hover hoverType = Hover::None;
QToolButton* upButton;
QToolButton* downButton;
QColor borderColor;
};

}

#endif
38 changes: 26 additions & 12 deletions src/TabToolbar/Group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
#include <QSize>
#include <QApplication>
#include <QStyle>
#include <QPainter>
#include <TabToolbar/Group.h>
#include <TabToolbar/SubGroup.h>
#include <TabToolbar/TabToolbar.h>
#include "CompactToolButton.h"

using namespace tt;

Expand Down Expand Up @@ -121,20 +123,32 @@ void Group::AddSeparator()
innerLayout->addWidget(CreateSeparator());
}

void Group::UseCompactButtons(bool use)
{
useCompactButtons = use;
}

void Group::AddAction(QToolButton::ToolButtonPopupMode type, QAction* action, QMenu* menu)
{
const int iconSize = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
QToolButton* btn = new QToolButton(this);
btn->setProperty("TTInternal", QVariant(true));
btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
btn->setAutoRaise(true);
btn->setDefaultAction(action);
btn->setIconSize(QSize(iconSize, iconSize));
btn->setPopupMode(type);
if(menu)
btn->setMenu(menu);
btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
innerLayout->addWidget(btn);
if(type == QToolButton::MenuButtonPopup && useCompactButtons)
{
innerLayout->addWidget(new CompactToolButton(action, menu, this));
}
else
{
const int iconSize = QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize);
QToolButton* btn = new QToolButton(this);
btn->setProperty("TTInternal", QVariant(true));
btn->setAutoRaise(true);
btn->setDefaultAction(action);
btn->setIconSize(QSize(iconSize, iconSize));
btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
btn->setPopupMode(type);
if(menu)
btn->setMenu(menu);
innerLayout->addWidget(btn);
}
}

void Group::AddWidget(QWidget* widget)
Expand Down
2 changes: 1 addition & 1 deletion src/TabToolbar/Styles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ struct DefaultStylesRegistrar
params->ToolbarBackgroundColor = p.light;
const float paneDimmCoeff = (p.window.lightnessF() > 0.5f ? 0.03529f : 0.1f);
params->PaneColor = dimmed(p.light, paneDimmCoeff);
const float borderDimmCoeff = (p.window.lightnessF() > 0.5f ? 0.08f : 0.2f);
const float borderDimmCoeff = (p.window.lightnessF() > 0.5f ? 0.15f : 0.3f);
params->BorderColor = dimmed(params->ToolbarBackgroundColor, borderDimmCoeff);
params->GroupNameColor = lcomb(p.text, p.light, 0.43f);

Expand Down

0 comments on commit d053f2b

Please sign in to comment.