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);