void TFileAttachmentWidget::onDelTriggered()
  {
  TSelection selection;
  RetrieveSelection(&selection);

  bool sortEnabled = FreezeAttachmentTable();

  int row_no = 0;

  for(AAttachmentItem* item : selection)
    {
    item->Unregister();
    int rowNo = item->row();
    ui->attachmentTable->removeRow(rowNo);
    row_no = rowNo;
    }

  if(row_no < ui->attachmentTable->rowCount())
    ui->attachmentTable->selectRow(row_no);
  else
    ui->attachmentTable->selectRow(row_no-1);

  UnFreezeAttachmentTable(sortEnabled);

  UpdateColumnHeaders();

  ui->attachmentTable->setFocus();
  
  emit attachmentListChanged();
  }
void TFileAttachmentWidget::onAttachementTableSelectionChanged()
{
  TSelection selection;
  RetrieveSelection(&selection);

  unsigned int selectedCount = selection.size();
  bool anySelection = selectedCount != 0;
  bool singleSelection = selectedCount == 1;

  ui->actionAdd->setEnabled(EditMode);
  ui->actionDel->setEnabled(anySelection && EditMode);
  ui->actionOpen->setEnabled(singleSelection);
  ui->actionSave->setEnabled(anySelection);  

  bool vCardVaild = false;
  bool existContact = false;
  if (anySelection)
  {
    AAttachmentItem* item = selection.front();
    QString fileName = item->GetDisplayedFileName();

    QByteArray contactData;
    if (TFileAttachmentWidget::isValidContactvCard(fileName, *item, &contactData))
    {
      vCardVaild = true;

      ContactvCard converter(contactData);
      std::string publicKeyString = converter.getPublicKey().toStdString();

      fc::ecc::public_key parsedKey;
      if (public_key_address::convert(publicKeyString, &parsedKey))
      {
        if(Utils::matchContact(parsedKey, &_clickedContact))
        {
          existContact = true;
        }
      }
      //else
      //Warning: public key can be invalid but enable option "AddContact".
      //User can correct public key
    }    
  }

  ui->actionAddContact->setEnabled(singleSelection && !EditMode && vCardVaild && !existContact);
  ui->actionFindContact->setEnabled(singleSelection && !EditMode && vCardVaild && existContact);
  ui->actionRename->setEnabled(singleSelection && EditMode && !vCardVaild);
  if (singleSelection)
  {
    //disable Import contact when contact already exist
    ui->actionImportContact->setEnabled(!EditMode && vCardVaild && !existContact);
  }
  else
  {
    //Don't check existContact flag when there are selected more contacts.
    //If some contact already exist there will be displayed message with containing list of ignored .vcf files
    ui->actionImportContact->setEnabled(anySelection && !EditMode && vCardVaild);
  }
  
}
void TFileAttachmentWidget::onRenameTriggered()
  {
  TSelection selection;
  RetrieveSelection(&selection);

  assert(selection.size() == 1 &&
    "Bad code in command update ui (onAttachementTableSelectionChanged)");

  AAttachmentItem* item = selection.front();
  ui->attachmentTable->editItem(item);
  }
void TFileAttachmentWidget::onOpenTriggered()
  {
  TSelection selection;
  RetrieveSelection(&selection);

  assert(selection.size() == 1 &&
    "Bad code in command update ui (onAttachementTableSelectionChanged)");

  const AAttachmentItem* item = selection.front();
  item->Open();
  }
void TFileAttachmentWidget::onDelTriggered()
  {
  TSelection selection;
  RetrieveSelection(&selection);

  bool sortEnabled = FreezeAttachmentTable();

  for(AAttachmentItem* item : selection)
    {
    item->Unregister();
    int rowNo = item->row();
    ui->attachmentTable->removeRow(rowNo);
    }

  UnFreezeAttachmentTable(sortEnabled);

  UpdateColumnHeaders();
  
  emit attachmentListChanged();
  }
