LCOV - code coverage report
Current view: top level - src/tools/qt-gui/src - treeviewmodel.cpp (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 397 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 22 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "treeviewmodel.hpp"
      10             : 
      11             : #include <backends.hpp>
      12             : #include <kdbconfig.h> // for DEBUG and VERBOSE
      13             : #include <kdbease.h>
      14             : #include <kdbproposal.h> // for namespaces
      15             : #include <modules.hpp>
      16             : #include <plugin.hpp>
      17             : #include <plugins.hpp>
      18             : #include <toolexcept.hpp>
      19             : 
      20             : #if HAVE_DBUS
      21             : #include <QtDBus/QtDBus>
      22             : #endif
      23             : 
      24             : #include "kdblogger.h"
      25             : #include <merging/automergeconfiguration.hpp>
      26             : #include <merging/automergestrategy.hpp>
      27             : #include <merging/mergeconflictstrategy.hpp>
      28             : #include <merging/onesidestrategy.hpp>
      29             : #include <merging/onesidevaluestrategy.hpp>
      30             : #include <merging/threewaymerge.hpp>
      31             : 
      32             : using namespace std;
      33             : using namespace kdb;
      34             : using namespace kdb::tools;
      35             : using namespace kdb::tools::merging;
      36             : 
      37           0 : TreeViewModel::TreeViewModel (QObject * parentModel) : m_root ("/", KEY_END), m_kdb ()
      38             : {
      39             :         Q_UNUSED (parentModel);
      40           0 : }
      41             : 
      42           0 : TreeViewModel::TreeViewModel (MergingKDB * kdb, QObject * parentModel) : m_root ("/", KEY_END), m_kdb (kdb)
      43             : {
      44             :         Q_UNUSED (parentModel);
      45           0 :         connectDBus ();
      46           0 : }
      47             : 
      48           0 : TreeViewModel::TreeViewModel (const TreeViewModel & other)
      49           0 : : QAbstractListModel (), m_model (other.m_model), m_root (other.m_root), m_kdb (other.m_kdb)
      50             : 
      51             : {
      52           0 : }
      53             : 
      54           0 : int TreeViewModel::rowCount (const QModelIndex & parentIndex) const
      55             : {
      56             :         Q_UNUSED (parentIndex);
      57           0 :         return m_model.count ();
      58             : }
      59             : 
      60           0 : QVariant TreeViewModel::data (const QModelIndex & idx, int role) const
      61             : {
      62           0 :         if (!idx.isValid ())
      63             :         {
      64           0 :                 emit showMessage (tr ("Error"), tr ("Index not valid."),
      65           0 :                                   QString ("TreeViewModel::data: Index = %1,\nModel size = %2").arg (idx.row ()).arg (m_model.count ()));
      66             :                 return QVariant ();
      67             :         }
      68             : 
      69           0 :         if (idx.row () > (m_model.size () - 1))
      70             :         {
      71           0 :                 emit showMessage (tr ("Error"), QString (tr ("Index too high. ")),
      72           0 :                                   QString ("TreeViewModel::data: Index: %1").arg (idx.row ()));
      73             :                 return QVariant ();
      74             :         }
      75             : 
      76           0 :         ConfigNode * node = m_model.at (idx.row ()).data ();
      77             : 
      78           0 :         switch (role)
      79             :         {
      80             : 
      81             :         case Qt::DisplayRole:
      82             : 
      83             :         // TODO: document fallthrough if it was desired
      84             :         case NameRole:
      85           0 :                 return QVariant::fromValue (node->getName ());
      86             : 
      87             :         case PathRole:
      88           0 :                 return QVariant::fromValue (node->getPath ());
      89             : 
      90             :         case ValueRole:
      91           0 :                 return QVariant::fromValue (node->getValue ());
      92             : 
      93             :         case ChildCountRole:
      94           0 :                 return QVariant::fromValue (node->getChildCount ());
      95             : 
      96             :         case ChildrenRole:
      97           0 :                 return QVariant::fromValue (node->getChildren ());
      98             : 
      99             :         case ChildrenHaveNoChildrenRole:
     100           0 :                 return QVariant::fromValue (node->childrenHaveNoChildren ());
     101             : 
     102             :         case MetaValueRole:
     103           0 :                 return QVariant::fromValue (node->getMetaKeys ());
     104             : 
     105             :         case NodeRole:
     106             :                 return QVariant::fromValue (node);
     107             : 
     108             :         case ParentModelRole:
     109           0 :                 return QVariant::fromValue (node->getParentModel ());
     110             : 
     111             :         case IndexRole:
     112           0 :                 return QVariant::fromValue (idx.row ());
     113             : 
     114             :         case IsNullRole:
     115             :         {
     116           0 :                 if (node->getKey ())
     117           0 :                         return QVariant::fromValue (false);
     118             :                 else
     119           0 :                         return QVariant::fromValue (true);
     120             :         }
     121             : 
     122             :         case IsExpandedRole:
     123           0 :                 return QVariant::fromValue (node->isExpanded ());
     124             : 
     125             :         default:
     126           0 :                 emit showMessage (tr ("Error"), tr ("Unknown role: %1").arg (role), "TreeViewModel::data");
     127             :                 return QVariant ();
     128             :         }
     129             : }
     130             : 
     131           0 : bool TreeViewModel::setData (const QModelIndex & idx, const QVariant & modelData, int role)
     132             : {
     133           0 :         if (!idx.isValid () || idx.row () > (m_model.size () - 1))
     134             :         {
     135           0 :                 emit showMessage (tr ("Error"), tr ("Index not valid."),
     136           0 :                                   QString ("TreeViewModel::setData: Index = %1,\nModel size = %2").arg (idx.row ()).arg (m_model.count ()));
     137           0 :                 return false;
     138             :         }
     139             : 
     140           0 :         ConfigNodePtr node = m_model.at (idx.row ());
     141             : 
     142           0 :         switch (role)
     143             :         {
     144             : 
     145             :         case NameRole:
     146           0 :                 if (node->getName () != modelData.toString ())
     147             :                 {
     148           0 :                         node->setName (modelData.toString ());
     149           0 :                         node->setIsDirty (true);
     150             :                 }
     151             :                 break;
     152             : 
     153             :         case ValueRole:
     154           0 :                 if (node->getValue () != modelData)
     155             :                 {
     156           0 :                         node->setValue (modelData);
     157             :                 }
     158             :                 break;
     159             : 
     160             :         case MetaValueRole:
     161             :         {
     162           0 :                 QVariantList valueList = modelData.toList ();
     163           0 :                 node->setMeta (valueList.at (0).toString (), valueList.at (1));
     164             :                 break;
     165             :         }
     166             : 
     167             :         case IsExpandedRole:
     168           0 :                 node->setIsExpanded (modelData.toBool ());
     169             :         }
     170             : 
     171           0 :         emit dataChanged (idx, idx);
     172             : 
     173           0 :         return true;
     174             : }
     175             : 
     176           0 : int TreeViewModel::getIndexByName (const QString & name) const
     177             : {
     178           0 :         for (int i = 0; i < m_model.count (); i++)
     179             :         {
     180           0 :                 if (m_model.at (i)->getName () == name) return i;
     181             :         }
     182             : 
     183             :         return -1;
     184             : }
     185             : 
     186           0 : void TreeViewModel::importConfiguration (const QString & name, const QString & format, QString & file, const QVariantList & mergeStrategies)
     187             : {
     188           0 :         Key root (name.toStdString (), KEY_END);
     189           0 :         KeySet originalKeys = collectCurrentKeySet ();
     190           0 :         KeySet base = originalKeys.cut (root);
     191           0 :         printWarnings (cerr, root, true, true);
     192             : 
     193           0 :         KeySet importedKeys;
     194             : 
     195           0 :         string formatString = format.toStdString ();
     196           0 :         string fileString = file.remove ("file://").toStdString ();
     197             : 
     198           0 :         Modules modules;
     199           0 :         PluginPtr plugin = modules.load (formatString);
     200             : 
     201           0 :         Key errorKey (root);
     202           0 :         errorKey.setString (fileString);
     203             : 
     204           0 :         plugin->get (importedKeys, errorKey);
     205             : 
     206           0 :         stringstream ws;
     207           0 :         stringstream es;
     208           0 :         QString warnings;
     209           0 :         QString errors;
     210             : 
     211           0 :         printWarnings (ws, errorKey, true, true);
     212           0 :         warnings = QString::fromStdString (ws.str ());
     213           0 :         printError (es, errorKey, true, true);
     214           0 :         errors = QString::fromStdString (es.str ());
     215             : 
     216           0 :         if (!errors.isEmpty ())
     217             :         {
     218           0 :                 emit showMessage (tr ("Error"),
     219           0 :                                   tr ("Failed to import configuration from %1 to %2.").arg (file, QString::fromStdString (root.getName ())),
     220           0 :                                   errors);
     221           0 :                 return;
     222             :         }
     223             : 
     224           0 :         ThreeWayMerge merger;
     225             : 
     226           0 :         foreach (QVariant s, mergeStrategies)
     227             :         {
     228           0 :                 MergeConflictStrategy * strategy = getMergeStrategy (s.toString ());
     229             : 
     230           0 :                 if (strategy) merger.addConflictStrategy (strategy);
     231             :         }
     232             : 
     233           0 :         MergeResult result;
     234             : 
     235             :         try
     236             :         {
     237           0 :                 result = merger.mergeKeySet (
     238           0 :                         MergeTask (BaseMergeKeys (base, root), OurMergeKeys (base, root), TheirMergeKeys (importedKeys, root), root));
     239             :         }
     240           0 :         catch (...) // TODO: Which exceptions are possible?
     241             :         {
     242           0 :                 emit showMessage (tr ("Error"), tr ("Could not merge keys."), "");
     243             :         }
     244             : 
     245           0 :         if (!result.hasConflicts ())
     246             :         {
     247           0 :                 createNewNodes (result.getMergedKeys ());
     248             : 
     249           0 :                 if (importedKeys.size () > 0)
     250           0 :                         emit showMessage (tr ("Information"), tr ("Successfully imported %1 keys.").arg (importedKeys.size ()), "");
     251             :         }
     252             :         else
     253             :         {
     254           0 :                 KeySet conflictSet = result.getConflictSet ();
     255           0 :                 QStringList conflicts;
     256           0 :                 conflictSet.rewind ();
     257           0 :                 Key current;
     258             : 
     259           0 :                 while ((current = conflictSet.next ()))
     260             :                 {
     261           0 :                         QString ourConflict = QString::fromStdString (current.getMeta<string> ("conflict/operation/our"));
     262           0 :                         QString theirConflict = QString::fromStdString (current.getMeta<string> ("conflict/operation/their"));
     263             : 
     264           0 :                         conflicts.append (QString::fromStdString (current.getName ()));
     265           0 :                         conflicts.append ("Ours: " + ourConflict + ", Theirs " + theirConflict);
     266           0 :                         conflicts.append ("\n");
     267             :                 }
     268             : 
     269             :                 emit showMessage (
     270           0 :                         tr ("Error"),
     271           0 :                         tr ("The were conflicts importing %1 (%2 format) into %3, no configuration was imported.").arg (file, format, name),
     272           0 :                         conflicts.join ("\n"));
     273             :         }
     274             : }
     275             : 
     276           0 : void TreeViewModel::exportConfiguration (TreeViewModel * parentModel, int idx, QString format, QString file)
     277             : {
     278           0 :         KeySet ks = collectCurrentKeySet ();
     279           0 :         Key root = parentModel->model ().at (idx)->getKey ();
     280             : 
     281             :         // Node is only a filler
     282           0 :         if (!root) root = Key (parentModel->model ().at (idx)->getPath ().toStdString (), KEY_END);
     283             : 
     284           0 :         KeySet part (ks.cut (root));
     285             : 
     286           0 :         string formatString = format.toStdString ();
     287           0 :         string fileString = file.remove ("file://").toStdString ();
     288             : 
     289           0 :         Modules modules;
     290           0 :         PluginPtr plugin = modules.load (formatString);
     291             : 
     292           0 :         Key errorKey (root);
     293           0 :         errorKey.setString (fileString);
     294             : 
     295           0 :         plugin->set (part, errorKey);
     296             : 
     297           0 :         stringstream ws;
     298           0 :         stringstream es;
     299           0 :         QString warnings;
     300           0 :         QString errors;
     301             : 
     302           0 :         printWarnings (ws, errorKey, true, true);
     303           0 :         warnings = QString::fromStdString (ws.str ());
     304           0 :         printError (es, errorKey, true, true);
     305           0 :         errors = QString::fromStdString (es.str ());
     306             : 
     307           0 :         if (errors.isEmpty () && !warnings.isEmpty ())
     308           0 :                 emit showMessage (tr ("Information"),
     309           0 :                                   tr ("Successfully exported configuration below %1 to %2, warnings were issued.")
     310           0 :                                           .arg (QString::fromStdString (root.getName ()), file),
     311           0 :                                   "");
     312           0 :         else if (!errors.isEmpty () && warnings.isEmpty ())
     313           0 :                 emit showMessage (
     314           0 :                         tr ("Error"),
     315           0 :                         tr ("Failed to export configuration below %1 to %2.").arg (QString::fromStdString (root.getName ()), file), errors);
     316           0 :         else if (!errors.isEmpty () && !warnings.isEmpty ())
     317             :                 emit showMessage (
     318           0 :                         tr ("Error"),
     319           0 :                         tr ("Failed to export configuration below %1 to %2.").arg (QString::fromStdString (root.getName ()), file),
     320           0 :                         warnings + "\n" + errors);
     321           0 : }
     322             : 
     323           0 : KeySet TreeViewModel::collectCurrentKeySet ()
     324             : {
     325           0 :         KeySetVisitor ksVisit;
     326           0 :         accept (ksVisit);
     327             : 
     328           0 :         return ksVisit.getKeySet ();
     329             : }
     330             : 
     331           0 : Qt::ItemFlags TreeViewModel::flags (const QModelIndex & idx) const
     332             : {
     333           0 :         if (!idx.isValid ()) return Qt::ItemIsEnabled;
     334             : 
     335           0 :         return QAbstractItemModel::flags (idx) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
     336             : }
     337             : 
     338           0 : void TreeViewModel::accept (Visitor & visitor)
     339             : {
     340           0 :         visitor.visit (this);
     341           0 : }
     342             : 
     343           0 : QVariantMap TreeViewModel::get (const int & idx) const
     344             : {
     345           0 :         QVariantMap map;
     346             : 
     347           0 :         foreach (int k, roleNames ().keys ())
     348             :         {
     349           0 :                 map[roleNames ().value (k)] = data (index (idx, 0), k);
     350             :         }
     351             : 
     352           0 :         return map;
     353             : }
     354             : 
     355           0 : QVariant TreeViewModel::find (const QString & term)
     356             : {
     357           0 :         auto searchResults = new TreeViewModel;
     358           0 :         FindVisitor fVisit (searchResults, term);
     359           0 :         accept (fVisit);
     360             : 
     361           0 :         if (searchResults->rowCount () == 0)
     362             :         {
     363           0 :                 searchResults->model ().append (
     364           0 :                         ConfigNodePtr (new ConfigNode ("NotfoundNode", tr ("There were no results matching your query."), nullptr, this)));
     365             :         }
     366             : 
     367           0 :         QQmlEngine::setObjectOwnership (searchResults, QQmlApplicationEngine::CppOwnership);
     368             : 
     369           0 :         return QVariant::fromValue (searchResults);
     370             : }
     371             : 
     372           0 : bool TreeViewModel::removeRow (int row, const QModelIndex & parentIndex)
     373             : {
     374             :         Q_UNUSED (parentIndex);
     375             : 
     376           0 :         if (row < 0 || row > m_model.size () - 1)
     377             :         {
     378           0 :                 emit showMessage (tr ("Error"), tr ("Index not valid."),
     379           0 :                                   QString ("TreeViewModel::removeRow: Index = %1, Model size = %2").arg (m_model.size ()).arg (row));
     380           0 :                 return false;
     381             :         }
     382             : 
     383           0 :         beginRemoveRows (QModelIndex (), row, row);
     384             : 
     385           0 :         if (!m_model.isEmpty ()) m_model.removeAt (row);
     386             : 
     387           0 :         endRemoveRows ();
     388             : 
     389           0 :         int childCount = 0;
     390             : 
     391           0 :         foreach (ConfigNodePtr node, m_model)
     392             :         {
     393           0 :                 childCount += node->getChildCount ();
     394             :         }
     395             : 
     396           0 :         if (childCount == 0) emit expandNode (false);
     397             : 
     398           0 :         emit updateIndicator ();
     399             : 
     400           0 :         return true;
     401             : }
     402             : 
     403           0 : bool TreeViewModel::insertRow (int row, const QModelIndex & parentIndex)
     404             : {
     405             :         Q_UNUSED (parentIndex);
     406           0 :         ConfigNodePtr node (new ConfigNode);
     407           0 :         node->setName (QString::fromStdString (m_metaModelParent.getName ()));
     408           0 :         node->setKey (m_metaModelParent);
     409           0 :         node->setParentModel (this);
     410             : 
     411           0 :         beginInsertRows (QModelIndex (), row, row);
     412           0 :         m_model.insert (row, node);
     413           0 :         endInsertRows ();
     414             : 
     415           0 :         emit updateIndicator ();
     416             : 
     417           0 :         return true;
     418             : }
     419             : 
     420           0 : void TreeViewModel::insertRow (int row, ConfigNodePtr node, bool addParent)
     421             : {
     422           0 :         beginInsertRows (QModelIndex (), row, row);
     423           0 :         if (addParent) node->setParentModel (this);
     424           0 :         m_model.insert (row, node);
     425           0 :         endInsertRows ();
     426             : 
     427           0 :         emit updateIndicator ();
     428           0 : }
     429             : 
     430           0 : void TreeViewModel::insertMetaRow (int row, Key key, const QString & name)
     431             : {
     432           0 :         m_metaModelParent = key;
     433             : 
     434           0 :         if (m_metaModelParent)
     435             :         {
     436           0 :                 insertRow (row);
     437             :         }
     438             :         else
     439             :         {
     440           0 :                 QString keyName;
     441             : 
     442           0 :                 if (key)
     443           0 :                         keyName = QString::fromStdString (key.getFullName ());
     444             :                 else
     445           0 :                         keyName = name;
     446             : 
     447           0 :                 emit showMessage (tr ("Error"), tr ("Inserting of Metakey failed, \"%1\" is not valid.").arg (keyName), "");
     448             :         }
     449           0 : }
     450             : 
     451           0 : void TreeViewModel::sink (ConfigNodePtr node, QStringList keys, const Key & key)
     452             : {
     453           0 :         if (keys.length () == 0) return;
     454             : 
     455           0 :         bool isLeaf = (keys.length () == 1);
     456             : 
     457           0 :         QString name = keys.takeFirst ();
     458             : 
     459           0 :         if (node->hasChild (name) && !node->getChildByName (name)->isDirty ())
     460             :         {
     461           0 :                 if (node->getChildByName (name)->getKey () && node->getChildByName (name)->getKey ().getName () == key.getName ())
     462             :                 {
     463           0 :                         if (node->getChildByName (name)->getKey ().getName () == key.getName ())
     464             :                         {
     465           0 :                                 node->getChildByName (name)->updateNode (key);
     466             :                         }
     467             :                 }
     468             : 
     469           0 :                 sink (node->getChildByName (name), keys, key);
     470             :         }
     471             :         else
     472             :         {
     473           0 :                 if (node->hasChild (name)) node->getChildren ()->removeRow (node->getChildIndexByName (name));
     474             : 
     475           0 :                 ConfigNodePtr newNode;
     476             : 
     477           0 :                 if (isLeaf)
     478           0 :                         newNode = ConfigNodePtr (new ConfigNode (name, (node->getPath () + "/" + name), key, node->getChildren ()));
     479             :                 else
     480           0 :                         newNode = ConfigNodePtr (new ConfigNode (name, (node->getPath () + "/" + name), nullptr, node->getChildren ()));
     481             : 
     482           0 :                 node->appendChild (newNode);
     483             : 
     484           0 :                 sink (newNode, keys, key);
     485             :         }
     486             : }
     487             : 
     488           0 : void TreeViewModel::populateModel ()
     489             : {
     490           0 :         kdb::KeySet config;
     491           0 :         m_kdb->get (config, m_root);
     492           0 :         populateModel (config);
     493           0 : }
     494             : 
     495           0 : void TreeViewModel::populateModel (KeySet const & keySet)
     496             : {
     497           0 :         m_model.clear ();
     498             : 
     499             :         using namespace ckdb; // for namespaces
     500           0 :         for (int i = KEY_NS_FIRST; i <= KEY_NS_LAST; ++i)
     501             :         {
     502           0 :                 elektraNamespace ns = static_cast<elektraNamespace> (i);
     503           0 :                 ConfigNodePtr toAdd;
     504           0 :                 switch (ns)
     505             :                 {
     506             :                 case KEY_NS_SPEC:
     507           0 :                         toAdd = ConfigNodePtr (new ConfigNode ("spec", "spec", nullptr, this));
     508           0 :                         break;
     509             :                 case KEY_NS_PROC:
     510             :                         // TODO: add generic commandline parsing
     511             :                         break;
     512             :                 case KEY_NS_DIR:
     513           0 :                         toAdd = ConfigNodePtr (new ConfigNode ("dir", "dir", nullptr, this));
     514           0 :                         break;
     515             :                 case KEY_NS_USER:
     516           0 :                         toAdd = ConfigNodePtr (new ConfigNode ("user", "user", nullptr, this));
     517           0 :                         break;
     518             :                 case KEY_NS_SYSTEM:
     519           0 :                         toAdd = ConfigNodePtr (new ConfigNode ("system", "system", nullptr, this));
     520           0 :                         break;
     521             :                 case KEY_NS_EMPTY:
     522             :                         break;
     523             :                 case KEY_NS_NONE:
     524             :                         break;
     525             :                 case KEY_NS_META:
     526             :                         break;
     527             :                 case KEY_NS_CASCADING:
     528             :                         break;
     529             :                 }
     530           0 :                 if (toAdd) m_model << toAdd;
     531             :         }
     532             : 
     533           0 :         createNewNodes (keySet);
     534           0 : }
     535             : 
     536           0 : void TreeViewModel::createNewNodes (KeySet keySet)
     537             : {
     538             :         keySet.rewind ();
     539             : 
     540           0 :         while (keySet.next ())
     541             :         {
     542           0 :                 Key k = keySet.current ();
     543           0 :                 QStringList keys = getSplittedKeyname (k);
     544           0 :                 QString root = keys.takeFirst ();
     545             : 
     546           0 :                 for (int i = 0; i < m_model.count (); i++)
     547             :                 {
     548           0 :                         if (root == m_model.at (i)->getName ()) sink (m_model.at (i), keys, k);
     549             :                 }
     550             :         }
     551           0 : }
     552             : 
     553           0 : Key TreeViewModel::createNewKey (const QString & path, const QString & value, const QVariantMap metaData)
     554             : {
     555           0 :         Key key;
     556           0 :         key.setName (path.toStdString ());
     557           0 :         key.setString (value.toStdString ());
     558             : 
     559           0 :         for (QVariantMap::const_iterator iter = metaData.begin (); iter != metaData.end (); iter++)
     560             :         {
     561           0 :                 key.setMeta (iter.key ().toStdString (), iter.value ().toString ().toStdString ());
     562             :         }
     563             : 
     564           0 :         return key;
     565             : }
     566             : 
     567           0 : void TreeViewModel::append (ConfigNodePtr node)
     568             : {
     569           0 :         insertRow (rowCount (), node);
     570           0 : }
     571             : 
     572             : namespace
     573             : {
     574             : 
     575             : #if DEBUG && VERBOSE
     576             : std::string printKey (Key const & k)
     577             : {
     578             :         std::string ret;
     579             :         ret += k.getName ();
     580             : 
     581             :         if (ckdb::keyNeedSync (*k)) ret += "°";
     582             : 
     583             :         if (!k.isBinary ())
     584             :         {
     585             :                 ret += "=";
     586             :                 ret += k.getString ();
     587             :         }
     588             :         return ret;
     589             : }
     590             : 
     591             : void printKeys (KeySet const & theirs, KeySet const & base, KeySet const & ours)
     592             : {
     593             :         theirs.rewind ();
     594             :         base.rewind ();
     595             :         for (Key o : ours)
     596             :         {
     597             :                 std::string prefix ("user/guitest");
     598             :                 Key t = theirs.next ();
     599             :                 Key b = base.next ();
     600             :                 if (!((o && !o.getName ().compare (0, prefix.size (), prefix)) &&
     601             :                       (t && !t.getName ().compare (0, prefix.size (), prefix)) && (b && !b.getName ().compare (0, prefix.size (), prefix))))
     602             :                         continue;
     603             :                 std::cout << printKey (o);
     604             :                 ;
     605             :                 std::cout << "\t";
     606             :                 !b.isValid () ? std::cout << "none" : std::cout << printKey (b);
     607             :                 std::cout << "\t";
     608             :                 !t.isValid () ? std::cout << "none" : std::cout << printKey (t);
     609             :                 std::cout << std::endl;
     610             :         }
     611             : }
     612             : #endif
     613             : } // namespace
     614             : 
     615           0 : QStringList getConflicts (KeySet const & conflictSet)
     616             : {
     617           0 :         QStringList conflicts;
     618           0 :         conflictSet.rewind ();
     619           0 :         Key current;
     620             : 
     621           0 :         while ((current = conflictSet.next ()))
     622             :         {
     623           0 :                 QString ourConflict = QString::fromStdString (current.getMeta<string> ("conflict/operation/our"));
     624           0 :                 QString theirConflict = QString::fromStdString (current.getMeta<string> ("conflict/operation/their"));
     625             : 
     626           0 :                 conflicts.append (QString::fromStdString (current.getName ()));
     627           0 :                 conflicts.append ("Ours: " + ourConflict + ", Theirs " + theirConflict);
     628           0 :                 conflicts.append ("\n");
     629             :         }
     630           0 :         return conflicts;
     631             : }
     632             : 
     633           0 : void TreeViewModel::synchronize ()
     634             : {
     635           0 :         KeySet ours = collectCurrentKeySet ();
     636             : 
     637             :         try
     638             :         {
     639             : #if DEBUG && VERBOSE
     640             :                 std::cout << "guitest: start" << std::endl;
     641             :                 printKeys (ours, ours, ours);
     642             : #endif
     643             : 
     644           0 :                 ThreeWayMerge merger;
     645           0 :                 AutoMergeConfiguration configuration;
     646           0 :                 configuration.configureMerger (merger);
     647             : 
     648             :                 // write our config
     649           0 :                 m_kdb->synchronize (ours, m_root, merger);
     650             : 
     651             : #if DEBUG && VERBOSE
     652             :                 std::cout << "guitest: after get" << std::endl;
     653             :                 printKeys (ours, ours, ours);
     654             : #endif
     655             : 
     656           0 :                 createNewNodes (ours);
     657             :         }
     658           0 :         catch (MergingKDBException const & exc)
     659             :         {
     660           0 :                 QStringList conflicts = getConflicts (exc.getConflicts ());
     661           0 :                 emit showMessage (tr ("Error"), tr ("Synchronizing failed, conflicts occurred."), conflicts.join ("\n"));
     662             :         }
     663           0 :         catch (KDBException const & e)
     664             :         {
     665           0 :                 QMap<QString, QString> message = getErrorMessage (e);
     666             : 
     667             :                 emit showMessage (
     668           0 :                         tr ("Error"), message.value ("error"),
     669           0 :                         QString ("%1%2%3").arg (message.value ("at"), message.value ("mountpoint"), message.value ("configfile")));
     670             :         }
     671           0 : }
     672             : 
     673           0 : QMap<QString, QString> TreeViewModel::getErrorMessage (KDBException const & e)
     674             : {
     675           0 :         QRegExp error_regex ("Sorry, ((.*\\n){2})");
     676           0 :         QRegExp at_regex ("At: (.*)\\n");
     677           0 :         QRegExp mountpoint_regex ("Mountpoint: (.*)\\n");
     678           0 :         QRegExp configfile_regex ("Configfile: (.*)\\n");
     679             : 
     680           0 :         QMap<QString, QString> message;
     681           0 :         QString error = QString (e.what ());
     682             : 
     683           0 :         error_regex.setMinimal (true);
     684           0 :         at_regex.setMinimal (true);
     685           0 :         mountpoint_regex.setMinimal (true);
     686           0 :         configfile_regex.setMinimal (true);
     687             : 
     688           0 :         error_regex.indexIn (error);
     689           0 :         at_regex.indexIn (error);
     690           0 :         mountpoint_regex.indexIn (error);
     691           0 :         configfile_regex.indexIn (error);
     692             : 
     693           0 :         message.insert ("error", error_regex.cap ());
     694           0 :         message.insert ("at", at_regex.cap ());
     695           0 :         message.insert ("mountpoint", mountpoint_regex.cap ());
     696           0 :         message.insert ("configfile", configfile_regex.cap ());
     697             : 
     698             : 
     699           0 :         return message;
     700             : }
     701             : 
     702           0 : void TreeViewModel::clearMetaModel ()
     703             : {
     704           0 :         beginResetModel ();
     705           0 :         m_model.clear ();
     706           0 :         endResetModel ();
     707           0 : }
     708             : 
     709           0 : void TreeViewModel::unMountBackend (QString backendName)
     710             : {
     711           0 :         KeySet keySet = collectCurrentKeySet ();
     712           0 :         Backends::umount (backendName.toStdString (), keySet);
     713           0 :         populateModel (keySet);
     714           0 :         synchronize ();
     715           0 : }
     716             : 
     717           0 : void TreeViewModel::refresh ()
     718             : {
     719           0 :         layoutAboutToBeChanged ();
     720           0 :         layoutChanged ();
     721             : 
     722           0 :         emit updateIndicator ();
     723           0 : }
     724             : 
     725           0 : QString TreeViewModel::getCurrentArrayNo () const
     726             : {
     727           0 :         ConfigNodePtr max (nullptr);
     728             : 
     729           0 :         foreach (ConfigNodePtr node, m_model)
     730             :         {
     731           0 :                 if (node->getName ().startsWith ("#"))
     732             :                 {
     733           0 :                         max = node;
     734             :                 }
     735             :         }
     736             : 
     737           0 :         if (max)
     738             :         {
     739           0 :                 Key k = max->getKey ();
     740           0 :                 ckdb::elektraArrayIncName (k.getKey ());
     741           0 :                 return QString::fromStdString (k.getBaseName ());
     742             :         }
     743             : 
     744           0 :         return "#0";
     745             : }
     746             : 
     747           0 : void TreeViewModel::refreshArrayNumbers ()
     748             : {
     749           0 :         QList<ConfigNodePtr> arrayElements;
     750             : 
     751           0 :         foreach (ConfigNodePtr node, m_model)
     752             :         {
     753           0 :                 if (node->getName ().startsWith ("#"))
     754             :                 {
     755           0 :                         arrayElements.append (node);
     756             :                 }
     757             :         }
     758             : 
     759           0 :         if (!arrayElements.isEmpty ())
     760             :         {
     761             : 
     762           0 :                 arrayElements.at (0)->setName ("#0");
     763             : 
     764           0 :                 if (arrayElements.count () > 1)
     765             :                 {
     766             : 
     767           0 :                         for (int i = 1; i < arrayElements.count (); i++)
     768             :                         {
     769           0 :                                 Key k = arrayElements.at (i - 1)->getKey ().dup ();
     770           0 :                                 ckdb::elektraArrayIncName (k.getKey ());
     771           0 :                                 arrayElements.at (i)->setName (QString::fromStdString (k.getBaseName ()));
     772             :                         }
     773             :                 }
     774             :         }
     775           0 : }
     776             : 
     777           0 : QStringList TreeViewModel::mountedBackends ()
     778             : {
     779           0 :         KeySet keySet = collectCurrentKeySet ();
     780             : 
     781           0 :         Backends::BackendInfoVector mtab = Backends::getBackendInfo (keySet);
     782             : 
     783           0 :         QStringList mountedBends;
     784             : 
     785           0 :         for (Backends::BackendInfoVector::const_iterator it = mtab.begin (); it != mtab.end (); ++it)
     786             :         {
     787           0 :                 mountedBends.append (QString::fromStdString (it->name));
     788             :         }
     789             : 
     790             :         // cannot read the size of the QStringList in QML
     791           0 :         if (mountedBends.isEmpty ()) mountedBends.append ("empty");
     792             : 
     793           0 :         return mountedBends;
     794             : }
     795             : 
     796           0 : QStringList TreeViewModel::getSplittedKeyname (const Key & key)
     797             : {
     798           0 :         QStringList names;
     799             : 
     800           0 :         for (auto && elem : key)
     801             :         {
     802           0 :                 names.append (QString::fromStdString (elem));
     803             :         }
     804             : 
     805           0 :         return names;
     806             : }
     807             : 
     808           0 : void TreeViewModel::discardModel ()
     809             : {
     810           0 :         delete this;
     811           0 : }
     812             : 
     813           0 : MergeConflictStrategy * TreeViewModel::getMergeStrategy (const QString & mergeStrategy)
     814             : {
     815           0 :         if (mergeStrategy == "Preserve")
     816           0 :                 return new AutoMergeStrategy ();
     817           0 :         else if (mergeStrategy == "Ours")
     818           0 :                 return new OneSideStrategy (OURS);
     819           0 :         else if (mergeStrategy == "Theirs")
     820           0 :                 return new OneSideStrategy (THEIRS);
     821           0 :         else if (mergeStrategy == "Base")
     822           0 :                 return new OneSideStrategy (BASE);
     823           0 :         else if (mergeStrategy == "None")
     824             :                 return nullptr;
     825             : 
     826             :         return nullptr;
     827             : }
     828             : 
     829           0 : void TreeViewModel::showConfigNodeMessage (QString title, QString text, QString detailedText)
     830             : {
     831           0 :         emit showMessage (title, text, detailedText);
     832           0 : }
     833             : 
     834           0 : void TreeViewModel::connectDBus ()
     835             : {
     836             : #if HAVE_DBUS
     837           0 :         if (QDBusConnection::sessionBus ().connect (QString (), "/org/libelektra/configuration", "org.libelektra", QString (), this,
     838             :                                                     SLOT (configChanged (QString))))
     839             :         {
     840             :                 ELEKTRA_LOG ("Successfully connected to DBus");
     841             :         }
     842             :         else
     843             :         {
     844             :                 ELEKTRA_LOG ("Failed to connect to DBus");
     845             :         }
     846             : #else
     847             :         ELEKTRA_LOG ("No DBus support");
     848             : #endif
     849           0 : }
     850             : 
     851           0 : void TreeViewModel::configChanged (QString msg)
     852             : {
     853             :         Q_UNUSED (msg)
     854             :         ELEKTRA_LOG ("config changed: %s", msg.toLocal8Bit ().data ());
     855             : 
     856           0 :         synchronize ();
     857           0 :         refresh ();
     858           0 : }
     859             : 
     860           0 : QHash<int, QByteArray> TreeViewModel::roleNames () const
     861             : {
     862           0 :         QHash<int, QByteArray> roles;
     863             : 
     864           0 :         roles[NameRole] = "name";
     865           0 :         roles[PathRole] = "path";
     866           0 :         roles[ValueRole] = "value";
     867           0 :         roles[ChildCountRole] = "childCount";
     868           0 :         roles[ChildrenRole] = "children";
     869           0 :         roles[ChildrenHaveNoChildrenRole] = "childrenHaveNoChildren";
     870           0 :         roles[MetaValueRole] = "metaValue";
     871           0 :         roles[NodeRole] = "node";
     872           0 :         roles[ParentModelRole] = "parentModel";
     873           0 :         roles[IndexRole] = "index";
     874           0 :         roles[IsNullRole] = "isNull";
     875           0 :         roles[IsExpandedRole] = "isExpanded";
     876             : 
     877           0 :         return roles;
     878           0 : }

Generated by: LCOV version 1.13