Add context menu on transaction list: copy label, copy address, edit label, show...
[novacoin.git] / src / qt / transactiontablemodel.cpp
index e49629c..17622e0 100644 (file)
@@ -3,6 +3,8 @@
 #include "transactionrecord.h"
 #include "guiconstants.h"
 #include "transactiondesc.h"
+#include "walletmodel.h"
+#include "addresstablemodel.h"
 
 #include "headers.h"
 
 #include <QColor>
 #include <QTimer>
 #include <QIcon>
+#include <QDateTime>
 #include <QtAlgorithms>
 
-const QString TransactionTableModel::Sent = "s";
-const QString TransactionTableModel::Received = "r";
-const QString TransactionTableModel::Other = "o";
-
 // Credit and Debit columns are right-aligned as they contain numbers
 static int column_alignments[] = {
         Qt::AlignLeft|Qt::AlignVCenter,
@@ -204,12 +203,13 @@ struct TransactionTablePriv
 
 };
 
-TransactionTableModel::TransactionTableModel(CWallet* wallet, QObject *parent):
+TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *parent):
         QAbstractTableModel(parent),
         wallet(wallet),
+        walletModel(parent),
         priv(new TransactionTablePriv(wallet, this))
 {
-    columns << tr("Status") << tr("Date") << tr("Type") << tr("Address") << tr("Amount");
+    columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount");
 
     priv->refreshWallet();
 
@@ -276,15 +276,34 @@ QVariant TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) con
         status = tr("Open until %1").arg(GUIUtil::DateTimeStr(wtx->status.open_for));
         break;
     case TransactionStatus::Offline:
-        status = tr("Offline (%1)").arg(wtx->status.depth);
+        status = tr("Offline (%1 confirmations)").arg(wtx->status.depth);
         break;
     case TransactionStatus::Unconfirmed:
-        status = tr("Unconfirmed (%1/%2)").arg(wtx->status.depth).arg(TransactionRecord::NumConfirmations);
+        status = tr("Unconfirmed (%1 of %2 confirmations required)").arg(wtx->status.depth).arg(TransactionRecord::NumConfirmations);
         break;
     case TransactionStatus::HaveConfirmations:
-        status = tr("Confirmed (%1)").arg(wtx->status.depth);
+        status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth);
         break;
     }
+    if(wtx->type == TransactionRecord::Generated)
+    {
+        status += "\n\n";
+        switch(wtx->status.maturity)
+        {
+        case TransactionStatus::Immature:
+            status += tr("Mined balance will be available in %n more blocks", "",
+                           wtx->status.matures_in);
+            break;
+        case TransactionStatus::Mature:
+            break;
+        case TransactionStatus::MaturesWarning:
+            status += tr("This block was not received by any other nodes and will probably not be accepted!");
+            break;
+        case TransactionStatus::NotAccepted:
+            status += tr("Generated but not accepted");
+            break;
+        }
+    }
 
     return QVariant(status);
 }
@@ -302,25 +321,20 @@ QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const
 }
 
 /* Look up address in address book, if found return
-     address[0:12]... (label)
+     address (label)
    otherwise just return address
  */
-std::string TransactionTableModel::lookupAddress(const std::string &address) const
+QString TransactionTableModel::lookupAddress(const std::string &address) const
 {
-    std::string description;
-    CRITICAL_BLOCK(wallet->cs_mapAddressBook)
+    QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address));
+    QString description;
+    if(label.isEmpty())
     {
-        std::map<std::string, std::string>::iterator mi = wallet->mapAddressBook.find(address);
-        if (mi != wallet->mapAddressBook.end() && !(*mi).second.empty())
-        {
-            std::string label = (*mi).second;
-            description += address.substr(0,12) + "... ";
-            description += "(" + label + ")";
-        }
-        else
-        {
-            description += address;
-        }
+        description = QString::fromStdString(address);
+    }
+    else
+    {
+        description = label + QString(" (") + QString::fromStdString(address) + QString(")");
     }
     return description;
 }
@@ -347,7 +361,7 @@ QVariant TransactionTableModel::formatTxType(const TransactionRecord *wtx) const
         description = tr("Payment to yourself");
         break;
     case TransactionRecord::Generated:
-        description = tr("Generated");
+        description = tr("Mined");
         break;
     }
     return QVariant(description);
@@ -360,13 +374,13 @@ QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx)
     switch(wtx->type)
     {
     case TransactionRecord::RecvWithAddress:
-        description = QString::fromStdString(lookupAddress(wtx->address));
+        description = lookupAddress(wtx->address);
         break;
     case TransactionRecord::RecvFromIP:
         description = QString::fromStdString(wtx->address);
         break;
     case TransactionRecord::SendToAddress:
-        description = QString::fromStdString(lookupAddress(wtx->address));
+        description = lookupAddress(wtx->address);
         break;
     case TransactionRecord::SendToIP:
         description = QString::fromStdString(wtx->address);
@@ -375,59 +389,66 @@ QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx)
         description = QString();
         break;
     case TransactionRecord::Generated:
