From 3174d63d392afecdb69abf31e5e12127ce79eec6 Mon Sep 17 00:00:00 2001
From: Christian Rapp <0x2a@posteo.org>
Date: Fri, 6 Nov 2015 22:31:46 +0100
Subject: [PATCH] New Version. Incompatible API changes
Bumped version number to 0.2
Renamed API functions:
(these are doing the same)
getOpen --> getActive
contentPaneOpened --> isActive
contentPaneClosed --> isInactive
Removed API functions:
(these are no longer needed)
closeContentPane
openContentPane
ContentPane::headerClicked is the new possibility to open/close
ContentPanes programmatically. You have to check with getActive yourself
before calling the function to see if the result is what you want it to
be.
Some code cleanup in internalAddContentPane and
internalInsertContentPane.
collapsible feature is now working.
Signed-off-by: Christian Rapp <0x2a@posteo.org>
---
CMakeLists.txt | 2 +-
README.md | 6 +--
doc/main_page.dox | 3 +-
include/qAccordion/contentpane.h | 57 +++++++++++----------
include/qAccordion/qaccordion.h | 3 ++
src/contentpane.cpp | 22 +++++----
src/qaccordion.cpp | 85 +++++++++++++++-----------------
test/mainwindow.cpp | 6 ++-
8 files changed, 99 insertions(+), 85 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0ce8dd5..c7adf80 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ option (QACCORDION_BUILD_TESTER OFF)
option (QACCORDION_EXTERNAL OFF)
set (qAccordion_VERSION_MAJOR 0)
-set (qAccordion_VERSION_MINOR 1)
+set (qAccordion_VERSION_MINOR 2)
set (qAccordion_VERSION_PATCH 0)
add_subdirectory(test)
diff --git a/README.md b/README.md
index 4cb6d91..a357097 100644
--- a/README.md
+++ b/README.md
@@ -112,8 +112,8 @@ If you find a Bug or have a feature request head over to github and open a new [
## ToDo ##
* Drag and Drop support. The API already supports moving Content Panes but only programmatically.
* User defined Icons and Icon position.
-* Changable Animation Type
-* Maybe much, maybe nothing. So far it covers all my use cases ;)
+* Definable animation type.
+* Trigger open / close not only on single mouse click (e.g. double click, mouse over).
## FAQ ##
@@ -137,4 +137,4 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
-`````
\ No newline at end of file
+`````
diff --git a/doc/main_page.dox b/doc/main_page.dox
index b04a5d7..8e4fd13 100644
--- a/doc/main_page.dox
+++ b/doc/main_page.dox
@@ -23,6 +23,7 @@
* used in the demo application located in the test folder.
*
* ## License
+ * ```
* Copyright (C) 2015 Christian Rapp
*
* This program is free software: you can redistribute it and/or modify
@@ -37,5 +38,5 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
- *
+ * ```
*/
diff --git a/include/qAccordion/contentpane.h b/include/qAccordion/contentpane.h
index 95edf4a..1a1721c 100644
--- a/include/qAccordion/contentpane.h
+++ b/include/qAccordion/contentpane.h
@@ -29,6 +29,7 @@
#include
#include "clickableframe.h"
+#include "qaccordion.h"
/**
* @brief Content Pane class
@@ -78,10 +79,10 @@ class ContentPane : public QWidget
explicit ContentPane(QString header, QFrame *content, QWidget *parent = 0);
/**
- * @brief Check if this Content pane is open
- * @return boolean True if open
+ * @brief Check if this Content pane is active
+ * @return boolean True if active
*/
- bool getOpen();
+ bool getActive();
/**
* @brief Get the content frame of the content pane
@@ -233,6 +234,7 @@ class ContentPane : public QWidget
uint getAnimationDuration();
signals:
+
/**
* @brief Clicked signal is emitted when the header is clicked
*/
@@ -240,34 +242,21 @@ class ContentPane : public QWidget
/**
* @brief Signal will be emitted after the open animation finished
*/
- void contentPaneOpened();
+ void isActive();
/**
* @brief Signal will be emitted after the close animation finished
*/
- void contentPaneClosed();
+ void isInactive();
public slots:
- /**
- * @brief Open the content pane
- *
- * @details
- * This will open the content pane if it is currently closed.
- * @warning
- * Currently there is no inbuild mechanism to close an already open
- * Content Pane when you open another one programmatically. Meaning you have
- * to take care of this yourself.
- */
- void openContentPane();
- /**
- * @brief Close the content pane
- *
- * @details
- * This will close the content pane if it is currently open.
- */
- void closeContentPane();
+ void headerClicked(QPoint pos);
private:
+ // yeah we are friends. this is important to keep openContentPane and
+ // closeContentPane private
+ friend class QAccordion;
+
ClickableFrame *header;
QFrame *container;
QFrame *content;
@@ -276,7 +265,7 @@ public slots:
int contentPaneFrameStyle;
int containerAnimationMaxHeight;
- bool open;
+ bool active;
std::unique_ptr openAnimation;
std::unique_ptr closeAnimation;
@@ -287,7 +276,25 @@ public slots:
void initAnimations();
private slots:
- void clickableFrameClicked(QPoint pos);
+
+ /**
+ * @brief Open the content pane
+ *
+ * @details
+ * This will open the content pane if it is currently closed.
+ * @warning
+ * Currently there is no inbuild mechanism to close an already open
+ * Content Pane when you open another one programmatically. Meaning you have
+ * to take care of this yourself.
+ */
+ void openContentPane();
+ /**
+ * @brief Close the content pane
+ *
+ * @details
+ * This will close the content pane if it is currently open.
+ */
+ void closeContentPane();
protected:
/**
diff --git a/include/qAccordion/qaccordion.h b/include/qAccordion/qaccordion.h
index 37ed55e..4766ea5 100644
--- a/include/qAccordion/qaccordion.h
+++ b/include/qAccordion/qaccordion.h
@@ -35,6 +35,8 @@
#include "config.h"
#include "contentpane.h"
+class ContentPane;
+
/**
* @brief QAccordion base class
*
@@ -365,6 +367,7 @@ public slots:
bool checkIndexError(uint index, bool sizeIndexAllowed,
const QString &errMessage);
+ void handleClickedSignal(ContentPane *cpane);
private slots:
void numberOfPanesChanged(int number);
diff --git a/src/contentpane.cpp b/src/contentpane.cpp
index 0157842..ab08948 100644
--- a/src/contentpane.cpp
+++ b/src/contentpane.cpp
@@ -31,7 +31,7 @@ ContentPane::ContentPane(QString header, QFrame *content, QWidget *parent)
this->initDefaults(std::move(header));
}
-bool ContentPane::getOpen() { return this->open; }
+bool ContentPane::getActive() { return this->active; }
QFrame *ContentPane::getContentFrame() { return this->content; }
@@ -51,7 +51,7 @@ void ContentPane::setMaximumHeight(int maxHeight)
{
this->containerAnimationMaxHeight = maxHeight;
- if (this->open)
+ if (this->getActive())
this->container->setMaximumHeight(this->containerAnimationMaxHeight);
this->openAnimation->setEndValue(this->containerAnimationMaxHeight);
this->closeAnimation->setStartValue(this->containerAnimationMaxHeight);
@@ -110,25 +110,25 @@ int ContentPane::getContainerFrameStyle()
void ContentPane::openContentPane()
{
- if (this->open)
+ if (this->getActive())
return;
this->openAnimation->start();
this->header->setCaretPixmap(clickcon::CARRET_ICON_OPENED);
- this->open = true;
+ this->active = true;
}
void ContentPane::closeContentPane()
{
- if (!this->open)
+ if (!this->getActive())
return;
this->closeAnimation->start();
this->header->setCaretPixmap(clickcon::CARRET_ICON_CLOSED);
- this->open = false;
+ this->active = false;
}
void ContentPane::initDefaults(QString header)
{
- this->open = false;
+ this->active = false;
this->headerFrameStyle = QFrame::Shape::StyledPanel | QFrame::Shadow::Raised;
this->contentPaneFrameStyle =
@@ -155,7 +155,7 @@ void ContentPane::initHeaderFrame(QString header)
this->layout()->addWidget(this->header);
QObject::connect(this->header, &ClickableFrame::singleClick, this,
- &ContentPane::clickableFrameClicked);
+ &ContentPane::headerClicked);
}
void ContentPane::initContainerContentFrame()
@@ -201,10 +201,12 @@ void ContentPane::initAnimations()
this->openAnimation->setEasingCurve(
QEasingCurve(QEasingCurve::Type::Linear));
this->closeAnimation->setEasingCurve(
- QEasingCurve(QEasingCurve::Type::Linear));
+ QEasingCurve(QEasingCurve::Type::Linear));
}
-void ContentPane::clickableFrameClicked(__attribute__((unused)) QPoint pos) { emit this->clicked(); }
+void ContentPane::headerClicked(__attribute__((unused)) QPoint pos) {
+ emit this->clicked();
+}
void ContentPane::paintEvent(__attribute__((unused)) QPaintEvent *event)
{
diff --git a/src/qaccordion.cpp b/src/qaccordion.cpp
index b012e05..52d0372 100644
--- a/src/qaccordion.cpp
+++ b/src/qaccordion.cpp
@@ -184,7 +184,7 @@ void QAccordion::getActiveContentPaneIndex(std::vector &indexVector)
indexVector.clear();
std::for_each(this->contentPanes.begin(), this->contentPanes.end(),
[&indexVector, this](ContentPane *pane) {
- if (pane->getOpen()) {
+ if (pane->getActive()) {
indexVector.push_back(
this->findContentPaneIndex("", nullptr, pane));
}
@@ -223,27 +223,8 @@ int QAccordion::internalAddContentPane(QString header, QFrame *cframe,
this->contentPanes.push_back(cpane);
// manage the clicked signal in a lambda expression
- QObject::connect(cpane, &ContentPane::clicked, [this, cpane]() {
- // if the clicked content pane is open we simply close it and return
- if (cpane->getOpen()) {
- cpane->closeContentPane();
- return;
- }
- // if it is not open we will open it and search our vector for other
- // panes that are already open.
- // TODO: Is it really necessary to search for more than one open cpane?
- if (!cpane->getOpen()) {
- // check if multiActive is allowed
- if (!this->getMultiActive()) {
- std::for_each(this->contentPanes.begin(),
- this->contentPanes.end(), [](ContentPane *pane) {
- if (pane->getOpen())
- pane->closeContentPane();
- });
- }
- cpane->openContentPane();
- }
- });
+ QObject::connect(cpane, &ContentPane::clicked,
+ [this, cpane]() { this->handleClickedSignal(cpane); });
emit numberOfContentPanesChanged(this->contentPanes.size());
@@ -276,29 +257,9 @@ bool QAccordion::internalInsertContentPane(uint index, QString header,
this->contentPanes.insert(this->contentPanes.begin() + index, cpane);
- // TODO: This code has to be merged with internalAddContentPane.
// manage the clicked signal in a lambda expression
- QObject::connect(cpane, &ContentPane::clicked, [this, cpane]() {
- // if the clicked content pane is open we simply close it and return
- if (cpane->getOpen()) {
- cpane->closeContentPane();
- return;
- }
- // if it is not open we will open it and search our vector for other
- // panes that are already open.
- // TODO: Is it really necessary to search for more than one open cpane?
- if (!cpane->getOpen()) {
- // check if multiActive is allowed
- if (!this->getMultiActive()) {
- std::for_each(this->contentPanes.begin(),
- this->contentPanes.end(), [](ContentPane *pane) {
- if (pane->getOpen())
- pane->closeContentPane();
- });
- }
- cpane->openContentPane();
- }
- });
+ QObject::connect(cpane, &ContentPane::clicked,
+ [this, cpane]() { this->handleClickedSignal(cpane); });
emit numberOfContentPanesChanged(this->contentPanes.size());
@@ -404,6 +365,42 @@ bool QAccordion::checkIndexError(uint index, bool sizeIndexAllowed,
return false;
}
+void QAccordion::handleClickedSignal(ContentPane *cpane)
+{
+ // if the clicked content pane is open we simply close it and return
+ if (cpane->getActive()) {
+ // if collapsible and multiActive are false we are not allowed to close
+ // this pane
+ if (!this->collapsible && !this->multiActive) {
+ return;
+ }
+ // when multiActive is true we have to check if there is any other open
+ // cpane. if so we can close this one
+ std::vector activePanes;
+ if (!this->collapsible) {
+ this->getActiveContentPaneIndex(activePanes);
+ if (activePanes.size() == 1)
+ return; // only one active --> good bye :)
+ }
+ cpane->closeContentPane();
+ return;
+ }
+ // if it is not open we will open it and search our vector for other
+ // panes that are already open.
+ // TODO: Is it really necessary to search for more than one open cpane?
+ if (!cpane->getActive()) {
+ // check if multiActive is allowed
+ if (!this->getMultiActive()) {
+ std::for_each(this->contentPanes.begin(), this->contentPanes.end(),
+ [](ContentPane *pane) {
+ if (pane->getActive())
+ pane->closeContentPane();
+ });
+ }
+ cpane->openContentPane();
+ }
+}
+
void QAccordion::numberOfPanesChanged(int number)
{
// automatically open contentpane if we have only one and collapsible is
diff --git a/test/mainwindow.cpp b/test/mainwindow.cpp
index c25e49b..c8cfa72 100644
--- a/test/mainwindow.cpp
+++ b/test/mainwindow.cpp
@@ -72,6 +72,9 @@ void MainWindow::networkRequestFinished(QNetworkReply *reply)
void MainWindow::contentPaneAdd(QAccordion *topAccordion)
{
+ ui->widgetControlAccordion->setCollapsible(false);
+ // good pratice is to check the return value of addContentPane. see the API
+ // Reference for more details
int indexAddPane = ui->widgetControlAccordion->addContentPane("Add Pane");
// Get the content frame
@@ -187,7 +190,8 @@ void MainWindow::contentPaneRemove(QAccordion *topAccordion)
topAccordion,
this]() {
if (headerName->text() != "") {
- bool status = topAccordion->removeContentPane(true, headerName->text());
+ bool status =
+ topAccordion->removeContentPane(true, headerName->text());
if (status) {
this->statusBar()->showMessage(
"Content Pane \"" + headerName->text() + "\" removed", 3000);