void TFileAttachmentWidget::onAddContactTriggered()
{
  TSelection selection;
  RetrieveSelection(&selection);

  assert(selection.size() == 1 &&
    "Bad code in command update ui (onAttachementTableSelectionChanged)");

  const AAttachmentItem* item = selection.front();

  QByteArray contactData;
  item->getContactData(contactData);
  assert (contactData.size() > 0);  

  std::list<Contact> contacts;
  Contact contact;
  ContactvCard vCard(contactData);
  // Public key can be invalid, but user can correct key in the "Add contact" dialog
  vCard.convert(&contact);
  contacts.push_back(contact);

  getKeyhoteeWindow()->addToContacts(false, contacts);
  getKeyhoteeWindow()->activateMainWindow();
}
bool TFileAttachmentWidget::saveAttachments()
{
  TSelection selection;
  RetrieveSelection(&selection);

  QString docPath = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);

  if(selection.size() > 1)
  {
    /// If multiple items are selected ask for directory where files should be written to.
    QString storageDir = QFileDialog::getExistingDirectory(this,
      tr("Save selected file attachments..."), docPath, QFileDialog::ShowDirsOnly);
    if(storageDir.length() == 0)
      return false;
    QDir dir(storageDir);
    bool savedOK = true;
    for(const AAttachmentItem* attachmentItem : selection)
    {
      QFileInfo fi(dir, attachmentItem->GetDisplayedFileName());
      if (SaveAttachmentItem(attachmentItem, fi, true) == false)
        savedOK = false;
    }
    return savedOK;
  }
  else
  {
    /// If single item is selected just ask for direct path to save it
    QString filePath = QFileDialog::getSaveFileName(this, "Save attachment file...", QDir(docPath).filePath(selection.front()->GetDisplayedFileName()));
    if(filePath.length() == 0)
      return false;
    const AAttachmentItem* attachmentItem = selection.front();
    QFileInfo fi(filePath);
    /// Here we don't need to check for file overwrite - it was done by QFileDialog.
    return SaveAttachmentItem(attachmentItem, fi, false);
  }
}
void TFileAttachmentWidget::onImportContactTriggered()
{
  TSelection selection;
  RetrieveSelection(&selection);

  QStringList         contactsDuplicated;
  QStringList         contactsPublicKeyInvalid;
  QByteArray          contactData;
  std::list<Contact>  contacts;
  Contact             contact;
  QString             fileName;  
  fc::ecc::public_key parsedKey;
  for (AAttachmentItem* item : selection)
  {    
    item->getContactData(contactData);
    fileName = item->GetDisplayedFileName();
    //check validation file name
    if (TFileAttachmentWidget::isValidContactvCard(fileName, *item, &contactData))
    {
      ContactvCard vCard(contactData);
      assert (contactData.size() > 0);
      std::string publicKeyString = vCard.getPublicKey().toStdString();
    
      //check validation public key
      if (public_key_address::convert(publicKeyString, &parsedKey))
      {
        if(Utils::matchContact(parsedKey, &_clickedContact))
        {
          contactsDuplicated.push_back(fileName);
        }
        else
        {
          // Must be success because validation is checked in the above
          assert (vCard.convert(&contact) == ContactvCard::ConvertStatus::SUCCESS);
          contacts.push_back(contact);
        }
      }
      else
        contactsPublicKeyInvalid.push_back(fileName);
    }
  }

  QWidget *parentWidget;
  if (contacts.size())
  {
    getKeyhoteeWindow()->addToContacts(true/*silent*/, contacts);
    getKeyhoteeWindow()->activateMainWindow();
    parentWidget = getKeyhoteeWindow();
  }
  else
    parentWidget = this;

  QString msg = "";
  if (contactsDuplicated.size())
  {
    /// Report a message about contacts duplicated
    msg += (tr("Following contacts were not imported because they already exist in your contact list:<br/>"));
    for(auto name : contactsDuplicated)
    {
      msg += name + tr("<br/>");
    }
  }
  if (contactsPublicKeyInvalid.size())
  {
    //set empty line if contactsDuplicated exist
    if (contactsDuplicated.size())
      msg += tr("<br/>");
    /// Report a message about contacts with invalid public key
    msg += (tr("Following contacts were not imported because they have invalid public key:<br/>"));
    for(auto name : contactsPublicKeyInvalid)
    {
      msg += name + tr("<br/>");
    }
  }

  if (contactsDuplicated.size() || contactsPublicKeyInvalid.size())
  {    
    QMessageBox::information(parentWidget, tr("Import contact(s)"), msg);
  }
}