[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