PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/kdenetwork-4.8.97/kopete/protocols/jabber/jingle/jinglecallsgui.cpp

#
C++ | 568 lines | 412 code | 105 blank | 51 comment | 63 complexity | 4248f830374c868ae88c237a4f9d7fda MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0
  1. /*
  2. * jinglecallsgui.cpp - A GUI which displays all Jingle calls.
  3. *
  4. * Copyright (c) 2008 by Detlev Casanova <detlev.casanova@gmail.com>
  5. *
  6. * Kopete (c) by the Kopete developers <kopete-devel@kde.org>
  7. *
  8. * *************************************************************************
  9. * * *
  10. * * This program is free software; you can redistribute it and/or modify *
  11. * * it under the terms of the GNU General Public License as published by *
  12. * * the Free Software Foundation; either version 2 of the License, or *
  13. * * (at your option) any later version. *
  14. * * *
  15. * *************************************************************************
  16. */
  17. #include "jinglecallsgui.h"
  18. #include "jinglecallsmanager.h"
  19. #include "jabberjinglesession.h"
  20. #include "jabberjinglecontent.h"
  21. #include "jinglesession.h"
  22. #include "jinglecontent.h"
  23. #include <KDebug>
  24. static QString stateToString(JabberJingleSession::State s)
  25. {
  26. //TODO : more precise states...
  27. switch (s)
  28. {
  29. case JabberJingleSession::Pending :
  30. return "Pending";
  31. case JabberJingleSession::Active :
  32. return "Active";
  33. case JabberJingleSession::Ended :
  34. return "Ended";
  35. default :
  36. return "Unknown";
  37. }
  38. }
  39. JingleCallsGui::JingleCallsGui(JingleCallsManager* parent)
  40. : m_callsManager(parent)
  41. {
  42. kDebug() << "Created";
  43. ui.setupUi(this);
  44. setWindowTitle("Jingle calls");
  45. setupActions();
  46. model = new JingleCallsModel(m_callsManager->jabberSessions());
  47. ui.treeView->setModel(model);
  48. updater = new QTimer();
  49. connect(updater, SIGNAL(timeout()), this, SLOT(updateTime()));
  50. updater->start(1000);
  51. }
  52. JingleCallsGui::~JingleCallsGui()
  53. {
  54. kDebug() << "deleted";
  55. delete updater;
  56. delete model;
  57. }
  58. void JingleCallsGui::setupActions()
  59. {
  60. // Create a new session
  61. QAction *newSession = new QAction(tr("Add Content"), this);
  62. ui.toolBar->addAction(newSession);
  63. connect(newSession, SIGNAL(triggered()), this, SLOT(slotAddContent()));
  64. // Adds a content to the session.
  65. QAction *addContent = new QAction(tr("New Session"), this);
  66. ui.toolBar->addAction(addContent);
  67. connect(addContent, SIGNAL(triggered()), this, SLOT(slotNewSession()));
  68. // Terminate the whole session.
  69. QAction *terminate = new QAction(tr("Terminate"), this);
  70. ui.toolBar->addAction(terminate);
  71. connect(terminate, SIGNAL(triggered()), this, SLOT(slotTerminate()));
  72. // ^ Actions on sessions
  73. ui.toolBar->addSeparator();
  74. // v Actions on contents
  75. // Remove the content.
  76. QAction *remove = new QAction(tr("Remove"), this);
  77. ui.toolBar->addAction(remove);
  78. connect(remove, SIGNAL(triggered()), this, SLOT(slotRemove()));
  79. ui.toolBar->addSeparator();
  80. // quit
  81. QAction *close = new QAction(tr("Close"), this);
  82. ui.toolBar->addAction(close);
  83. connect(close, SIGNAL(triggered()), this, SLOT(slotClose()));
  84. }
  85. void JingleCallsGui::slotNewSession()
  86. {
  87. //TODO:Implement me !
  88. }
  89. void JingleCallsGui::slotAddContent()
  90. {
  91. //TODO:Implement me !
  92. }
  93. void JingleCallsGui::slotTerminate()
  94. {
  95. kDebug() << "Terminate session";
  96. TreeItem *item = static_cast<TreeItem*>(ui.treeView->currentIndex().internalPointer());
  97. if (item == 0 || item->session() == 0)
  98. return;
  99. item->session()->jingleSession()->sessionTerminate(); //FIXME:Maybe ask the manager to do that...
  100. removeSession(item->session());
  101. //TODO:Implement me !
  102. }
  103. void JingleCallsGui::slotRemove()
  104. {
  105. //TODO:Implement me !
  106. }
  107. void JingleCallsGui::slotClose()
  108. {
  109. hide();
  110. }
  111. void JingleCallsGui::addSession(JabberJingleSession* sess)
  112. {
  113. kDebug() << "Add session" << sess;
  114. if (!sess)
  115. return;
  116. // Insert Session
  117. QAbstractItemModel *model = ui.treeView->model();
  118. QModelIndex index = model->index(model->rowCount() - 1, 0);
  119. if (!model->insertRow(model->rowCount(), index.parent()))
  120. return;
  121. //kDebug() << "Session inserted in the model !";
  122. QVector<QVariant> sessData;
  123. sessData << sess->session()->to().full();
  124. sessData << stateToString(sess->state());
  125. sessData << sess->upTime().toString("HH:mm"); // FIXME: find a better formatting : don't show 0 at the beginning (no 00:03)
  126. for (int column = 0; column < model->columnCount(index.parent()); ++column)
  127. {
  128. QModelIndex child = model->index(index.row() + 1, column, index.parent());
  129. TreeItem *item = static_cast<TreeItem*>(child.internalPointer());
  130. item->setSessionPtr(sess);
  131. model->setData(child, sessData[column], Qt::EditRole);
  132. }
  133. // Insert Contents
  134. index = model->index(model->rowCount() - 1, 0);
  135. if (!model->insertRows(model->rowCount(), sess->contents().count(), index))
  136. return;
  137. //kDebug() << "Contents inserted in the model !";
  138. for (int i = 0; i < sess->contents().count(); i++)
  139. {
  140. QVector<QVariant> contData;
  141. contData << sess->contents()[i]->contentName();
  142. contData << "";
  143. contData << "";
  144. for (int column = 0; column < model->columnCount(index.parent()); ++column)
  145. {
  146. QModelIndex child = model->index(i, column, index);
  147. model->setData(child, contData[column], Qt::EditRole);
  148. }
  149. }
  150. }
  151. void JingleCallsGui::changeState(JabberJingleSession *sess)
  152. {
  153. JabberJingleSession::State s = sess->state();
  154. int i = 0;
  155. //Looking for the QModelIndex with the session sess.
  156. //root QModelIndex
  157. QAbstractItemModel *model = ui.treeView->model();
  158. QModelIndex child = model->index(0, 0);
  159. //QModelIndex child = rootIndex.child(0, 0);
  160. while (child.isValid())
  161. {
  162. kDebug() << child.data();
  163. TreeItem *childItem = static_cast<TreeItem*>(child.internalPointer());
  164. if (childItem == 0)
  165. kDebug() << "childItem is NULL";
  166. if (childItem->session() == sess)
  167. {
  168. // We have the right index :)
  169. //model->removeRow(i, child.parent());
  170. model->setData(model->index(child.row(), 1), QVariant(stateToString(s)), Qt::DisplayRole);
  171. break;
  172. }
  173. child = model->index(++i, 0);
  174. }
  175. }
  176. //This is run once every second.
  177. void JingleCallsGui::updateTime()
  178. {
  179. int i = 0;
  180. QAbstractItemModel *model = ui.treeView->model();
  181. QModelIndex child = model->index(0, 0);
  182. while (child.isValid())
  183. {
  184. TreeItem *childItem = static_cast<TreeItem*>(child.internalPointer());
  185. if (childItem->session() != 0)
  186. {
  187. // We have a session index, let's update it :)
  188. QTime t = childItem->session()->upTime();
  189. model->setData(model->index(child.row(), 2), QVariant(t.toString()), Qt::DisplayRole);
  190. }
  191. child = model->index(++i, 0);
  192. }
  193. }
  194. void JingleCallsGui::removeSession(JabberJingleSession* sess)
  195. {
  196. kDebug() << "Remove session" << sess;
  197. int i = 0;
  198. //Looking for the QModelIndex with the session sess.
  199. //root QModelIndex
  200. QAbstractItemModel *model = ui.treeView->model();
  201. QModelIndex child = model->index(0, 0);
  202. //QModelIndex child = rootIndex.child(0, 0);
  203. while (child.isValid())
  204. {
  205. kDebug() << child.data();
  206. TreeItem *childItem = static_cast<TreeItem*>(child.internalPointer());
  207. if (childItem == 0)
  208. kDebug() << "childItem is NULL";
  209. kDebug() << "Compare" << childItem->session() << "to" << sess;
  210. if (childItem->session() == sess)
  211. {
  212. //Children of this line will be automatically removed.
  213. model->removeRow(i, child.parent());
  214. }
  215. child = model->index(++i, 0);
  216. }
  217. //Don't delete it, just remove it from the QTreeView.
  218. }
  219. /*DEPRECATED(sessions retrieved from m_callsManager)*/void JingleCallsGui::setSessions(const QList<JabberJingleSession*>& sessions)
  220. {
  221. Q_UNUSED(sessions)
  222. }
  223. // Model/View
  224. // JingleCallsModel :
  225. JingleCallsModel::JingleCallsModel(const QList<JabberJingleSession*> &data, QObject *parent)
  226. : QAbstractItemModel(parent)
  227. {
  228. kDebug() << "Create Model";
  229. QVector<QVariant> rootData;
  230. rootData << "Session with" << "State" << "Time";
  231. rootItem = new TreeItem(rootData);
  232. setModelUp(data);
  233. }
  234. void JingleCallsModel::setModelUp(const QList<JabberJingleSession*> &sessions)
  235. {
  236. for (int i = 0; i < sessions.count(); i++)
  237. {
  238. QVector<QVariant> sessData;
  239. sessData << sessions[i]->session()->to().full();
  240. sessData << stateToString(sessions[i]->state());
  241. sessData << sessions[i]->upTime().toString("HH:mm"); // FIXME: find a better formatting : don't show 0 at the beginning (no 00:03)
  242. TreeItem *sessItem = new TreeItem(sessData, rootItem);
  243. sessItem->setSessionPtr(sessions[i]);
  244. for (int j = 0; j < sessions[i]->contents().count(); j++)
  245. {
  246. QVector<QVariant> contData;
  247. contData << sessions[i]->contents()[j]->contentName();
  248. TreeItem *contItem = new TreeItem(contData, sessItem);
  249. contItem->setContentPtr(sessions[i]->contents()[j]);
  250. sessItem->appendChild(contItem);
  251. }
  252. rootItem->appendChild(sessItem);
  253. }
  254. }
  255. JingleCallsModel::~JingleCallsModel()
  256. {
  257. delete rootItem;
  258. }
  259. QModelIndex JingleCallsModel::index(int row, int column, const QModelIndex& parent) const
  260. {
  261. if (!hasIndex(row, column, parent))
  262. return QModelIndex();
  263. TreeItem *parentItem;
  264. if (!parent.isValid())
  265. parentItem = rootItem;
  266. else
  267. parentItem = static_cast<TreeItem*>(parent.internalPointer());
  268. TreeItem *childItem = parentItem->child(row);
  269. if (childItem)
  270. return createIndex(row, column, childItem);
  271. else
  272. return QModelIndex();
  273. }
  274. QModelIndex JingleCallsModel::parent(const QModelIndex& index) const
  275. {
  276. if (!index.isValid())
  277. return QModelIndex();
  278. TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
  279. TreeItem *parentItem = childItem->parent();
  280. if (parentItem == rootItem)
  281. return QModelIndex();
  282. return createIndex(parentItem->row(), 0, parentItem);
  283. }
  284. int JingleCallsModel::rowCount(const QModelIndex& parent) const
  285. {
  286. TreeItem *parentItem;
  287. if (parent.column() > 0)
  288. return 0;
  289. if (!parent.isValid())
  290. parentItem = rootItem;
  291. else
  292. parentItem = static_cast<TreeItem*>(parent.internalPointer());
  293. return parentItem->childCount();
  294. }
  295. int JingleCallsModel::columnCount(const QModelIndex& parent) const
  296. {
  297. if (parent.isValid())
  298. return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
  299. else
  300. return rootItem->columnCount();
  301. }
  302. QVariant JingleCallsModel::data(const QModelIndex& index, int role) const
  303. {
  304. if (!index.isValid())
  305. return QVariant();
  306. if ((role != Qt::DisplayRole) && (role != Qt::EditRole))
  307. return QVariant();
  308. TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
  309. return item->data(index.column());
  310. }
  311. QVariant JingleCallsModel::headerData(int section, Qt::Orientation orientation,
  312. int role) const
  313. {
  314. if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
  315. return rootItem->data(section);
  316. return QVariant();
  317. }
  318. Qt::ItemFlags JingleCallsModel::flags(const QModelIndex& index) const
  319. {
  320. if (!index.isValid())
  321. return Qt::ItemIsEnabled;
  322. return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
  323. }
  324. bool JingleCallsModel::setData(const QModelIndex& index, const QVariant& value, int role)
  325. {
  326. if (role != Qt::EditRole && role != Qt::DisplayRole)
  327. return false;
  328. TreeItem *item = getItem(index);
  329. bool ret = item->setData(index.column(), value);
  330. if (ret)
  331. emit dataChanged(this->index(0, 0), this->index(rootItem->childCount(), 3));
  332. //FIXME: decrease the number of items in the interval.
  333. return ret;
  334. }
  335. bool JingleCallsModel::insertRows(int position, int rows, const QModelIndex& parent)
  336. {
  337. TreeItem *parentItem = getItem(parent);
  338. bool success = true;
  339. beginInsertRows(parent, position, position + rows - 1);
  340. for (int i = 0; i < rows; i++)
  341. {
  342. if (!parentItem->appendChild(rootItem->columnCount()))
  343. {
  344. success = false;
  345. break;
  346. }
  347. }
  348. endInsertRows();
  349. return success;
  350. }
  351. void JingleCallsModel::printTree()
  352. {
  353. kDebug() << "|-(rootItem)" << rootItem->data(0) << "|" << rootItem->data(1) << "|" << rootItem->data(2);
  354. for (int i = 0; i < rootItem->childCount(); i++)
  355. {
  356. TreeItem *sessItem = rootItem->child(i);
  357. kDebug() << " |-" << sessItem->data(0) << "|" << sessItem->data(1) << "|" << sessItem->data(2);
  358. for (int j = 0; j < sessItem->childCount(); j++)
  359. {
  360. TreeItem *contItem = sessItem->child(j);
  361. kDebug() << " |-" << contItem->data(0);
  362. }
  363. }
  364. }
  365. bool JingleCallsModel::removeRows(int position, int rows, const QModelIndex& parent)
  366. {
  367. TreeItem *parentItem = getItem(parent);
  368. bool success = true;
  369. beginRemoveRows(parent, position, position + rows - 1);
  370. success = parentItem->removeChildren(position, rows);
  371. endRemoveRows();
  372. return success;
  373. }
  374. TreeItem *JingleCallsModel::getItem(const QModelIndex& index) const
  375. {
  376. if (index.isValid())
  377. {
  378. TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
  379. if (item)
  380. return item;
  381. }
  382. //kDebug() << "Return ROOT Item";
  383. return rootItem;
  384. }
  385. // TreeItem
  386. TreeItem::TreeItem(const QVector<QVariant> &data, TreeItem *parent)
  387. {
  388. parentItem = parent;
  389. itemData = data;
  390. contentPtr = 0L;
  391. sessionPtr = 0L;
  392. }
  393. TreeItem::~TreeItem()
  394. {
  395. for (int i = 0; i < childItems.count(); i++)
  396. {
  397. delete childItems.takeAt(i);
  398. }
  399. }
  400. void TreeItem::setContentPtr(JabberJingleContent* c)
  401. {
  402. contentPtr = c;
  403. }
  404. void TreeItem::setSessionPtr(JabberJingleSession* s)
  405. {
  406. sessionPtr = s;
  407. }
  408. void TreeItem::appendChild(TreeItem* child)
  409. {
  410. childItems.append(child);
  411. }
  412. TreeItem *TreeItem::child(int row)
  413. {
  414. return childItems.value(row);
  415. }
  416. bool TreeItem::removeChildren(int pos, int count)
  417. {
  418. if (pos < 0 || pos + count > childItems.size())
  419. return false;
  420. for (int row = 0; row < count; ++row)
  421. {
  422. delete childItems.takeAt(pos);
  423. }
  424. return true;
  425. }
  426. bool TreeItem::appendChild(int columns)
  427. {
  428. //kDebug() << "Adding a TreeItem with" << columns << "columns";
  429. QVector<QVariant> data(columns);
  430. TreeItem *item = new TreeItem(data, this);
  431. childItems.append(item);
  432. return true;
  433. }
  434. bool TreeItem::setData(int column, const QVariant &val)
  435. {
  436. if (column < 0 || column >= itemData.size())
  437. return false;
  438. //kDebug() << "Set value" << val << "in column" << column;
  439. itemData[column] = val;
  440. return true;
  441. }
  442. int TreeItem::childCount() const
  443. {
  444. return childItems.count();
  445. }
  446. int TreeItem::row() const
  447. {
  448. if (parentItem)
  449. return parentItem->childItems.indexOf(const_cast<TreeItem*>(this));
  450. return 0;
  451. }
  452. int TreeItem::columnCount() const
  453. {
  454. return itemData.count();
  455. }
  456. QVariant TreeItem::data(int column) const
  457. {
  458. return itemData.value(column);
  459. }
  460. TreeItem *TreeItem::parent()
  461. {
  462. return parentItem;
  463. }