[rkward/work/optionset_experiments] rkward: Small progress on accordion widget.
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Sat Oct 24 20:04:25 UTC 2015
Git commit b8cbf6596c1089f1d593a2c3749631a49329a48c by Thomas Friedrichsmeier.
Committed on 24/10/2015 at 20:04.
Pushed by tfry into branch 'work/optionset_experiments'.
Small progress on accordion widget.
M +1 -1 rkward/misc/CMakeLists.txt
M +68 -74 rkward/misc/rkaccordiontable.cpp
M +17 -44 rkward/misc/rkaccordiontable.h
M +6 -6 rkward/plugin/rkoptionset.cpp
M +3 -3 rkward/plugin/rkoptionset.h
http://commits.kde.org/rkward/b8cbf6596c1089f1d593a2c3749631a49329a48c
diff --git a/rkward/misc/CMakeLists.txt b/rkward/misc/CMakeLists.txt
index 35988bc..048a51a 100644
--- a/rkward/misc/CMakeLists.txt
+++ b/rkward/misc/CMakeLists.txt
@@ -26,7 +26,7 @@ SET(misc_STAT_SRCS
rkmessagecatalog.cpp
rkdbusapi.cpp
rkfindbar.cpp
- rktabslide.cpp
+ rkaccordiontable.cpp
)
QT4_AUTOMOC(${misc_STAT_SRCS})
diff --git a/rkward/misc/rkaccordiontable.cpp b/rkward/misc/rkaccordiontable.cpp
index 5d03824..2a307bf 100644
--- a/rkward/misc/rkaccordiontable.cpp
+++ b/rkward/misc/rkaccordiontable.cpp
@@ -1,7 +1,7 @@
/***************************************************************************
- rktabslide - description
+ rkaccordiontable - description
-------------------
- begin : Fri Jun 22 2015
+ begin : Fri Oct 24 2015
copyright : (C) 2015 by Thomas Friedrichsmeier
email : thomas.friedrichsmeier at kdemail.net
***************************************************************************/
@@ -15,100 +15,94 @@
* *
***************************************************************************/
-#include "rktabslide.h"
+#include "rkaccordiontable.h"
-#include <QSplitter>
-#include <QVBoxLayout>
-#include <QPainter>
#include <kvbox.h>
#include "../debug.h"
-RKTabSlide::RKTabSlide (QWidget* parent) : QWidget (parent) {
- RK_TRACE (MISC);
+class RKAccordionDummyModel : public QAbstractProxyModel {
+public:
+ RKAccordionDummyModel (QObject *parent) : QAbstractProxyModel (parent) {};
- new QVBoxLayout (this);
- splitter = new QSplitter (this);
- tab_bar = new RKTabSlideBar (0);
- splitter->addWidget (tab_bar);
- splitter->setCollapsible (0, false);
- content = new KVBox;
- splitter->addWidget (content);
- layout ()->addWidget (splitter);
+ QModelIndex mapFromSource (const QModelIndex& sindex) const {
+ return (createIndex (sindex.row () * 2 + 1, sindex.column ()));
+ }
- last_content_width = -1;
+ QModelIndex mapToSource (const QModelIndex& pindex) const {
+ int srow;
+ if (pindex.row () % 2) srow = (pindex.row () - 1) / 2;
+ else srow = pindex.row () / 2;
+ return (createIndex (srow, pindex.column ()));
+ }
+
+ Qt::ItemFlags flags (const QModelIndex& index) const {
+ if (index.row () % 2) return (Qt::NoItemFlags);
+ return QAbstractProxyModel::flags (index);
+ }
+
+ int rowCount (const QModelIndex& parent) const {
+ return sourceModel ()->rowCount (parent) * 2;
+ }
- connect (tab_bar, SIGNAL (activated(int)), this, SLOT (activate(int)));
-}
+ int columnCount(const QModelIndex& parent) const {
+ return sourceModel ()->columnCount (parent);
+ }
+};
-void RKTabSlide::activate (int index) {
+#include <QLabel>
+RKAccordionTable::RKAccordionTable (QWidget* parent) : QTableView (parent) {
RK_TRACE (MISC);
- if (index < 0) {
- int s = splitter->sizes ().value (1, 0);
- if (s > 0) last_content_width = s;
- splitter->setSizes (QList<int> () << width () << 0);
- tab_bar->setWide (true);
- } else {
- tab_bar->setWide (false);
- int s = last_content_width;
- if (s <= 0) {
- s = content->minimumWidth ();
- }
- splitter->setSizes (QList<int> () << width () - s << s);
- }
+ default_widget = new KVBox;
+ new QLabel ("This is the content\nExcept it's just a dummy!!!!!!!!!!!!!!!", default_widget);
+ setSelectionBehavior (SelectRows);
+ setSelectionMode (SingleSelection);
+ pmodel = new RKAccordionDummyModel (this);
}
-RKTabSlideBar::RKTabSlideBar (QWidget* parent) : QTreeView (parent) {
+RKAccordionTable::~RKAccordionTable () {
RK_TRACE (MISC);
- buttons = 0;
- setWide (false);
-
- QStyleOptionTabV3 toption;
- toption.shape = QTabBar::RoundedWest;
- tab_vspace = style()->pixelMetric (QStyle::PM_TabBarTabVSpace, &toption);
- tab_hspace = style()->pixelMetric (QStyle::PM_TabBarTabVSpace, &toption);
- tab_height = fontMetrics ().height () + tab_vspace;
-
- setItemsExpandable (false);
- setRootIsDecorated (false);
- setSelectionBehavior (QAbstractItemView::SelectRows);
- setSelectionMode (QAbstractItemView::SingleSelection);
+ delete default_widget;
}
-#error Gaaaaah. Perhaps base on QListView + QItemDelegate w/o clipping, instead?
-void RKTabSlideBar::drawRow (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
-// RK_TRACE (MISC);
-
- QStyleOptionTabV3 toption;
- toption.initFrom (this);
- toption.shape = QTabBar::RoundedWest;
- toption.rect = option.rect;
- toption.rect.moveTop (option.rect.y () + dirtyRegionOffset ().y () + tab_vspace);
- toption.rect.moveLeft (option.rect.x () + dirtyRegionOffset ().x () + tab_hspace);
- toption.text = index.data ().toString ();
-
- int current_row = currentIndex ().row ();
- if (current_row > 0) {
- int paint_row = index.row ();
- if (current_row == paint_row) toption.state |= QStyle::State_Selected;
- else if (current_row == (paint_row - 1)) toption.selectedPosition = QStyleOptionTabV3::PreviousIsSelected;
- else if (current_row == (paint_row + 1)) toption.selectedPosition = QStyleOptionTabV3::NextIsSelected;
- }
- style ()->drawControl (QStyle::CE_TabBarTabShape, &toption, painter);
- toption.shape = QTabBar::RoundedNorth;
- style ()->drawControl (QStyle::CE_TabBarTabLabel, &toption, painter);
+void RKAccordionTable::currentChanged (const QModelIndex& current, const QModelIndex& previous) {
+ RK_TRACE (MISC);
+ RK_ASSERT (current.isValid ());
+
+ int cur = current.row;
+ if (previous.isValid ()) {
+ int prev = previous.row;
+ int height = rowHeight (prev + 1);
+ hideRow (prev + 1);
+ setRowHeight (cur + 1, height);
+ }
+ showRow (cur + 1);
}
-void RKTabSlideBar::setWide (bool wide_format) {
+void RKAccordionTable::setModel (QAbstractItemModel* model) {
RK_TRACE (MISC);
- is_wide = wide_format;
- setHorizontalScrollBarPolicy (is_wide ? Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOff);
- // TODO: redraw
+ pmodel->setSourceModel (model);
+ QTableView::setModel (pmodel);
+
+ for (int i = 1; i < model->rowCount (); ++i) {
+ hideRow (i * 2 + 1);
+ }
+ if (model->rowCount () > 0) showRow (1);
+}
+
+void RKAccordionTable::resizeEvent (QResizeEvent* event) {
+ // TODO
+ QAbstractItemView::resizeEvent (event);
}
+// TODO
+// - add buttons to each row
+// - handle row removals
+// - handle resize
+
// KF5 TODO: remove:
-#include "rktabslide.moc"
+#include "rkaccordiontable.moc"
diff --git a/rkward/misc/rkaccordiontable.h b/rkward/misc/rkaccordiontable.h
index 52e765c..5fbd716 100644
--- a/rkward/misc/rkaccordiontable.h
+++ b/rkward/misc/rkaccordiontable.h
@@ -1,7 +1,7 @@
/***************************************************************************
- rktabslide - description
+ rkaccordiontable - description
-------------------
- begin : Fri Jun 22 2015
+ begin : Fri Oct 24 2015
copyright : (C) 2015 by Thomas Friedrichsmeier
email : thomas.friedrichsmeier at kdemail.net
***************************************************************************/
@@ -15,58 +15,31 @@
* *
***************************************************************************/
-#ifndef RKTABSLIDE_H
-#define RKTABSLIDE_H
+#ifndef RKACCORDIONTABLE_H
+#define RKACCORDIONTABLE_H
#include <QWidget>
-#include <QScrollArea>
-#include <QTreeView>
+#include <QTableView>
+#include <QAbstractProxyModel>
-class QSplitter;
-class RKTabSlideBar;
-class RKTabSlide : public QWidget {
- Q_OBJECT
-public:
- RKTabSlide (QWidget *parent);
-
- RKTabSlideBar *tabBar () const { return tab_bar; };
- QWidget *contentArea () const { return content; };
-public slots:
- void activate (int index);
-private:
- RKTabSlideBar *tab_bar;
- QSplitter *splitter;
- QWidget *content;
- int last_content_width;
-};
+class QAbstractItemModel;
-class RKTabSlideBar : public QTreeView { // basing on QTreeView, rather than QTableView, as the former is already designed for drawing row by row, rather than cell by cell
+class RKAccordionTable : public QTableView {
Q_OBJECT
public:
- RKTabSlideBar (QWidget* parent);
+ RKAccordionTable (QWidget *parent);
+ ~RKAccordionTable ();
- enum InternalButtons {
- Delete,
- Insert,
- Edit
- };
- void setInternalButtons (int buttons);
+ QWidget *defaultWidget () const { return default_widget; };
- void setWide (bool wide_format);
-signals:
- void deleteClicked (int index);
- void insertClicked (int index);
- void activated (int index);
+ void setModel (QAbstractItemModel *model);
protected:
- void drawRow (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; // re-implemented from QTreeView
- int sizeHintForRow (int) const { return tab_height; }; // re-implemented from QAbstractItemView: Rows have uniform size. TODO: Guess we also need a QItemDelegate implementing sizeHint().
+ void currentChanged (const QModelIndex& current, const QModelIndex& previous); // reimplemented to adjust selection / activate correct row
+ void resizeEvent (QResizeEvent* event); // reimplemented to make the current content widget stretch / shrink
+ void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); // reimplemented to switch to a different row, if current row is about to be removed
private:
- int currentindex;
- bool is_wide;
- int buttons;
- int tab_height;
- int tab_vspace;
- int tab_hspace;
+ QWidget *default_widget;
+ QAbstractProxyModel *pmodel;
};
#endif
diff --git a/rkward/plugin/rkoptionset.cpp b/rkward/plugin/rkoptionset.cpp
index a9b367f..5f8b06c 100644
--- a/rkward/plugin/rkoptionset.cpp
+++ b/rkward/plugin/rkoptionset.cpp
@@ -29,7 +29,7 @@
#include "rkstandardcomponent.h"
#include "../misc/rkcommonfunctions.h"
-#include "../misc/rktabslide.h"
+#include "../misc/rkaccordiontable.h"
#include "../misc/rkstandardicons.h"
#include "../misc/xmlhelper.h"
@@ -48,7 +48,7 @@ RKOptionSet::RKOptionSet (const QDomElement &element, RKComponent *parent_compon
min_rows = xml->getIntAttribute (element, "min_rows", 0, DL_INFO);
min_rows_if_any = xml->getIntAttribute (element, "min_rows_if_any", 1, DL_INFO);
max_rows = xml->getIntAttribute (element, "max_rows", INT_MAX, DL_INFO);
- exp_mode = (ExperimentalMode) xml->getMultiChoiceAttribute (element, "exp_mode", "regular;detached;tabbed", 2, DL_INFO);
+ exp_mode = (ExperimentalMode) xml->getMultiChoiceAttribute (element, "exp_mode", "regular;detached;accordion", 2, DL_INFO);
// build UI framework
QVBoxLayout *layout = new QVBoxLayout (this);
@@ -56,7 +56,7 @@ RKOptionSet::RKOptionSet (const QDomElement &element, RKComponent *parent_compon
if (exp_mode != Detached) layout->addWidget (switcher);
user_area = new KVBox (this);
switcher->addWidget (user_area);
- if (exp_mode == Tabbed) tabslide = new RKTabSlide (user_area);
+ if (exp_mode == Accordion) accordion = new RKAccordionTable (user_area);
updating_notice = new QLabel (i18n ("Updating status, please wait"), this);
switcher->addWidget (updating_notice);
update_timer.setInterval (0);
@@ -80,10 +80,10 @@ RKOptionSet::RKOptionSet (const QDomElement &element, RKComponent *parent_compon
// first build the contents, as we will need to refer to the elements inside, later
model = 0;
display = 0; // will be created from the builder, on demand -> createDisplay ()
- contents_container = new RKComponent (this, exp_mode == Tabbed ? tabslide->contentArea () : user_area);
+ contents_container = new RKComponent (this, exp_mode == RKOptionSet::Accordion ? accordion->defaultWidget () : user_area);
QDomElement content_element = xml->getChildElement (element, "content", DL_ERROR);
RKComponentBuilder *builder = new RKComponentBuilder (contents_container, content_element);
- builder->buildElement (content_element, *xml, exp_mode == Tabbed ? tabslide->contentArea () : user_area, false); // NOTE that parent widget != parent component, here, by intention. The point is that the display should not be disabled along with the contents
+ builder->buildElement (content_element, *xml, exp_mode == Accordion ? accordion->defaultWidget () : user_area, false); // NOTE that parent widget != parent component, here, by intention. The point is that the display should not be disabled along with the contents
builder->parseLogic (xml->getChildElement (element, "logic", DL_INFO), *xml, false);
builder->makeConnections ();
addChild ("contents", contents_container);
@@ -216,7 +216,7 @@ RKComponent *RKOptionSet::createDisplay (bool show_index, QWidget *parent) {
display_show_index = show_index;
model = new RKOptionSetDisplayModel (this);
if (exp_mode == Detached) display->setItemDelegate (new RKOptionSetDelegate (this));
- if (exp_mode == Tabbed) tabslide->tabBar ()->setModel (model);
+ if (exp_mode == Accordion) accordion->setModel (model);
}
display_buttons = new KHBox (dummy);
diff --git a/rkward/plugin/rkoptionset.h b/rkward/plugin/rkoptionset.h
index cf93d44..aa2e949 100644
--- a/rkward/plugin/rkoptionset.h
+++ b/rkward/plugin/rkoptionset.h
@@ -25,7 +25,7 @@
#include <QTimer>
#include <QSet>
-class RKTabSlide;
+class RKAccordionTable;
class QTreeView;
class QPushButton;
class RKOptionSetDisplayModel;
@@ -120,7 +120,7 @@ friend class RKOptionSetDisplayModel;
QStackedWidget *switcher;
QWidget *updating_notice;
QWidget *user_area;
- RKTabSlide *tabslide;
+ RKAccordionTable *accordion;
void updateUnfinishedRows ();
int return_to_row;
QTimer update_timer;
@@ -132,7 +132,7 @@ friend class RKOptionSetDisplayModel;
enum ExperimentalMode {
Regular,
Detached,
- Tabbed
+ Accordion
} exp_mode;
bool updating;
More information about the rkward-tracker
mailing list