-        switch(wtx->status.maturity)
-        {
-        case TransactionStatus::Immature:
-            description = tr("(matures in %n more blocks)", "",
-                           wtx->status.matures_in);
-            break;
-        case TransactionStatus::Mature:
-            description = QString();
-            break;
-        case TransactionStatus::MaturesWarning:
-            description = tr("(Warning: This block was not received by any other nodes and will probably not be accepted!)");
-            break;
-        case TransactionStatus::NotAccepted:
-            description = tr("(not accepted)");
-            break;
-        }
+        description = QString();
         break;
     }
     return QVariant(description);
 }
 
-QVariant TransactionTableModel::formatTxAmount(const TransactionRecord *wtx) const
+QVariant TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed) const
 {
     QString str = QString::fromStdString(FormatMoney(wtx->credit + wtx->debit));
-    if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature)
+    if(showUnconfirmed)
     {
-        str = QString("[") + str + QString("]");
+        if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature)
+        {
+            str = QString("[") + str + QString("]");
+        }
     }
     return QVariant(str);
 }
 
 QVariant TransactionTableModel::formatTxDecoration(const TransactionRecord *wtx) const
 {
-    switch(wtx->status.status)
+    if(wtx->type == TransactionRecord::Generated)
     {
-    case TransactionStatus::OpenUntilBlock:
-    case TransactionStatus::OpenUntilDate:
-        return QColor(64,64,255);
-        break;
-    case TransactionStatus::Offline:
-        return QColor(192,192,192);
-    case TransactionStatus::Unconfirmed:
-        switch(wtx->status.depth)
+        switch(wtx->status.maturity)
         {
-        case 0: return QIcon(":/icons/transaction_0");
-        case 1: return QIcon(":/icons/transaction_1");
-        case 2: return QIcon(":/icons/transaction_2");
-        case 3: return QIcon(":/icons/transaction_3");
-        case 4: return QIcon(":/icons/transaction_4");
-        default: return QIcon(":/icons/transaction_5");
-        };
-    case TransactionStatus::HaveConfirmations:
-        return QIcon(":/icons/transaction_confirmed");
+        case TransactionStatus::Immature: {
+            int total = wtx->status.depth + wtx->status.matures_in;
+            int part = (wtx->status.depth * 4 / total) + 1;
+            return QIcon(QString(":/icons/transaction_%1").arg(part));
+            }
+        case TransactionStatus::Mature:
+            return QIcon(":/icons/transaction_confirmed");
+        case TransactionStatus::MaturesWarning:
+        case TransactionStatus::NotAccepted:
+            return QIcon(":/icons/transaction_0");
+        }
+    }
+    else
+    {
+        switch(wtx->status.status)
+        {
+        case TransactionStatus::OpenUntilBlock:
+        case TransactionStatus::OpenUntilDate:
+            return QColor(64,64,255);
+            break;
+        case TransactionStatus::Offline:
+            return QColor(192,192,192);
+        case TransactionStatus::Unconfirmed:
+            switch(wtx->status.depth)
+            {
+            case 0: return QIcon(":/icons/transaction_0");
+            case 1: return QIcon(":/icons/transaction_1");
+            case 2: return QIcon(":/icons/transaction_2");
+            case 3: return QIcon(":/icons/transaction_3");
+            case 4: return QIcon(":/icons/transaction_4");
+            default: return QIcon(":/icons/transaction_5");
+            };
+        case TransactionStatus::HaveConfirmations:
+            return QIcon(":/icons/transaction_confirmed");
+        }
     }
     return QColor(0,0,0);
 }
@@ -502,24 +523,40 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
     }
     else if (role == TypeRole)
     {
-        /* Role for filtering tabs by type */
-        switch(rec->type)
-        {
-        case TransactionRecord::RecvWithAddress:
-        case TransactionRecord::RecvFromIP:
-            return TransactionTableModel::Received;
-        case TransactionRecord::SendToAddress:
-        case TransactionRecord::SendToIP:
-        case TransactionRecord::SendToSelf:
-            return TransactionTableModel::Sent;
-        default:
-            return TransactionTableModel::Other;
-        }
+        return rec->type;
+    }
+    else if (role == DateRole)
+    {
+        return QDateTime::fromTime_t(static_cast<uint>(rec->time));
     }
     else if (role == LongDescriptionRole)
     {
         return priv->describe(rec);
     }
+    else if (role == AddressRole)
+    {
+        return QString::fromStdString(rec->address);
+    }
+    else if (role == LabelRole)
+    {
+        return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
+    }
+    else if (role == AbsoluteAmountRole)
+    {
+        return llabs(rec->credit + rec->debit);
+    }
+    else if (role == TxIDRole)
+    {
+        return QString::fromStdString(rec->getTxID());
+    }
+    else if (role == ConfirmedRole)
+    {
+        return rec->status.status == TransactionStatus::HaveConfirmations;
+    }
+    else if (role == FormattedAmountRole)
+    {
+        return formatTxAmount(rec, false);
+    }
     return QVariant();
 }