一、结果预览
二、核心代码
mainwindow.h
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenu>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Hide ribbon dock title bar
ui->ribbonDockWidget->setTitleBarWidget(new QWidget());
// Add tabs to ribbon
ui->ribbonTabWidget->addTab(QIcon("icons//briefcase_1.svg"), "Project");
ui->ribbonTabWidget->addTab(QIcon("icons//monitor_1.svg"), "View");
ui->ribbonTabWidget->addTab(QIcon("icons//engineering_1.svg"), "Tools");
ui->ribbonTabWidget->addTab(QIcon("icons//information_1.svg"), "Help");
// Add 'Open project' button
QToolButton *openProjectButton = new QToolButton;
openProjectButton->setText(tr("Open"));
openProjectButton->setToolTip(tr("Open existing project"));
openProjectButton->setIcon(QIcon("icons//live_folder_2.svg"));
openProjectButton->setEnabled(true);
ui->ribbonTabWidget->addButton("Project", "Project", openProjectButton);
// Add 'New project' button
QToolButton *newProjectButton = new QToolButton;
newProjectButton->setText(tr("New"));
newProjectButton->setToolTip(tr("Create new project"));
newProjectButton->setIcon(QIcon("icons//create_new_2.svg"));
newProjectButton->setEnabled(true);
ui->ribbonTabWidget->addButton("Project", "Project", newProjectButton);
// Add 'Save project' button
QToolButton *saveProjectButton = new QToolButton;
saveProjectButton->setText(tr("Save"));
saveProjectButton->setToolTip(tr("Save project"));
saveProjectButton->setIcon(QIcon("/icons/save_2.svg"));
saveProjectButton->setEnabled(false);
ui->ribbonTabWidget->addButton("Project", "Project", saveProjectButton);
// Add 'Open file' button
QToolButton *openFileButton = new QToolButton(this);
openFileButton->setText(tr("File"));
openFileButton->setToolTip(tr("Open file or directory"));
openFileButton->setIcon(QIcon("icons//add_folder_2.svg"));
// Add dropdown menu to button
openFileButton->setPopupMode(QToolButton::MenuButtonPopup);
QMenu *menu = new QMenu("Title");
//menu->addAction(QIcon(":/icons/folder_2.svg"),
// "Recent directory");
menu->addAction(QIcon("icons//file_2.svg"), "Recent file 1");
menu->addAction(QIcon("icons//file_2.svg"), "Recent file 2");
menu->addAction(QIcon("icons//file_2.svg"), "Recent file 3");
openFileButton->setMenu(menu);
ui->ribbonTabWidget->addButton("Project", "Import", openFileButton);
// Add 'Open database' button
QToolButton *openDatabaseButton = new QToolButton;
openDatabaseButton->setText(tr("Database"));
openDatabaseButton->setToolTip(tr("Connect to database"));
openDatabaseButton->setIcon(QIcon("icons//add_database_2.svg"));
ui->ribbonTabWidget->addButton("Project", "Import", openDatabaseButton);
// Add 'Connect to web service' button
QToolButton *connectWebserviceButton = new QToolButton;
connectWebserviceButton->setText(tr("Web service"));
connectWebserviceButton->setToolTip(tr("Connect to web service"));
connectWebserviceButton->setIcon(QIcon("icons//add_link_2.svg"));
ui->ribbonTabWidget->addButton("Project", "Import", connectWebserviceButton);
}
MainWindow::~MainWindow()
{
delete ui;
}
ribbon.h
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#ifndef RIBBONTABWIDGET_H
#define RIBBONTABWIDGET_H
#include <QTabWidget>
#include <QToolButton>
class Ribbon : public QTabWidget
{
Q_OBJECT
public:
explicit Ribbon(QWidget *parent = 0);
/// Add a tab to the ribbon.
///
/// \param[in] tabName Name of the tab
void addTab(const QString &tabName);
/// Add a tab to the ribbon.
///
/// \param[in] tabIcon Icon of the tab
/// \param[in] tabName Name of the tab
void addTab(const QIcon &tabIcon, const QString &tabName);
/// Remove a tab from the ribbon.
///
/// \param[in] tabName Name of the tab
void removeTab(const QString &tabName);
/// Add a group to the specified tab.
/// The specified tab is created if it does not exist.
///
/// \param[in] tabName Name of the tab
/// \param[in] groupName Name of the group
void addGroup(const QString &tabName, const QString &groupName);
/// Add a button to the specified group.
/// The specified group and tab are created if they do not exist.
///
/// \param[in] tabName Name of the tab
/// \param[in] groupName Name of the group
/// \param[in] button The button
void addButton(const QString &tabName, const QString &groupName, QToolButton *button);
/// Remove a button from the specified group.
/// Do nothing if the button, group or tab doesn't exist.
/// The button group and tab are also removed if they become empty due to
/// the removal of the button.
///
/// \param[in] tabName Name of the tab
/// \param[in] groupName Name of the group
/// \param[in] button The button
void removeButton(const QString &tabName, const QString &groupName, QToolButton *button);
};
#endif // RIBBONTABWIDGET_H
ribbon.cpp
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#include "ribbon.h"
#include "ribbontabcontent.h"
#include <QApplication>
#include <QStyleOption>
#include <QPainter>
Ribbon::Ribbon(QWidget *parent)
: QTabWidget(parent)
{
// Determine default colors
QColor bg = qApp->palette().color(QPalette::Background);
QColor mid = qApp->palette().color(QPalette::Mid);
// Note: the order in which the background/palette/stylesheet functions are
// called does matter. Should be same as in Qt designer.
setAutoFillBackground(true);
// Set stylesheet
QString styleSheetText = QString(
"QTabWidget::pane {"
" border-top: 1px solid rgb(%4, %5, %6);"
" position: absolute;"
" top: -1px;"
"}"
""
"QTabBar::tab {"
" padding-top: 5px;"
" padding-bottom: 5px;"
" padding-left: 10px;"
" padding-right: 10px;"
" margin-top: 1px;"
"}"
""
"QTabBar::tab::!selected {"
" border-bottom: 1px solid rgb(%4, %5, %6);"
" background-color:#ffffff;"
"}"
""
"QTabBar::tab:selected {"
" background-color: rgb(%1, %2, %3);"
" border-top: 1px solid rgb(%4, %5, %6);"
" border-right: 1px solid rgb(%4, %5, %6);"
" border-left: 1px solid rgb(%4, %5, %6);"
" border-bottom: 1px solid rgb(%1, %2, %3);"
"}"
""
"QTabBar::tab:hover"
"{"
" background-color: rgb(205, 232, 255);"
"}"
""
"QTabBar::tab:selected:hover {"
" background-color: rgb(%1, %2, %3);"
"}"
).arg(bg.red()).arg(bg.green()).arg(bg.blue())
.arg(mid.red()).arg(mid.green()).arg(mid.blue());
setStyleSheet(styleSheetText);
// Set background color
QPalette pal = palette();
pal.setColor(QPalette::Background, Qt::white);
setPalette(pal);
}
void Ribbon::addTab(const QString &tabName)
{
// Note: superclass QTabWidget also has a function addTab()
RibbonTabContent *ribbonTabContent = new RibbonTabContent;
QTabWidget::addTab(ribbonTabContent, tabName);
}
void Ribbon::addTab(const QIcon &tabIcon, const QString &tabName)
{
// Note: superclass QTabWidget also has a function addTab()
RibbonTabContent *ribbonTabContent = new RibbonTabContent;
QTabWidget::addTab(ribbonTabContent, tabIcon, tabName);
}
void Ribbon::removeTab(const QString &tabName)
{
// Find ribbon tab
for (int i = 0; i < count(); i++)
{
if (tabText(i).toLower() == tabName.toLower())
{
// Remove tab
QWidget *tab = QTabWidget::widget(i);
QTabWidget::removeTab(i);
delete tab;
break;
}
}
}
void Ribbon::addGroup(const QString &tabName, const QString &groupName)
{
// Find ribbon tab
QWidget *tab = nullptr;
for (int i = 0; i < count(); i++)
{
if (tabText(i).toLower() == tabName.toLower())
{
tab = QTabWidget::widget(i);
break;
}
}
if (tab != nullptr)
{
// Tab found
// Add ribbon group
RibbonTabContent *ribbonTabContent = static_cast<RibbonTabContent*>(tab);
ribbonTabContent->addGroup(groupName);
}
else
{
// Tab not found
// Create tab
addTab(tabName);
// Add ribbon group
addGroup(tabName, groupName);
}
}
void Ribbon::addButton(const QString &tabName, const QString &groupName, QToolButton *button)
{
// Find ribbon tab
QWidget *tab = nullptr;
for (int i = 0; i < count(); i++)
{
if (tabText(i).toLower() == tabName.toLower())
{
tab = QTabWidget::widget(i);
break;
}
}
if (tab != nullptr)
{
// Tab found
// Add ribbon button
RibbonTabContent *ribbonTabContent = static_cast<RibbonTabContent*>(tab);
ribbonTabContent->addButton(groupName, button);
}
else
{
// Tab not found.
// Create tab
addTab(tabName);
// Add ribbon button
addButton(tabName, groupName, button);
}
}
void Ribbon::removeButton(const QString &tabName, const QString &groupName, QToolButton *button)
{
// Find ribbon tab
QWidget *tab = nullptr;
for (int i = 0; i < count(); i++)
{
if (tabText(i).toLower() == tabName.toLower())
{
tab = QTabWidget::widget(i);
break;
}
}
if (tab != nullptr)
{
// Tab found
// Remove ribbon button
RibbonTabContent *ribbonTabContent = static_cast<RibbonTabContent*>(tab);
ribbonTabContent->removeButton(groupName, button);
if (ribbonTabContent->groupCount() == 0)
{
removeTab(tabName);
}
}
}
ribbonbuttongroup.h
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#ifndef RIBBONBUTTONGROUP_H
#define RIBBONBUTTONGROUP_H
#include <QWidget>
#include <QToolButton>
namespace Ui {
class RibbonButtonGroup;
}
class RibbonButtonGroup : public QWidget
{
Q_OBJECT
public:
explicit RibbonButtonGroup(QWidget *parent = 0);
virtual ~RibbonButtonGroup();
/// Set the title of the button group.
/// The title is shown underneath the buttons.
///
/// \param[in] title The title
void setTitle(const QString &title);
/// Get the title of the button group.
///
/// \return The title
QString title() const;
/// Get the number of buttons in the button group.
///
/// \return The number of buttons
int buttonCount() const;
/// Add a button to the group.
///
/// \param[in] button The button
void addButton(QToolButton *button);
/// Remove a button from the group.
///
/// \param[in] button The button
void removeButton(QToolButton *button);
private:
Ui::RibbonButtonGroup *ui;
QString m_title; ///< Title of the button group
};
#endif // RIBBONBUTTONGROUP_H
ribbonbuttongroup.cpp
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#include "ribbonbuttongroup.h"
#include "ui_ribbonbuttongroup.h"
#include <QToolButton>
RibbonButtonGroup::RibbonButtonGroup(QWidget *parent)
: QWidget(parent)
, ui(new Ui::RibbonButtonGroup)
, m_title("")
{
ui->setupUi(this);
}
RibbonButtonGroup::~RibbonButtonGroup()
{
delete ui;
}
void RibbonButtonGroup::setTitle(const QString &title)
{
m_title = title;
ui->label->setText(m_title);
}
QString RibbonButtonGroup::title() const
{
return m_title;
}
int RibbonButtonGroup::buttonCount() const
{
return ui->horizontalLayout->count();
}
void RibbonButtonGroup::addButton(QToolButton *button)
{
button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
button->setMinimumSize(48, 48);
button->setAutoRaise(true);
button->setIconSize(QSize(32,32));
button->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
ui->horizontalLayout->addWidget(button);
}
void RibbonButtonGroup::removeButton(QToolButton *button)
{
/// \todo What happens if button is not part of the layout?
ui->horizontalLayout->removeWidget(button);
}
ribbontabcontent.h
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#ifndef RIBBONTABCONTENT_H
#define RIBBONTABCONTENT_H
#include <QWidget>
#include <QToolButton>
namespace Ui {
class RibbonTabContent;
}
class RibbonTabContent : public QWidget
{
Q_OBJECT
public:
explicit RibbonTabContent(QWidget *parent = 0);
virtual ~RibbonTabContent();
/// Add a group to the tab content.
///
/// \param[in] groupName Name of the group
void addGroup(const QString &groupName);
/// Remove a group from the tab content.
///
/// \param[in] groupName Name of the group
void removeGroup(const QString &groupName);
/// Get the number of button groups in this tab content.
///
/// \return The number of button groups
int groupCount() const;
/// Add a button to the specified group.
/// The group is created if it does not exist.
///
/// \param[in] groupName Name of the group
/// \param[in] button The button
void addButton(const QString &groupName, QToolButton *button);
/// Remove a button from the specified group.
/// The group is also removed if it's empty.
///
/// \param[in] groupName Name of the group
/// \param[in] button The button
void removeButton(const QString &groupName, QToolButton *button);
private:
Ui::RibbonTabContent *ui;
};
#endif // RIBBONTABCONTENT_H
ribbontabcontent.cpp
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#include "ribbontabcontent.h"
#include "ui_ribbontabcontent.h"
#include "ribbonbuttongroup.h"
RibbonTabContent::RibbonTabContent(QWidget *parent)
: QWidget(parent)
, ui(new Ui::RibbonTabContent)
{
ui->setupUi(this);
}
RibbonTabContent::~RibbonTabContent()
{
delete ui;
}
void RibbonTabContent::addGroup(const QString &groupName)
{
RibbonButtonGroup *ribbonButtonGroup = new RibbonButtonGroup;
ribbonButtonGroup->setTitle(groupName);
ui->ribbonHorizontalLayout->addWidget(ribbonButtonGroup);
}
void RibbonTabContent::removeGroup(const QString &groupName)
{
// Find ribbon group
for (int i = 0; i < ui->ribbonHorizontalLayout->count(); i++)
{
RibbonButtonGroup *group = static_cast<RibbonButtonGroup*>(ui->ribbonHorizontalLayout->itemAt(i)->widget());
if (group->title().toLower() == groupName.toLower())
{
ui->ribbonHorizontalLayout->removeWidget(group); /// \todo :( No effect
delete group;
break;
}
}
/// \todo What if the group still contains buttons? Delete manually?
// Or automaticly deleted by Qt parent() system.
}
int RibbonTabContent::groupCount() const
{
return ui->ribbonHorizontalLayout->count();
}
void RibbonTabContent::addButton(const QString &groupName, QToolButton *button)
{
// Find ribbon group
RibbonButtonGroup *ribbonButtonGroup = nullptr;
for (int i = 0; i < ui->ribbonHorizontalLayout->count(); i++)
{
RibbonButtonGroup *group = static_cast<RibbonButtonGroup*>(ui->ribbonHorizontalLayout->itemAt(i)->widget());
if (group->title().toLower() == groupName.toLower())
{
ribbonButtonGroup = group;
break;
}
}
if (ribbonButtonGroup != nullptr)
{
// Group found
// Add ribbon button
ribbonButtonGroup->addButton(button);
}
else
{
// Group not found
// Add ribbon group
addGroup(groupName);
// Add ribbon button
addButton(groupName, button);
}
}
void RibbonTabContent::removeButton(const QString &groupName, QToolButton *button)
{
// Find ribbon group
RibbonButtonGroup *ribbonButtonGroup = nullptr;
for (int i = 0; i < ui->ribbonHorizontalLayout->count(); i++)
{
RibbonButtonGroup *group = static_cast<RibbonButtonGroup*>(ui->ribbonHorizontalLayout->itemAt(i)->widget());
if (group->title().toLower() == groupName.toLower())
{
ribbonButtonGroup = group;
break;
}
}
if (ribbonButtonGroup != nullptr)
{
// Group found
// Remove ribbon button
ribbonButtonGroup->removeButton(button);
if (ribbonButtonGroup->buttonCount() == 0)
{
// Empty button group
// Remove button group
removeGroup(groupName);
}
}
}
main.cpp
/*
* Copyright (C) Martijn Koopman
* All Rights Reserved
*
* This software is distributed WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.
*
*/
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}