ctkLayoutViewFactory.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QDebug>
  16. #include <QDomElement>
  17. #include <QList>
  18. #include <QPair>
  19. #include <QVector>
  20. #include <QWidget>
  21. // CTK includes
  22. #include "ctkLayoutViewFactory.h"
  23. class ctkLayoutViewFactoryPrivate
  24. {
  25. Q_DECLARE_PUBLIC(ctkLayoutViewFactory);
  26. public:
  27. ctkLayoutViewFactoryPrivate(ctkLayoutViewFactory& obj);
  28. ~ctkLayoutViewFactoryPrivate();
  29. void init();
  30. protected:
  31. ctkLayoutViewFactory* q_ptr;
  32. typedef QPair<QDomElement, QWidget*> ViewFactory;
  33. QVector<ViewFactory> Views;
  34. bool UseCachedViews;
  35. int NumberOfViewsInCurrentLayout;
  36. };
  37. //-----------------------------------------------------------------------------
  38. ctkLayoutViewFactoryPrivate::ctkLayoutViewFactoryPrivate(ctkLayoutViewFactory& object)
  39. : q_ptr(&object)
  40. , UseCachedViews(true)
  41. , NumberOfViewsInCurrentLayout( 0 )
  42. {
  43. }
  44. //-----------------------------------------------------------------------------
  45. ctkLayoutViewFactoryPrivate::~ctkLayoutViewFactoryPrivate()
  46. {
  47. }
  48. //-----------------------------------------------------------------------------
  49. void ctkLayoutViewFactoryPrivate::init()
  50. {
  51. }
  52. //-----------------------------------------------------------------------------
  53. // ctkLayoutViewFactory
  54. //-----------------------------------------------------------------------------
  55. ctkLayoutViewFactory::ctkLayoutViewFactory(QObject* parentObject)
  56. : QObject(parentObject)
  57. , d_ptr(new ctkLayoutViewFactoryPrivate(*this))
  58. {
  59. Q_D(ctkLayoutViewFactory);
  60. d->init();
  61. }
  62. //-----------------------------------------------------------------------------
  63. ctkLayoutViewFactory::~ctkLayoutViewFactory()
  64. {
  65. }
  66. //-----------------------------------------------------------------------------
  67. QStringList ctkLayoutViewFactory::supportedElementNames()const
  68. {
  69. return QStringList() << "view";
  70. }
  71. //-----------------------------------------------------------------------------
  72. bool ctkLayoutViewFactory::isElementSupported(QDomElement layoutElement)const
  73. {
  74. return this->supportedElementNames().contains(layoutElement.tagName());
  75. }
  76. //-----------------------------------------------------------------------------
  77. bool ctkLayoutViewFactory::useCachedViews()const
  78. {
  79. Q_D(const ctkLayoutViewFactory);
  80. return d->UseCachedViews;
  81. }
  82. //-----------------------------------------------------------------------------
  83. void ctkLayoutViewFactory::setUseCachedViews(bool cache)
  84. {
  85. Q_D(ctkLayoutViewFactory);
  86. d->UseCachedViews = cache;
  87. }
  88. //-----------------------------------------------------------------------------
  89. void ctkLayoutViewFactory::beginSetupLayout()
  90. {
  91. Q_D(ctkLayoutViewFactory);
  92. // A new layout is set, reset the number of views being used in the layout.
  93. d->NumberOfViewsInCurrentLayout = 0;
  94. }
  95. //-----------------------------------------------------------------------------
  96. void ctkLayoutViewFactory::endSetupLayout()
  97. {
  98. }
  99. //-----------------------------------------------------------------------------
  100. void ctkLayoutViewFactory::setupView(QDomElement viewElement, QWidget* view)
  101. {
  102. Q_ASSERT(view);
  103. view->setVisible(true);
  104. this->registerView(viewElement, view);
  105. }
  106. //-----------------------------------------------------------------------------
  107. QWidget* ctkLayoutViewFactory::viewFromXML(QDomElement layoutElement)
  108. {
  109. Q_D(ctkLayoutViewFactory);
  110. QWidgetList views = this->registeredViews(layoutElement);
  111. // The same XML element has already been processed, reuse the view associated
  112. // to it.
  113. if (views.count())
  114. {
  115. return views[0];
  116. }
  117. // The layout element does not match any existing one, however we can just reuse
  118. // one that was registered for a different layout element.
  119. if (this->useCachedViews() &&
  120. d->NumberOfViewsInCurrentLayout >= 0 &&
  121. d->NumberOfViewsInCurrentLayout < d->Views.count())
  122. {
  123. QWidget* view = d->Views[d->NumberOfViewsInCurrentLayout].second;
  124. return view;
  125. }
  126. return this->createViewFromXML(layoutElement);
  127. }
  128. //-----------------------------------------------------------------------------
  129. QWidget* ctkLayoutViewFactory::createViewFromXML(QDomElement layoutElement)
  130. {
  131. Q_UNUSED(layoutElement);
  132. return 0;
  133. }
  134. //-----------------------------------------------------------------------------
  135. QList<QWidget*> ctkLayoutViewFactory::viewsFromXML(QDomElement layoutElement)
  136. {
  137. Q_D(ctkLayoutViewFactory);
  138. QWidgetList views = this->registeredViews(layoutElement);
  139. if (views.count())
  140. {
  141. return views;
  142. }
  143. // The layout element does not match any existing one, however we can just reuse
  144. // one that was registered for a different layout element.
  145. // We use cached views (regardless of useCachedViews settings)
  146. // as this is required for showing all compatible views when multiple="true"
  147. // attribute is set.
  148. if (d->NumberOfViewsInCurrentLayout >= 0 &&
  149. d->NumberOfViewsInCurrentLayout < d->Views.count())
  150. {
  151. for (int i = d->NumberOfViewsInCurrentLayout; i < d->Views.count(); ++i)
  152. {
  153. views << d->Views[i].second;
  154. }
  155. return views;
  156. }
  157. return this->createViewsFromXML(layoutElement);
  158. }
  159. //-----------------------------------------------------------------------------
  160. QList<QWidget*> ctkLayoutViewFactory::createViewsFromXML(QDomElement layoutElement)
  161. {
  162. QWidgetList views;
  163. QWidget* view = this->createViewFromXML(layoutElement);
  164. if (view)
  165. {
  166. views << view;
  167. }
  168. return views;
  169. }
  170. //-----------------------------------------------------------------------------
  171. QList<QWidget*> ctkLayoutViewFactory::registeredViews()const
  172. {
  173. Q_D(const ctkLayoutViewFactory);
  174. QWidgetList res;
  175. foreach(ctkLayoutViewFactoryPrivate::ViewFactory p, d->Views)
  176. {
  177. res << p.second;
  178. }
  179. return res;
  180. }
  181. //-----------------------------------------------------------------------------
  182. QList<QWidget*> ctkLayoutViewFactory
  183. ::registeredViews(const QDomElement& layoutElement)const
  184. {
  185. Q_D(const ctkLayoutViewFactory);
  186. QWidgetList res;
  187. foreach(ctkLayoutViewFactoryPrivate::ViewFactory p, d->Views)
  188. {
  189. if (p.first == layoutElement)
  190. {
  191. res << p.second;
  192. }
  193. }
  194. return res;
  195. }
  196. //-----------------------------------------------------------------------------
  197. void ctkLayoutViewFactory::registerView(QDomElement layoutElement, QWidget* view)
  198. {
  199. Q_D(ctkLayoutViewFactory);
  200. QDomElement viewElement = this->layoutElement(view);
  201. if (!viewElement.isNull())
  202. { // replace the current view element with the new layout element.
  203. ctkLayoutViewFactoryPrivate::ViewFactory item(viewElement, view);
  204. int index = d->Views.indexOf(item);
  205. Q_ASSERT(index >= 0);
  206. d->Views[index].first = layoutElement;
  207. }
  208. else
  209. {
  210. d->Views.push_back(ctkLayoutViewFactoryPrivate::ViewFactory(layoutElement, view));
  211. }
  212. ++d->NumberOfViewsInCurrentLayout;
  213. }
  214. //-----------------------------------------------------------------------------
  215. void ctkLayoutViewFactory::unregisterView(QDomElement layoutElement, QWidget* view)
  216. {
  217. Q_D(ctkLayoutViewFactory);
  218. ctkLayoutViewFactoryPrivate::ViewFactory itemToRemove(layoutElement, view);
  219. for (int index = d->Views.indexOf(itemToRemove) ; index >= 0 ;
  220. index = d->Views.indexOf(itemToRemove))
  221. {
  222. d->Views.remove(index);
  223. }
  224. }
  225. //-----------------------------------------------------------------------------
  226. void ctkLayoutViewFactory::unregisterView(QWidget* view)
  227. {
  228. for (QDomElement viewElement = this->layoutElement(view);
  229. !viewElement.isNull();
  230. viewElement = this->layoutElement(view))
  231. {
  232. this->unregisterView(viewElement, view);
  233. }
  234. }
  235. //-----------------------------------------------------------------------------
  236. QDomElement ctkLayoutViewFactory::layoutElement(QWidget* view)const
  237. {
  238. Q_D(const ctkLayoutViewFactory);
  239. for (int index = 0 ; index < d->Views.count(); ++index)
  240. {
  241. if (d->Views[index].second == view)
  242. {
  243. return d->Views[index].first;
  244. }
  245. }
  246. return QDomElement();
  247. }