<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    utils/classify.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "classify.h"

#include <QString>
#include <QStringList>
#include <QFile>
#include <QFileInfo>
#include <QtAlgorithms>
#include <QByteArrayMatcher>

#include <boost/range.hpp>

#ifdef __GNUC__
# include <ext/algorithm>
#endif

#include <functional>

using namespace boost;
using namespace Kleo::Class;

namespace {

    const unsigned int ExamineContentHint = 0x8000;

    static const struct _classification {
        char extension[4];
        unsigned int classification;
    } classifications[] = {
        // ordered by extension
        { "asc", OpenPGP|  Ascii  | OpaqueSignature|DetachedSignature|CipherText|AnyCertStoreType | ExamineContentHint },
        { "crt", CMS    | Binary  | Certificate },
        { "der", CMS    | Binary  | Certificate },
        { "gpg", OpenPGP| Binary  | OpaqueSignature|CipherText|AnyCertStoreType },
        { "p10", CMS    |  Ascii  | CertificateRequest },
        { "p12", CMS    | Binary  | ExportedPSM },
        { "p7c", CMS    | Binary  | Certificate  },
        { "p7m", CMS    | Binary  | CipherText },
        { "p7s", CMS    | Binary  | AnySignature },
        { "pem", CMS    |  Ascii  | AnyType | ExamineContentHint },
        { "sig", OpenPGP|AnyFormat| DetachedSignature },
    };

    static const unsigned int defaultClassification = NoClass;

    template <template <typename U> class Op>
    struct ByExtension {
        typedef bool result_type;

        template <typename T>
        bool operator()( const T & lhs, const T & rhs ) const {
            return Op<int>()( qstricmp( lhs.extension, rhs.extension ), 0 );
        }
        template <typename T>
        bool operator()( const T & lhs, const char * rhs ) const {
            return Op<int>()( qstricmp( lhs.extension, rhs ), 0 );
        }
        template <typename T>
        bool operator()( const char * lhs, const T & rhs ) const {
            return Op<int>()( qstricmp( lhs, rhs.extension ), 0 );
        }
        bool operator()( const char * lhs, const char * rhs ) const {
            return Op<int>()( qstricmp( lhs, rhs ), 0 );
        }
    };

    static const struct _content_classification {
        char content[28];
        unsigned int classification;
    } content_classifications[] = {
        { "CERTIFICATE",       Certificate },
        { "MESSAGE",           OpaqueSignature|CipherText },
        { "PKCS12",            ExportedPSM },
        { "PRIVATE KEY BLOCK", ExportedPSM },
        { "PUBLIC KEY BLOCK",  Certificate },
        { "SIGNATURE",         DetachedSignature },
        { "SIGNED MESSAGE",    ClearsignedMessage },
    };

    template <template <typename U> class Op>
    struct ByContent {
        typedef bool result_type;

        const unsigned int N;
        explicit ByContent( unsigned int n ) : N( n ) {}

        template <typename T>
        bool operator()( const T & lhs, const T & rhs ) const {
            return Op<int>()( qstrncmp( lhs.content, rhs.content, N ), 0 );
        }
        template <typename T>
        bool operator()( const T & lhs, const char * rhs ) const {
            return Op<int>()( qstrncmp( lhs.content, rhs, N ), 0 );
        }
        template <typename T>
        bool operator()( const char * lhs, const T & rhs ) const {
            return Op<int>()( qstrncmp( lhs, rhs.content, N ), 0 );
        }
        bool operator()( const char * lhs, const char * rhs ) const {
            return Op<int>()( qstrncmp( lhs, rhs, N ), 0 );
        }
    };

}

unsigned int Kleo::classify( const QString & filename ) {
#ifdef __GNUC__
    assert( __gnu_cxx::is_sorted( begin( classifications ), end( classifications ), ByExtension<std::less>() ) );
#endif

    const QFileInfo fi( filename );

    const _classification * const it = qBinaryFind( begin( classifications ), end( classifications ),
                                                    fi.suffix().toLatin1().constData(),
                                                    ByExtension<std::less>() );
    if ( it == end( classifications ) )
        return defaultClassification;
    if ( !( it->classification & ExamineContentHint ) )
        return it->classification;

    QFile file( filename );
    if ( !file.open( QIODevice::ReadOnly|QIODevice::Text ) )
        return it->classification;

    const unsigned int contentClassification = classifyContent( file.read( 4096 ) );
    if ( contentClassification != defaultClassification )
        return contentClassification;
    else
        return it->classification;
}

unsigned int Kleo::classifyContent( const QByteArray & data ) {
#ifdef __GNUC__
    assert( __gnu_cxx::is_sorted( begin( content_classifications ), end( content_classifications ), ByContent<std::less>(100) ) );
#endif

    static const char beginString[] = "-----BEGIN ";
    static const QByteArrayMatcher beginMatcher( beginString );
    int pos = beginMatcher.indexIn( data );
    if ( pos < 0 )
        return defaultClassification;
    pos += sizeof beginString - 1;

    const bool pgp = qstrncmp( data.data() + pos, "PGP ", 4 ) == 0;
    if ( pgp )
        pos += 4;

    const int epos = data.indexOf( "-----\n", pos );
    if ( epos < 0 )
        return defaultClassification;

    const _content_classification * const cit
        = qBinaryFind( begin( content_classifications ), end( content_classifications ),
                       data.data() + pos, ByContent<std::less>( epos - pos ) );

    if ( cit == end( content_classifications ) )
        return defaultClassification;
    else
        return cit->classification | ( pgp ? OpenPGP : CMS );
}

QString Kleo::printableClassification( unsigned int classification ) {
    QStringList parts;
    if ( classification & CMS )
        parts.push_back( "CMS" );
    if ( classification & OpenPGP )
        parts.push_back( "OpenPGP" );
    if ( classification & Binary )
        parts.push_back( "Binary" );
    if ( classification & Ascii )
        parts.push_back( "Ascii" );
    if ( classification & DetachedSignature )
        parts.push_back( "DetachedSignature" );
    if ( classification & OpaqueSignature )
        parts.push_back( "OpaqueSignature" );
    if ( classification & ClearsignedMessage )
        parts.push_back( "ClearsignedMessage" );
    if ( classification & CipherText )
        parts.push_back( "CipherText" );
    if ( classification & Certificate )
        parts.push_back( "Certificate" );
    if ( classification & ExportedPSM )
        parts.push_back( "ExportedPSM" );
    if ( classification & CertificateRequest )
        parts.push_back( "CertificateRequest" );
    return parts.join( ", " );
}

static QString chopped( QString s, unsigned int n ) {
    s.chop( n );
    return s;
}

/*!
  \return the data file that corresponds to the signature file \a
  signatureFileName, or QString(), if no such file can be found.
*/
QString Kleo::findSignedData( const QString & signatureFileName ) {
    if ( !mayBeDetachedSignature( signatureFileName ) )
        return QString();
    const QString baseName = chopped( signatureFileName, 4 );
    return QFile::exists( baseName ) ? baseName : QString() ;
}

/*!
  \return all (existing) candiate signature files for \a signedDataFileName

  Note that there can very well be more than one such file, e.g. if
  the same data file was signed by both CMS and OpenPGP certificates.
*/
QStringList Kleo::findSignatures( const QString & signedDataFileName ) {
    QStringList result;
    for ( unsigned int i = 0, end = size( classifications ) ; i < end ; ++i )
        if ( classifications[i].classification & DetachedSignature ) {
            const QString candiate = signedDataFileName + '.' + classifications[i].extension;
            if ( QFile::exists( candiate ) )
                result.push_back( candiate );
        }
    return result;
}

/*!
  \return the (likely) output filename for \a inputFileName, or
  "inputFileName.out" if none can be determined.
*/
QString Kleo::outputFileName( const QString & inputFileName ) {
    const QFileInfo fi( inputFileName );

    if ( qBinaryFind( begin( classifications ), end( classifications ),
                      fi.suffix().toLatin1().constData(),
                      ByExtension<std::less>() ) == end( classifications ) )
        return inputFileName + ".out";
    else
        return chopped( inputFileName, 4 );
}

/*!
  \return the commonly used extension for files of type
  \a classification, or NULL if none such exists.
*/
const char * Kleo::outputFileExtension( unsigned int classification ) {
    for ( unsigned int i = 0 ; i < sizeof classifications / sizeof *classifications ; ++i )
        if ( ( classifications[i].classification & classification ) == classification )
            return classifications[i].extension;
    return 0;
}
<commit_msg>Treat files ending in .pgp the same as those ending in .gpg.<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    utils/classify.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

    Kleopatra is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Kleopatra is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "classify.h"

#include <QString>
#include <QStringList>
#include <QFile>
#include <QFileInfo>
#include <QtAlgorithms>
#include <QByteArrayMatcher>

#include <boost/range.hpp>

#ifdef __GNUC__
# include <ext/algorithm>
#endif

#include <functional>

using namespace boost;
using namespace Kleo::Class;

namespace {

    const unsigned int ExamineContentHint = 0x8000;

    static const struct _classification {
        char extension[4];
        unsigned int classification;
    } classifications[] = {
        // ordered by extension
        { "asc", OpenPGP|  Ascii  | OpaqueSignature|DetachedSignature|CipherText|AnyCertStoreType | ExamineContentHint },
        { "crt", CMS    | Binary  | Certificate },
        { "der", CMS    | Binary  | Certificate },
        { "gpg", OpenPGP| Binary  | OpaqueSignature|CipherText|AnyCertStoreType },
        { "pgp", OpenPGP| Binary  | OpaqueSignature|CipherText|AnyCertStoreType },
        { "p10", CMS    |  Ascii  | CertificateRequest },
        { "p12", CMS    | Binary  | ExportedPSM },
        { "p7c", CMS    | Binary  | Certificate  },
        { "p7m", CMS    | Binary  | CipherText },
        { "p7s", CMS    | Binary  | AnySignature },
        { "pem", CMS    |  Ascii  | AnyType | ExamineContentHint },
        { "sig", OpenPGP|AnyFormat| DetachedSignature },
    };

    static const unsigned int defaultClassification = NoClass;

    template <template <typename U> class Op>
    struct ByExtension {
        typedef bool result_type;

        template <typename T>
        bool operator()( const T & lhs, const T & rhs ) const {
            return Op<int>()( qstricmp( lhs.extension, rhs.extension ), 0 );
        }
        template <typename T>
        bool operator()( const T & lhs, const char * rhs ) const {
            return Op<int>()( qstricmp( lhs.extension, rhs ), 0 );
        }
        template <typename T>
        bool operator()( const char * lhs, const T & rhs ) const {
            return Op<int>()( qstricmp( lhs, rhs.extension ), 0 );
        }
        bool operator()( const char * lhs, const char * rhs ) const {
            return Op<int>()( qstricmp( lhs, rhs ), 0 );
        }
    };

    static const struct _content_classification {
        char content[28];
        unsigned int classification;
    } content_classifications[] = {
        { "CERTIFICATE",       Certificate },
        { "MESSAGE",           OpaqueSignature|CipherText },
        { "PKCS12",            ExportedPSM },
        { "PRIVATE KEY BLOCK", ExportedPSM },
        { "PUBLIC KEY BLOCK",  Certificate },
        { "SIGNATURE",         DetachedSignature },
        { "SIGNED MESSAGE",    ClearsignedMessage },
    };

    template <template <typename U> class Op>
    struct ByContent {
        typedef bool result_type;

        const unsigned int N;
        explicit ByContent( unsigned int n ) : N( n ) {}

        template <typename T>
        bool operator()( const T & lhs, const T & rhs ) const {
            return Op<int>()( qstrncmp( lhs.content, rhs.content, N ), 0 );
        }
        template <typename T>
        bool operator()( const T & lhs, const char * rhs ) const {
            return Op<int>()( qstrncmp( lhs.content, rhs, N ), 0 );
        }
        template <typename T>
        bool operator()( const char * lhs, const T & rhs ) const {
            return Op<int>()( qstrncmp( lhs, rhs.content, N ), 0 );
        }
        bool operator()( const char * lhs, const char * rhs ) const {
            return Op<int>()( qstrncmp( lhs, rhs, N ), 0 );
        }
    };

}

unsigned int Kleo::classify( const QString & filename ) {
#ifdef __GNUC__
    assert( __gnu_cxx::is_sorted( begin( classifications ), end( classifications ), ByExtension<std::less>() ) );
#endif

    const QFileInfo fi( filename );

    const _classification * const it = qBinaryFind( begin( classifications ), end( classifications ),
                                                    fi.suffix().toLatin1().constData(),
                                                    ByExtension<std::less>() );
    if ( it == end( classifications ) )
        return defaultClassification;
    if ( !( it->classification & ExamineContentHint ) )
        return it->classification;

    QFile file( filename );
    if ( !file.open( QIODevice::ReadOnly|QIODevice::Text ) )
        return it->classification;

    const unsigned int contentClassification = classifyContent( file.read( 4096 ) );
    if ( contentClassification != defaultClassification )
        return contentClassification;
    else
        return it->classification;
}

unsigned int Kleo::classifyContent( const QByteArray & data ) {
#ifdef __GNUC__
    assert( __gnu_cxx::is_sorted( begin( content_classifications ), end( content_classifications ), ByContent<std::less>(100) ) );
#endif

    static const char beginString[] = "-----BEGIN ";
    static const QByteArrayMatcher beginMatcher( beginString );
    int pos = beginMatcher.indexIn( data );
    if ( pos < 0 )
        return defaultClassification;
    pos += sizeof beginString - 1;

    const bool pgp = qstrncmp( data.data() + pos, "PGP ", 4 ) == 0;
    if ( pgp )
        pos += 4;

    const int epos = data.indexOf( "-----\n", pos );
    if ( epos < 0 )
        return defaultClassification;

    const _content_classification * const cit
        = qBinaryFind( begin( content_classifications ), end( content_classifications ),
                       data.data() + pos, ByContent<std::less>( epos - pos ) );

    if ( cit == end( content_classifications ) )
        return defaultClassification;
    else
        return cit->classification | ( pgp ? OpenPGP : CMS );
}

QString Kleo::printableClassification( unsigned int classification ) {
    QStringList parts;
    if ( classification & CMS )
        parts.push_back( "CMS" );
    if ( classification & OpenPGP )
        parts.push_back( "OpenPGP" );
    if ( classification & Binary )
        parts.push_back( "Binary" );
    if ( classification & Ascii )
        parts.push_back( "Ascii" );
    if ( classification & DetachedSignature )
        parts.push_back( "DetachedSignature" );
    if ( classification & OpaqueSignature )
        parts.push_back( "OpaqueSignature" );
    if ( classification & ClearsignedMessage )
        parts.push_back( "ClearsignedMessage" );
    if ( classification & CipherText )
        parts.push_back( "CipherText" );
    if ( classification & Certificate )
        parts.push_back( "Certificate" );
    if ( classification & ExportedPSM )
        parts.push_back( "ExportedPSM" );
    if ( classification & CertificateRequest )
        parts.push_back( "CertificateRequest" );
    return parts.join( ", " );
}

static QString chopped( QString s, unsigned int n ) {
    s.chop( n );
    return s;
}

/*!
  \return the data file that corresponds to the signature file \a
  signatureFileName, or QString(), if no such file can be found.
*/
QString Kleo::findSignedData( const QString & signatureFileName ) {
    if ( !mayBeDetachedSignature( signatureFileName ) )
        return QString();
    const QString baseName = chopped( signatureFileName, 4 );
    return QFile::exists( baseName ) ? baseName : QString() ;
}

/*!
  \return all (existing) candiate signature files for \a signedDataFileName

  Note that there can very well be more than one such file, e.g. if
  the same data file was signed by both CMS and OpenPGP certificates.
*/
QStringList Kleo::findSignatures( const QString & signedDataFileName ) {
    QStringList result;
    for ( unsigned int i = 0, end = size( classifications ) ; i < end ; ++i )
        if ( classifications[i].classification & DetachedSignature ) {
            const QString candiate = signedDataFileName + '.' + classifications[i].extension;
            if ( QFile::exists( candiate ) )
                result.push_back( candiate );
        }
    return result;
}

/*!
  \return the (likely) output filename for \a inputFileName, or
  "inputFileName.out" if none can be determined.
*/
QString Kleo::outputFileName( const QString & inputFileName ) {
    const QFileInfo fi( inputFileName );

    if ( qBinaryFind( begin( classifications ), end( classifications ),
                      fi.suffix().toLatin1().constData(),
                      ByExtension<std::less>() ) == end( classifications ) )
        return inputFileName + ".out";
    else
        return chopped( inputFileName, 4 );
}

/*!
  \return the commonly used extension for files of type
  \a classification, or NULL if none such exists.
*/
const char * Kleo::outputFileExtension( unsigned int classification ) {
    for ( unsigned int i = 0 ; i < sizeof classifications / sizeof *classifications ; ++i )
        if ( ( classifications[i].classification & classification ) == classification )
            return classifications[i].extension;
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>Add test for texture::SetRect to make sure -pitch works.<commit_after><|endoftext|>


<commit_before>//Simply print "Hello, World." on screen.
#include <iostream>
int main(){
    std::cout<<"Hello, World.";
}<commit_msg>updated<commit_after>//Simply print "Hello, World." on screen.
#include <iostream>
int main(){
    std::cout<<"Hello, World.";
    return 0;
}<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <stdint.h>
#include <sys/stat.h>
#include <ostream>
#include <thread>

#include <unistd.h>

#include "paddle/fluid/framework/executor.h"
#include "paddle/fluid/framework/framework.pb.h"
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/proto_desc.h"
#include "paddle/fluid/framework/threadpool.h"
#include "paddle/fluid/operators/detail/grpc_server.h"
#include "paddle/fluid/operators/detail/sendrecvop_utils.h"
#include "paddle/fluid/operators/detail/simple_block_queue.h"
#include "paddle/fluid/string/printf.h"

namespace paddle {
namespace operators {

constexpr char kOptimizeBlock[] = "OptimizeBlock";

void RunServer(std::shared_ptr<detail::AsyncGRPCServer> service) {
  service->RunSyncUpdate();
  VLOG(4) << "RunServer thread end";
}

static void CreateTensorFromMessageType(framework::Variable *var,
                                        sendrecv::VarType var_type) {
  if (var_type == sendrecv::VarType::LOD_TENSOR) {
    var->GetMutable<framework::LoDTensor>();
  } else if (var_type == sendrecv::VarType::SELECTED_ROWS) {
    var->GetMutable<framework::SelectedRows>();
  } else {
    PADDLE_THROW(
        "VariableMessage type %d is not in "
        "[LoDTensor, SelectedRows]",
        var_type);
  }
}

class ListenAndServOp : public framework::OperatorBase {
 public:
  ListenAndServOp(const std::string &type,
                  const framework::VariableNameMap &inputs,
                  const framework::VariableNameMap &outputs,
                  const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {
    if (!rpc_service_) {
      std::string endpoint = Attr<std::string>("endpoint");
      rpc_service_.reset(new detail::AsyncGRPCServer(endpoint));
      server_thread_.reset(new std::thread(RunServer, rpc_service_));
    }
  }

  void Stop() override {
    detail::MessageWithName term_msg;
    term_msg.first = LISTEN_TERMINATE_MESSAGE;
    rpc_service_->Push(term_msg);
    rpc_service_->ShutDown();
    server_thread_->join();
  }

  void RunImpl(const framework::Scope &scope,
               const platform::Place &dev_place) const override {
    platform::DeviceContextPool &pool = platform::DeviceContextPool::Instance();
    auto &dev_ctx = *pool.Get(dev_place);
    framework::Scope &recv_scope = scope.NewScope();

    // FIXME(Yancey1989): initialize rpc server with lazy mode.
    rpc_service_->SetScope(&recv_scope);
    rpc_service_->SetDevCtx(&dev_ctx);
    auto ins = Inputs("X");
    auto fan_in = Attr<int>("Fanin");

    auto *block = Attr<framework::BlockDesc *>(kOptimizeBlock);
    auto *program = block->Program();
    int num_blocks = program->Size();
    framework::Executor executor(dev_place);

    // TODO(typhoonzero): change this to a while_op for every cluster-batch.
    bool exit_flag = false;
    // Record received sparse variables, so that
    // we could reset those after execute optimize program
    std::vector<framework::Variable *> sparse_vars;
    while (!exit_flag) {
      // Get from multiple trainers, we don't care about the order in which
      // the gradients arrives, just add suffix 0~n and merge the gradient.
      rpc_service_->SetCond(0);
      size_t recv_var_cnt = 0;
      int batch_barrier = 0;
      while (batch_barrier != fan_in) {
        const detail::MessageWithName &v = rpc_service_->Get();
        auto recv_var_name = v.first;
        if (recv_var_name == LISTEN_TERMINATE_MESSAGE) {
          LOG(INFO) << "received terminate message and exit";
          exit_flag = true;
          break;
        } else if (recv_var_name == BATCH_BARRIER_MESSAGE) {
          VLOG(3) << "recv batch barrier message";
          batch_barrier++;
          continue;
        } else {
          VLOG(3) << "received grad: " << recv_var_name;
          recv_var_cnt++;
          auto *var = recv_scope.FindVar(recv_var_name);
          if (var == nullptr) {
            LOG(ERROR) << "Can not find server side var: " << recv_var_name;
            PADDLE_THROW("Can not find server side var");
          }
          detail::DeserializeFromMessage(v.second, dev_ctx, var);
          if (var->IsType<framework::SelectedRows>()) {
            sparse_vars.push_back(var);
          }
        }
      }
      if (exit_flag) {
        rpc_service_->SetCond(1);
        rpc_service_->ShutDown();
        break;
      }

      // put optimize blocks in the thread pool to start run, the last block
      // should be global ops.
      // NOTE: if is_gpu_place, CUDA kernels are laugched by multiple threads
      // and this will still work.
      double ts = detail::GetTimestamp();
      std::vector<std::future<void>> fs;
      for (int blkid = 0; blkid < num_blocks - 1; ++blkid) {
        fs.push_back(framework::Async([&]() {
          try {
            VLOG(2) << "begin run in thread" << blkid;
            executor.Run(*program, &recv_scope, blkid,
                         false /*create_local_scope*/, false /*create_vars*/);
            VLOG(2) << "end run in thread";
          } catch (std::exception &e) {
            LOG(ERROR) << "run sub program error " << e.what();
          }
        }));
      }
      VLOG(2) << "waiting opts...";
      for (int blkid = 0; blkid < num_blocks - 1; ++blkid) fs[blkid].wait();
      VLOG(2) << "waiting opts...OK";
      // Run global block at final step
      if (num_blocks > 2) {
        try {
          executor.Run(*program, &recv_scope, num_blocks - 1,
                       false /*create_local_scope*/, false /*create_vars*/);
          VLOG(2) << "run global OK , spent " << detail::GetTimestamp() - ts;
        } catch (std::exception &e) {
          LOG(ERROR) << "run sub program error " << e.what();
        }
      }
      for (auto &n : recv_scope.LocalVarNames()) {
        VLOG(2) << "vars in scope: " << n;
      }
      for (auto &n : recv_scope.LocalVarNames()) {
        VLOG(2) << "vars in parent scope: " << n;
      }

      // Reset the received sparse variables, the sum operator would not
      // sum the input sparse variables which rows is empty at the next
      // mini-batch.
      // TODO(Yancey1989): move the reset action into an operator, we couldn't
      // have any hide logic in the operator.
      for (auto &var : sparse_vars) {
        var->GetMutable<framework::SelectedRows>()->mutable_rows()->clear();
      }
      rpc_service_->SetCond(1);
      // FIXME(typhoonzero): use another condition to sync wait clients get.
      rpc_service_->WaitClientGet(fan_in);
      sparse_vars.clear();
    }  // while(true)
  }

 protected:
  std::shared_ptr<detail::AsyncGRPCServer> rpc_service_;
  std::shared_ptr<std::thread> server_thread_;
};

class ListenAndServOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  ListenAndServOpMaker(OpProto *proto, OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("X", "(Tensor) Variables that server recv.").AsDuplicable();
    AddComment(R"DOC(
ListenAndServ operator

This operator will start a RPC server which can receive variables
from send_op and send back variables to recv_op.
)DOC");
    AddAttr<std::string>("endpoint",
                         "(string, default 127.0.0.1:6164)"
                         "IP address to listen on.")
        .SetDefault("127.0.0.1:6164")
        .AddCustomChecker([](const std::string &ip) { return !ip.empty(); });
    AddAttr<framework::BlockDesc *>(kOptimizeBlock,
                                    "BlockID to run on server side.");
    AddAttr<int>("Fanin", "How many clients send to this server.")
        .SetDefault(1);
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OPERATOR(listen_and_serv, ops::ListenAndServOp,
                  ops::ListenAndServOpMaker);
<commit_msg>workable<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <stdint.h>
#include <sys/stat.h>
#include <ostream>
#include <thread>

#include <unistd.h>

#include "paddle/fluid/framework/executor.h"
#include "paddle/fluid/framework/framework.pb.h"
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/proto_desc.h"
#include "paddle/fluid/framework/threadpool.h"
#include "paddle/fluid/operators/detail/grpc_server.h"
#include "paddle/fluid/operators/detail/sendrecvop_utils.h"
#include "paddle/fluid/operators/detail/simple_block_queue.h"
#include "paddle/fluid/string/printf.h"

namespace paddle {
namespace operators {

constexpr char kOptimizeBlock[] = "OptimizeBlock";

void RunServer(std::shared_ptr<detail::AsyncGRPCServer> service) {
  service->RunSyncUpdate();
  VLOG(4) << "RunServer thread end";
}

static void CreateTensorFromMessageType(framework::Variable *var,
                                        sendrecv::VarType var_type) {
  if (var_type == sendrecv::VarType::LOD_TENSOR) {
    var->GetMutable<framework::LoDTensor>();
  } else if (var_type == sendrecv::VarType::SELECTED_ROWS) {
    var->GetMutable<framework::SelectedRows>();
  } else {
    PADDLE_THROW(
        "VariableMessage type %d is not in "
        "[LoDTensor, SelectedRows]",
        var_type);
  }
}

class ListenAndServOp : public framework::OperatorBase {
 public:
  ListenAndServOp(const std::string &type,
                  const framework::VariableNameMap &inputs,
                  const framework::VariableNameMap &outputs,
                  const framework::AttributeMap &attrs)
      : OperatorBase(type, inputs, outputs, attrs) {
    if (!rpc_service_) {
      std::string endpoint = Attr<std::string>("endpoint");
      rpc_service_.reset(new detail::AsyncGRPCServer(endpoint));
      server_thread_.reset(new std::thread(RunServer, rpc_service_));
    }
  }

  void Stop() override {
    detail::MessageWithName term_msg;
    term_msg.first = LISTEN_TERMINATE_MESSAGE;
    rpc_service_->Push(term_msg);
    rpc_service_->ShutDown();
    server_thread_->join();
  }

  void RunImpl(const framework::Scope &scope,
               const platform::Place &dev_place) const override {
    platform::DeviceContextPool &pool = platform::DeviceContextPool::Instance();
    auto &dev_ctx = *pool.Get(dev_place);
    framework::Scope &recv_scope = scope.NewScope();

    // FIXME(Yancey1989): initialize rpc server with lazy mode.
    rpc_service_->SetScope(&recv_scope);
    rpc_service_->SetDevCtx(&dev_ctx);
    auto ins = Inputs("X");
    auto fan_in = Attr<int>("Fanin");

    auto *block = Attr<framework::BlockDesc *>(kOptimizeBlock);
    auto *program = block->Program();
    int num_blocks = program->Size();
    PADDLE_ENFORCE_GE(num_blocks, 2,
                      "server program should have at least 2 blocks");

    framework::Executor executor(dev_place);

    // TODO(typhoonzero): change this to a while_op for every cluster-batch.
    bool exit_flag = false;
    // Record received sparse variables, so that
    // we could reset those after execute optimize program
    std::vector<framework::Variable *> sparse_vars;
    while (!exit_flag) {
      // Get from multiple trainers, we don't care about the order in which
      // the gradients arrives, just add suffix 0~n and merge the gradient.
      rpc_service_->SetCond(0);
      size_t recv_var_cnt = 0;
      int batch_barrier = 0;
      while (batch_barrier != fan_in) {
        const detail::MessageWithName &v = rpc_service_->Get();
        auto recv_var_name = v.first;
        if (recv_var_name == LISTEN_TERMINATE_MESSAGE) {
          LOG(INFO) << "received terminate message and exit";
          exit_flag = true;
          break;
        } else if (recv_var_name == BATCH_BARRIER_MESSAGE) {
          VLOG(3) << "recv batch barrier message";
          batch_barrier++;
          continue;
        } else {
          VLOG(3) << "received grad: " << recv_var_name;
          recv_var_cnt++;
          auto *var = recv_scope.FindVar(recv_var_name);
          if (var == nullptr) {
            LOG(ERROR) << "Can not find server side var: " << recv_var_name;
            PADDLE_THROW("Can not find server side var");
          }
          detail::DeserializeFromMessage(v.second, dev_ctx, var);
          if (var->IsType<framework::SelectedRows>()) {
            sparse_vars.push_back(var);
          }
        }
      }
      if (exit_flag) {
        rpc_service_->SetCond(1);
        rpc_service_->ShutDown();
        break;
      }

      // put optimize blocks in the thread pool to start run, the last block
      // should be global ops.
      // NOTE: if is_gpu_place, CUDA kernels are laugched by multiple threads
      // and this will still work.
      std::vector<std::future<void>> fs;
      // block0 contains only listen_and_serv op, start run from block1.
      for (int blkid = 1; blkid < num_blocks - 1; ++blkid) {
        fs.push_back(framework::Async([&executor, &program, &recv_scope,
                                       blkid]() {
          int run_block = blkid;  // thread local
          try {
            executor.Run(*program, &recv_scope, run_block,
                         false /*create_local_scope*/, false /*create_vars*/);
          } catch (std::exception &e) {
            LOG(ERROR) << "run sub program error " << e.what();
          }
        }));
      }
      for (int i = 0; i < num_blocks - 2; ++i) fs[i].wait();
      // Run global block at final step
      if (num_blocks > 2) {
        try {
          executor.Run(*program, &recv_scope, num_blocks - 1,
                       false /*create_local_scope*/, false /*create_vars*/);
        } catch (std::exception &e) {
          LOG(ERROR) << "run sub program error " << e.what();
        }
      }

      // Reset the received sparse variables, the sum operator would not
      // sum the input sparse variables which rows is empty at the next
      // mini-batch.
      // TODO(Yancey1989): move the reset action into an operator, we couldn't
      // have any hide logic in the operator.
      for (auto &var : sparse_vars) {
        var->GetMutable<framework::SelectedRows>()->mutable_rows()->clear();
      }
      rpc_service_->SetCond(1);
      // FIXME(typhoonzero): use another condition to sync wait clients get.
      rpc_service_->WaitClientGet(fan_in);
      sparse_vars.clear();
    }  // while(true)
  }

 protected:
  std::shared_ptr<detail::AsyncGRPCServer> rpc_service_;
  std::shared_ptr<std::thread> server_thread_;
};

class ListenAndServOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  ListenAndServOpMaker(OpProto *proto, OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("X", "(Tensor) Variables that server recv.").AsDuplicable();
    AddComment(R"DOC(
ListenAndServ operator

This operator will start a RPC server which can receive variables
from send_op and send back variables to recv_op.
)DOC");
    AddAttr<std::string>("endpoint",
                         "(string, default 127.0.0.1:6164)"
                         "IP address to listen on.")
        .SetDefault("127.0.0.1:6164")
        .AddCustomChecker([](const std::string &ip) { return !ip.empty(); });
    AddAttr<framework::BlockDesc *>(kOptimizeBlock,
                                    "BlockID to run on server side.");
    AddAttr<int>("Fanin", "How many clients send to this server.")
        .SetDefault(1);
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OPERATOR(listen_and_serv, ops::ListenAndServOp,
                  ops::ListenAndServOpMaker);
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE main

#include <boost/test/unit_test.hpp>
#include <boost/test/included/unit_test.hpp>

#include "SharedMap.hpp"

BOOST_AUTO_TEST_CASE(SharedMap_basic_test) {

	SharedMap<int, int> sm;
	sm.insert(0, 0);
	BOOST_CHECK_EQUAL(sm[0], 0);

}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_share_data) {
	SharedMap<int, int> sm1, sm2;

	sm1.insert(0, 0);
	BOOST_CHECK_EQUAL(sm1[0], sm2[0]);
}

BOOST_AUTO_TEST_CASE(SharedMap_should_throw_if_non_existant_value_is_requested) {
	SharedMap<int, int> sm;

	BOOST_CHECK_THROW(sm.at(1), std::out_of_range);
}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_be_independent_if_they_are_destroyed) {
	{
		// run1
		SharedMap<int, int> sm;
		sm.insert(0, 0);
		BOOST_CHECK_EQUAL(sm[0], 0);
	}

	{
		// run2
		SharedMap<int, int> sm;
		BOOST_CHECK_THROW(sm.at(0), std::out_of_range);
	}

}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_share_keys_for_allocating_keys) {
	SharedMap<int, std::string> sm1, sm2;

	sm1.insert(0, "value");
	BOOST_CHECK_EQUAL(sm2[0], "value");

}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_share_large_strings) {
	SharedMap<int, std::string> sm1, sm2;

	std::string largeString = "111111111111111111111111111111111111111111111";

	sm1.insert(0, largeString);

	BOOST_CHECK_EQUAL(sm2[0], largeString);

}
<commit_msg>Add failing string testcase<commit_after>#define BOOST_TEST_MODULE main

#include <boost/test/unit_test.hpp>
#include <boost/test/included/unit_test.hpp>

#include "SharedMap.hpp"

BOOST_AUTO_TEST_CASE(SharedMap_basic_test) {

	SharedMap<int, int> sm;
	sm.insert(0, 0);
	BOOST_CHECK_EQUAL(sm[0], 0);

}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_share_data) {
	SharedMap<int, int> sm1, sm2;

	sm1.insert(0, 0);
	BOOST_CHECK_EQUAL(sm1[0], sm2[0]);
}

BOOST_AUTO_TEST_CASE(SharedMap_should_throw_if_non_existant_value_is_requested) {
	SharedMap<int, int> sm;

	BOOST_CHECK_THROW(sm.at(1), std::out_of_range);
}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_be_independent_if_they_are_destroyed) {
	{
		// run1
		SharedMap<int, int> sm;
		sm.insert(0, 0);
		BOOST_CHECK_EQUAL(sm[0], 0);
	}

	{
		// run2
		SharedMap<int, int> sm;
		BOOST_CHECK_THROW(sm.at(0), std::out_of_range);
	}

}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_share_keys_for_allocating_keys) {
	SharedMap<int, std::string> sm1, sm2;

	sm1.insert(0, "value");
	BOOST_CHECK_EQUAL(sm2[0], "value");

}

BOOST_AUTO_TEST_CASE(SharedMap_instances_should_share_large_strings) {
	SharedMap<int, std::string> sm1, sm2;

	std::string largeString = "111111111111111111111111111111111111111111111";

	sm1.insert(0, largeString);

	BOOST_CHECK_EQUAL(sm2[0], largeString);

}

BOOST_AUTO_TEST_CASE(SharedMap_allocated_strings_should_be_shared) {
	SharedMap<int, std::string> sm;

	std::string largeString = "111111111111111111111111111111111111111111111";

	sm.insert(0, largeString);
	void* ptr = &sm[0][0];

	BOOST_CHECK(sm.isPointerShared(ptr));
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-file-style: "gnu" -*-
  This file is part of KMail, the KDE mail client.
  Copyright (c) 2009 Montel Laurent <montel@kde.org>

  KMail is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.

  KMail is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "collectionviewpage.h"

#include <akonadi/collection.h>
#include <akonadi/entitydisplayattribute.h>
#include <akonadi/private/collectionutils_p.h>
#include <QGroupBox>
#include <QHBoxLayout>
#include <kicondialog.h>
#include <QLabel>
#include <QCheckBox>
#include <QVBoxLayout>
#include <KLocale>
#include <KDialog>
#include "messagelist/utils/aggregationcombobox.h"
#include "messagelist/utils/aggregationconfigbutton.h"
#include "messagelist/utils/themecombobox.h"
#include "messagelist/utils/themeconfigbutton.h"

CollectionViewPage::CollectionViewPage(QWidget * parent) :
    CollectionPropertiesPage( parent )
{
  setPageTitle( i18nc( "@title:tab View settings for a folder.", "View" ) );
  init();
}

void CollectionViewPage::init()
{
#if 0
  mIsLocalSystemFolder = mDlg->folder()->isSystemFolder();
  mIsResourceFolder = kmkernel->iCalIface().isStandardResourceFolder( mDlg->folder() );
#endif

  QVBoxLayout * topLayout = new QVBoxLayout( this );
  topLayout->setSpacing( KDialog::spacingHint() );
  topLayout->setMargin( 0 );

  // Musn't be able to edit details for non-resource, system folder.
  if ( !mIsLocalSystemFolder || mIsResourceFolder )
  {
    // icons
    mIconsCheckBox = new QCheckBox( i18n( "Use custom &icons"), this );
    mIconsCheckBox->setChecked( false );

    mNormalIconLabel = new QLabel( i18nc( "Icon used for folders with no unread messages.", "&Normal:" ), this );
    mNormalIconLabel->setEnabled( false );

    mNormalIconButton = new KIconButton( this );
    mNormalIconLabel->setBuddy( mNormalIconButton );
    mNormalIconButton->setIconType( KIconLoader::NoGroup, KIconLoader::Place, false );
    mNormalIconButton->setIconSize( 16 );
    mNormalIconButton->setStrictIconSize( true );
    mNormalIconButton->setFixedSize( 28, 28 );
    // Can't use iconset here.
    mNormalIconButton->setIcon( "folder" );
    mNormalIconButton->setEnabled( false );

    mUnreadIconLabel = new QLabel( i18nc( "Icon used for folders which do have unread messages.", "&Unread:" ), this );
    mUnreadIconLabel->setEnabled( false );

    mUnreadIconButton = new KIconButton( this );
    mUnreadIconLabel->setBuddy( mUnreadIconButton );
    mUnreadIconButton->setIconType( KIconLoader::NoGroup, KIconLoader::Place, false );
    mUnreadIconButton->setIconSize( 16 );
    mUnreadIconButton->setStrictIconSize( true );
    mUnreadIconButton->setFixedSize( 28, 28 );
    // Can't use iconset here.
    mUnreadIconButton->setIcon( "folder-open" );
    mUnreadIconButton->setEnabled( false );

    QHBoxLayout * iconHLayout = new QHBoxLayout();
    iconHLayout->addWidget( mIconsCheckBox );
    iconHLayout->addStretch( 2 );
    iconHLayout->addWidget( mNormalIconLabel );
    iconHLayout->addWidget( mNormalIconButton );
    iconHLayout->addWidget( mUnreadIconLabel );
    iconHLayout->addWidget( mUnreadIconButton );
    iconHLayout->addStretch( 1 );
    topLayout->addLayout( iconHLayout );

    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mNormalIconLabel, SLOT( setEnabled( bool ) ) );
    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mNormalIconButton, SLOT( setEnabled( bool ) ) );
    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mUnreadIconButton, SLOT( setEnabled( bool ) ) );
    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mUnreadIconLabel, SLOT( setEnabled( bool ) ) );

    connect( mNormalIconButton, SIGNAL( iconChanged( const QString& ) ),
             this, SLOT( slotChangeIcon( const QString& ) ) );
  }

  // sender or receiver column
  const QString senderReceiverColumnTip = i18n( "Show Sender/Receiver Column in List of Messages" );

  QLabel * senderReceiverColumnLabel = new QLabel( i18n( "Sho&w column:" ), this );
  mShowSenderReceiverComboBox = new KComboBox( this );
  mShowSenderReceiverComboBox->setToolTip( senderReceiverColumnTip );
  senderReceiverColumnLabel->setBuddy( mShowSenderReceiverComboBox );
  mShowSenderReceiverComboBox->insertItem( 0, i18nc( "@item:inlistbox Show default value.", "Default" ) );
  mShowSenderReceiverComboBox->insertItem( 1, i18nc( "@item:inlistbox Show sender.", "Sender" ) );
  mShowSenderReceiverComboBox->insertItem( 2, i18nc( "@item:inlistbox Show receiver.", "Receiver" ) );

  QHBoxLayout * senderReceiverColumnHLayout = new QHBoxLayout();
  senderReceiverColumnHLayout->addWidget( senderReceiverColumnLabel );
  senderReceiverColumnHLayout->addWidget( mShowSenderReceiverComboBox );
  topLayout->addLayout( senderReceiverColumnHLayout );

  // message list
  QGroupBox * messageListGroup = new QGroupBox( i18n( "Message List" ), this );
  QVBoxLayout * messageListGroupLayout = new QVBoxLayout( messageListGroup );
  messageListGroupLayout->setSpacing( KDialog::spacingHint() );
  topLayout->addWidget( messageListGroup );

  // message list aggregation
  mUseDefaultAggregationCheckBox = new QCheckBox( i18n( "Use default aggregation" ), messageListGroup );
  messageListGroupLayout->addWidget( mUseDefaultAggregationCheckBox );
  connect( mUseDefaultAggregationCheckBox, SIGNAL( stateChanged( int ) ),
           this, SLOT( slotAggregationCheckboxChanged() ) );

  mAggregationComboBox = new MessageList::Utils::AggregationComboBox( messageListGroup );

  QLabel * aggregationLabel = new QLabel( i18n( "Aggregation" ), messageListGroup );
  aggregationLabel->setBuddy( mAggregationComboBox );

  using MessageList::Utils::AggregationConfigButton;
  AggregationConfigButton * aggregationConfigButton = new AggregationConfigButton( messageListGroup, mAggregationComboBox );
  // Make sure any changes made in the aggregations configure dialog are reflected in the combo.
  connect( aggregationConfigButton, SIGNAL( configureDialogCompleted() ),
           this, SLOT( slotSelectFolderAggregation() ) );

  QHBoxLayout * aggregationLayout = new QHBoxLayout();
  aggregationLayout->addWidget( aggregationLabel, 1 );
  aggregationLayout->addWidget( mAggregationComboBox, 1 );
  aggregationLayout->addWidget( aggregationConfigButton, 0 );
  messageListGroupLayout->addLayout( aggregationLayout );

  // message list theme
  mUseDefaultThemeCheckBox = new QCheckBox( i18n( "Use default theme" ), messageListGroup );
  messageListGroupLayout->addWidget( mUseDefaultThemeCheckBox );
  connect( mUseDefaultThemeCheckBox, SIGNAL( stateChanged( int ) ),
           this, SLOT( slotThemeCheckboxChanged() ) );

  mThemeComboBox = new MessageList::Utils::ThemeComboBox( messageListGroup );

  QLabel * themeLabel = new QLabel( i18n( "Theme" ), messageListGroup );
  themeLabel->setBuddy( mThemeComboBox );

  using MessageList::Utils::ThemeConfigButton;
  ThemeConfigButton * themeConfigButton = new ThemeConfigButton( messageListGroup, mThemeComboBox );
  // Make sure any changes made in the themes configure dialog are reflected in the combo.
  connect( themeConfigButton, SIGNAL( configureDialogCompleted() ),
           this, SLOT( slotSelectFolderTheme() ) );

  QHBoxLayout * themeLayout = new QHBoxLayout();
  themeLayout->addWidget( themeLabel, 1 );
  themeLayout->addWidget( mThemeComboBox, 1 );
  themeLayout->addWidget( themeConfigButton, 0 );
  messageListGroupLayout->addLayout( themeLayout );

  topLayout->addStretch( 100 );
#if 0
  initializeWithValuesFromFolder( mDlg->folder() );
#endif
}

#if 0
bool FolderDialogViewTab::save()
{
  KMFolder * folder = mDlg->folder();

  // folder icons
  if ( !mIsLocalSystemFolder || mIsResourceFolder )
  {
    // Update the tree if new icon paths are different and not empty or if
    // useCustomIcons changed.
    if ( folder->useCustomIcons() != mIconsCheckBox->isChecked() )
    {
      folder->setUseCustomIcons( mIconsCheckBox->isChecked() );
      // Reset icons, useCustomIcons was turned off.
      if( !folder->useCustomIcons() )
        folder->setIconPaths( "", "" );
    }
    if ( folder->useCustomIcons() &&
         ( ( mNormalIconButton->icon() != folder->normalIconPath() &&
             !mNormalIconButton->icon().isEmpty() ) ||
           ( mUnreadIconButton->icon() != folder->unreadIconPath() &&
             !mUnreadIconButton->icon().isEmpty() ) ) )
    {
      folder->setIconPaths( mNormalIconButton->icon(), mUnreadIconButton->icon() );
    }
  }

  // sender or receiver column
  if ( mShowSenderReceiverComboBox->currentIndex() == 1 )
    folder->setUserWhoField( "From" );
  else if ( mShowSenderReceiverComboBox->currentIndex() == 2 )
    folder->setUserWhoField( "To" );
  else
    folder->setUserWhoField( "" );
#ifdef OLD_MESSAGELIST
  // message list aggregation
  MessageListView::StorageModel messageListStorageModel( folder );
  const bool usePrivateAggregation = !mUseDefaultAggregationCheckBox->isChecked();
  mAggregationComboBox->writeStorageModelConfig( &messageListStorageModel, usePrivateAggregation );

  // message list theme
  const bool usePrivateTheme = !mUseDefaultThemeCheckBox->isChecked();
  mThemeComboBox->writeStorageModelConfig( &messageListStorageModel, usePrivateTheme );
#endif
  return true;
}

void FolderDialogViewTab::slotChangeIcon( const QString & icon )
{
    mUnreadIconButton->setIcon( icon );
}

void FolderDialogViewTab::slotAggregationCheckboxChanged()
{
  mAggregationComboBox->setEnabled( !mUseDefaultAggregationCheckBox->isChecked() );
}

void FolderDialogViewTab::slotThemeCheckboxChanged()
{
  mThemeComboBox->setEnabled( !mUseDefaultThemeCheckBox->isChecked() );
}

void FolderDialogViewTab::slotSelectFolderAggregation()
{
#ifdef OLD_MESSAGELIST
  MessageListView::StorageModel messageListStorageModel( mDlg->folder() );
  bool usesPrivateAggregation = false;
  mAggregationComboBox->readStorageModelConfig( &messageListStorageModel, usesPrivateAggregation );
  mUseDefaultAggregationCheckBox->setChecked( !usesPrivateAggregation );
#endif
}

void FolderDialogViewTab::slotSelectFolderTheme()
{
#ifdef OLD_MESSAGELIST
  MessageListView::StorageModel messageListStorageModel( mDlg->folder() );
  bool usesPrivateTheme = false;
  mThemeComboBox->readStorageModelConfig( &messageListStorageModel, usesPrivateTheme );
  mUseDefaultThemeCheckBox->setChecked( !usesPrivateTheme );
#endif
}

void FolderDialogViewTab::initializeWithValuesFromFolder( KMFolder * folder )
{
  if ( !folder )
    return;

  // folder icons
  if ( !mIsLocalSystemFolder || mIsResourceFolder )
  {
    const bool customIcons = folder->useCustomIcons();
    mIconsCheckBox->setChecked( customIcons );
    mNormalIconLabel->setEnabled( customIcons );
    mNormalIconButton->setEnabled( customIcons );
    mUnreadIconLabel->setEnabled( customIcons );
    mUnreadIconButton->setEnabled( customIcons );

    const QString normalIconPath = folder->normalIconPath();
    if( !normalIconPath.isEmpty() )
      mNormalIconButton->setIcon( normalIconPath );

    const QString unreadIconPath = folder->unreadIconPath();
    if( !unreadIconPath.isEmpty() )
      mUnreadIconButton->setIcon( unreadIconPath );
  }

  // sender or receiver column
  const QString whoField = mDlg->folder()->userWhoField();
  if ( whoField.isEmpty() )
    mShowSenderReceiverComboBox->setCurrentIndex( 0 );
  else if ( whoField == "From" )
    mShowSenderReceiverComboBox->setCurrentIndex( 1 );
  else if ( whoField == "To" )
    mShowSenderReceiverComboBox->setCurrentIndex( 2 );

  // message list aggregation
  slotSelectFolderAggregation();

  // message list theme
  slotSelectFolderTheme();
}
#endif
void CollectionViewPage::load( const Akonadi::Collection & col )
{
  QString iconName;
  QString unreadIconName;
  bool iconWasEmpty = false;
  if ( col.hasAttribute<Akonadi::EntityDisplayAttribute>() ) {
    iconName = col.attribute<Akonadi::EntityDisplayAttribute>()->iconName();
    unreadIconName = col.attribute<Akonadi::EntityDisplayAttribute>()->activeIconName();
    qDebug()<<" iconName :"<<iconName;
    qDebug()<<" unreadIconName :"<<unreadIconName;
  }

  if ( iconName.isEmpty() ) {
    iconName = Akonadi::CollectionUtils::defaultIconName( col );
    iconWasEmpty = true;
  }
  mNormalIconButton->setIcon( iconName );

  if ( unreadIconName.isEmpty() ) {
    mUnreadIconButton->setIcon( iconName );
  }
  else {
    mUnreadIconButton->setIcon( unreadIconName );
  }

  mIconsCheckBox->setChecked( !iconWasEmpty );
}

void CollectionViewPage::save( Akonadi::Collection & col )
{

  if ( mIconsCheckBox->isChecked() ) {
    col.attribute<Akonadi::EntityDisplayAttribute>( Akonadi::Collection::AddIfMissing )->setIconName( mNormalIconButton->icon() );
    col.attribute<Akonadi::EntityDisplayAttribute>( Akonadi::Collection::AddIfMissing )->setActiveIconName( mUnreadIconButton->icon() );
  }
  else if ( col.hasAttribute<Akonadi::EntityDisplayAttribute>() ) {
    col.attribute<Akonadi::EntityDisplayAttribute>()->setIconName( QString() );
    col.attribute<Akonadi::EntityDisplayAttribute>()->setActiveIconName( QString() );
  }
}

<commit_msg>Remove debug<commit_after>/* -*- mode: C++; c-file-style: "gnu" -*-
  This file is part of KMail, the KDE mail client.
  Copyright (c) 2009 Montel Laurent <montel@kde.org>

  KMail is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License, version 2, as
  published by the Free Software Foundation.

  KMail is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "collectionviewpage.h"

#include <akonadi/collection.h>
#include <akonadi/entitydisplayattribute.h>
#include <akonadi/private/collectionutils_p.h>
#include <QGroupBox>
#include <QHBoxLayout>
#include <kicondialog.h>
#include <QLabel>
#include <QCheckBox>
#include <QVBoxLayout>
#include <KLocale>
#include <KDialog>
#include "messagelist/utils/aggregationcombobox.h"
#include "messagelist/utils/aggregationconfigbutton.h"
#include "messagelist/utils/themecombobox.h"
#include "messagelist/utils/themeconfigbutton.h"

CollectionViewPage::CollectionViewPage(QWidget * parent) :
    CollectionPropertiesPage( parent )
{
  setPageTitle( i18nc( "@title:tab View settings for a folder.", "View" ) );
  init();
}

void CollectionViewPage::init()
{
#if 0
  mIsLocalSystemFolder = mDlg->folder()->isSystemFolder();
  mIsResourceFolder = kmkernel->iCalIface().isStandardResourceFolder( mDlg->folder() );
#endif

  QVBoxLayout * topLayout = new QVBoxLayout( this );
  topLayout->setSpacing( KDialog::spacingHint() );
  topLayout->setMargin( 0 );

  // Musn't be able to edit details for non-resource, system folder.
  if ( !mIsLocalSystemFolder || mIsResourceFolder )
  {
    // icons
    mIconsCheckBox = new QCheckBox( i18n( "Use custom &icons"), this );
    mIconsCheckBox->setChecked( false );

    mNormalIconLabel = new QLabel( i18nc( "Icon used for folders with no unread messages.", "&Normal:" ), this );
    mNormalIconLabel->setEnabled( false );

    mNormalIconButton = new KIconButton( this );
    mNormalIconLabel->setBuddy( mNormalIconButton );
    mNormalIconButton->setIconType( KIconLoader::NoGroup, KIconLoader::Place, false );
    mNormalIconButton->setIconSize( 16 );
    mNormalIconButton->setStrictIconSize( true );
    mNormalIconButton->setFixedSize( 28, 28 );
    // Can't use iconset here.
    mNormalIconButton->setIcon( "folder" );
    mNormalIconButton->setEnabled( false );

    mUnreadIconLabel = new QLabel( i18nc( "Icon used for folders which do have unread messages.", "&Unread:" ), this );
    mUnreadIconLabel->setEnabled( false );

    mUnreadIconButton = new KIconButton( this );
    mUnreadIconLabel->setBuddy( mUnreadIconButton );
    mUnreadIconButton->setIconType( KIconLoader::NoGroup, KIconLoader::Place, false );
    mUnreadIconButton->setIconSize( 16 );
    mUnreadIconButton->setStrictIconSize( true );
    mUnreadIconButton->setFixedSize( 28, 28 );
    // Can't use iconset here.
    mUnreadIconButton->setIcon( "folder-open" );
    mUnreadIconButton->setEnabled( false );

    QHBoxLayout * iconHLayout = new QHBoxLayout();
    iconHLayout->addWidget( mIconsCheckBox );
    iconHLayout->addStretch( 2 );
    iconHLayout->addWidget( mNormalIconLabel );
    iconHLayout->addWidget( mNormalIconButton );
    iconHLayout->addWidget( mUnreadIconLabel );
    iconHLayout->addWidget( mUnreadIconButton );
    iconHLayout->addStretch( 1 );
    topLayout->addLayout( iconHLayout );

    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mNormalIconLabel, SLOT( setEnabled( bool ) ) );
    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mNormalIconButton, SLOT( setEnabled( bool ) ) );
    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mUnreadIconButton, SLOT( setEnabled( bool ) ) );
    connect( mIconsCheckBox, SIGNAL( toggled( bool ) ),
             mUnreadIconLabel, SLOT( setEnabled( bool ) ) );

    connect( mNormalIconButton, SIGNAL( iconChanged( const QString& ) ),
             this, SLOT( slotChangeIcon( const QString& ) ) );
  }

  // sender or receiver column
  const QString senderReceiverColumnTip = i18n( "Show Sender/Receiver Column in List of Messages" );

  QLabel * senderReceiverColumnLabel = new QLabel( i18n( "Sho&w column:" ), this );
  mShowSenderReceiverComboBox = new KComboBox( this );
  mShowSenderReceiverComboBox->setToolTip( senderReceiverColumnTip );
  senderReceiverColumnLabel->setBuddy( mShowSenderReceiverComboBox );
  mShowSenderReceiverComboBox->insertItem( 0, i18nc( "@item:inlistbox Show default value.", "Default" ) );
  mShowSenderReceiverComboBox->insertItem( 1, i18nc( "@item:inlistbox Show sender.", "Sender" ) );
  mShowSenderReceiverComboBox->insertItem( 2, i18nc( "@item:inlistbox Show receiver.", "Receiver" ) );

  QHBoxLayout * senderReceiverColumnHLayout = new QHBoxLayout();
  senderReceiverColumnHLayout->addWidget( senderReceiverColumnLabel );
  senderReceiverColumnHLayout->addWidget( mShowSenderReceiverComboBox );
  topLayout->addLayout( senderReceiverColumnHLayout );

  // message list
  QGroupBox * messageListGroup = new QGroupBox( i18n( "Message List" ), this );
  QVBoxLayout * messageListGroupLayout = new QVBoxLayout( messageListGroup );
  messageListGroupLayout->setSpacing( KDialog::spacingHint() );
  topLayout->addWidget( messageListGroup );

  // message list aggregation
  mUseDefaultAggregationCheckBox = new QCheckBox( i18n( "Use default aggregation" ), messageListGroup );
  messageListGroupLayout->addWidget( mUseDefaultAggregationCheckBox );
  connect( mUseDefaultAggregationCheckBox, SIGNAL( stateChanged( int ) ),
           this, SLOT( slotAggregationCheckboxChanged() ) );

  mAggregationComboBox = new MessageList::Utils::AggregationComboBox( messageListGroup );

  QLabel * aggregationLabel = new QLabel( i18n( "Aggregation" ), messageListGroup );
  aggregationLabel->setBuddy( mAggregationComboBox );

  using MessageList::Utils::AggregationConfigButton;
  AggregationConfigButton * aggregationConfigButton = new AggregationConfigButton( messageListGroup, mAggregationComboBox );
  // Make sure any changes made in the aggregations configure dialog are reflected in the combo.
  connect( aggregationConfigButton, SIGNAL( configureDialogCompleted() ),
           this, SLOT( slotSelectFolderAggregation() ) );

  QHBoxLayout * aggregationLayout = new QHBoxLayout();
  aggregationLayout->addWidget( aggregationLabel, 1 );
  aggregationLayout->addWidget( mAggregationComboBox, 1 );
  aggregationLayout->addWidget( aggregationConfigButton, 0 );
  messageListGroupLayout->addLayout( aggregationLayout );

  // message list theme
  mUseDefaultThemeCheckBox = new QCheckBox( i18n( "Use default theme" ), messageListGroup );
  messageListGroupLayout->addWidget( mUseDefaultThemeCheckBox );
  connect( mUseDefaultThemeCheckBox, SIGNAL( stateChanged( int ) ),
           this, SLOT( slotThemeCheckboxChanged() ) );

  mThemeComboBox = new MessageList::Utils::ThemeComboBox( messageListGroup );

  QLabel * themeLabel = new QLabel( i18n( "Theme" ), messageListGroup );
  themeLabel->setBuddy( mThemeComboBox );

  using MessageList::Utils::ThemeConfigButton;
  ThemeConfigButton * themeConfigButton = new ThemeConfigButton( messageListGroup, mThemeComboBox );
  // Make sure any changes made in the themes configure dialog are reflected in the combo.
  connect( themeConfigButton, SIGNAL( configureDialogCompleted() ),
           this, SLOT( slotSelectFolderTheme() ) );

  QHBoxLayout * themeLayout = new QHBoxLayout();
  themeLayout->addWidget( themeLabel, 1 );
  themeLayout->addWidget( mThemeComboBox, 1 );
  themeLayout->addWidget( themeConfigButton, 0 );
  messageListGroupLayout->addLayout( themeLayout );

  topLayout->addStretch( 100 );
#if 0
  initializeWithValuesFromFolder( mDlg->folder() );
#endif
}

#if 0
bool FolderDialogViewTab::save()
{
  KMFolder * folder = mDlg->folder();

  // folder icons
  if ( !mIsLocalSystemFolder || mIsResourceFolder )
  {
    // Update the tree if new icon paths are different and not empty or if
    // useCustomIcons changed.
    if ( folder->useCustomIcons() != mIconsCheckBox->isChecked() )
    {
      folder->setUseCustomIcons( mIconsCheckBox->isChecked() );
      // Reset icons, useCustomIcons was turned off.
      if( !folder->useCustomIcons() )
        folder->setIconPaths( "", "" );
    }
    if ( folder->useCustomIcons() &&
         ( ( mNormalIconButton->icon() != folder->normalIconPath() &&
             !mNormalIconButton->icon().isEmpty() ) ||
           ( mUnreadIconButton->icon() != folder->unreadIconPath() &&
             !mUnreadIconButton->icon().isEmpty() ) ) )
    {
      folder->setIconPaths( mNormalIconButton->icon(), mUnreadIconButton->icon() );
    }
  }

  // sender or receiver column
  if ( mShowSenderReceiverComboBox->currentIndex() == 1 )
    folder->setUserWhoField( "From" );
  else if ( mShowSenderReceiverComboBox->currentIndex() == 2 )
    folder->setUserWhoField( "To" );
  else
    folder->setUserWhoField( "" );
#ifdef OLD_MESSAGELIST
  // message list aggregation
  MessageListView::StorageModel messageListStorageModel( folder );
  const bool usePrivateAggregation = !mUseDefaultAggregationCheckBox->isChecked();
  mAggregationComboBox->writeStorageModelConfig( &messageListStorageModel, usePrivateAggregation );

  // message list theme
  const bool usePrivateTheme = !mUseDefaultThemeCheckBox->isChecked();
  mThemeComboBox->writeStorageModelConfig( &messageListStorageModel, usePrivateTheme );
#endif
  return true;
}

void FolderDialogViewTab::slotChangeIcon( const QString & icon )
{
    mUnreadIconButton->setIcon( icon );
}

void FolderDialogViewTab::slotAggregationCheckboxChanged()
{
  mAggregationComboBox->setEnabled( !mUseDefaultAggregationCheckBox->isChecked() );
}

void FolderDialogViewTab::slotThemeCheckboxChanged()
{
  mThemeComboBox->setEnabled( !mUseDefaultThemeCheckBox->isChecked() );
}

void FolderDialogViewTab::slotSelectFolderAggregation()
{
#ifdef OLD_MESSAGELIST
  MessageListView::StorageModel messageListStorageModel( mDlg->folder() );
  bool usesPrivateAggregation = false;
  mAggregationComboBox->readStorageModelConfig( &messageListStorageModel, usesPrivateAggregation );
  mUseDefaultAggregationCheckBox->setChecked( !usesPrivateAggregation );
#endif
}

void FolderDialogViewTab::slotSelectFolderTheme()
{
#ifdef OLD_MESSAGELIST
  MessageListView::StorageModel messageListStorageModel( mDlg->folder() );
  bool usesPrivateTheme = false;
  mThemeComboBox->readStorageModelConfig( &messageListStorageModel, usesPrivateTheme );
  mUseDefaultThemeCheckBox->setChecked( !usesPrivateTheme );
#endif
}

void FolderDialogViewTab::initializeWithValuesFromFolder( KMFolder * folder )
{
  if ( !folder )
    return;

  // folder icons
  if ( !mIsLocalSystemFolder || mIsResourceFolder )
  {
    const bool customIcons = folder->useCustomIcons();
    mIconsCheckBox->setChecked( customIcons );
    mNormalIconLabel->setEnabled( customIcons );
    mNormalIconButton->setEnabled( customIcons );
    mUnreadIconLabel->setEnabled( customIcons );
    mUnreadIconButton->setEnabled( customIcons );

    const QString normalIconPath = folder->normalIconPath();
    if( !normalIconPath.isEmpty() )
      mNormalIconButton->setIcon( normalIconPath );

    const QString unreadIconPath = folder->unreadIconPath();
    if( !unreadIconPath.isEmpty() )
      mUnreadIconButton->setIcon( unreadIconPath );
  }

  // sender or receiver column
  const QString whoField = mDlg->folder()->userWhoField();
  if ( whoField.isEmpty() )
    mShowSenderReceiverComboBox->setCurrentIndex( 0 );
  else if ( whoField == "From" )
    mShowSenderReceiverComboBox->setCurrentIndex( 1 );
  else if ( whoField == "To" )
    mShowSenderReceiverComboBox->setCurrentIndex( 2 );

  // message list aggregation
  slotSelectFolderAggregation();

  // message list theme
  slotSelectFolderTheme();
}
#endif
void CollectionViewPage::load( const Akonadi::Collection & col )
{
  QString iconName;
  QString unreadIconName;
  bool iconWasEmpty = false;
  if ( col.hasAttribute<Akonadi::EntityDisplayAttribute>() ) {
    iconName = col.attribute<Akonadi::EntityDisplayAttribute>()->iconName();
    unreadIconName = col.attribute<Akonadi::EntityDisplayAttribute>()->activeIconName();
  }

  if ( iconName.isEmpty() ) {
    iconName = Akonadi::CollectionUtils::defaultIconName( col );
    iconWasEmpty = true;
  }
  mNormalIconButton->setIcon( iconName );

  if ( unreadIconName.isEmpty() ) {
    mUnreadIconButton->setIcon( iconName );
  }
  else {
    mUnreadIconButton->setIcon( unreadIconName );
  }

  mIconsCheckBox->setChecked( !iconWasEmpty );
}

void CollectionViewPage::save( Akonadi::Collection & col )
{

  if ( mIconsCheckBox->isChecked() ) {
    col.attribute<Akonadi::EntityDisplayAttribute>( Akonadi::Collection::AddIfMissing )->setIconName( mNormalIconButton->icon() );
    col.attribute<Akonadi::EntityDisplayAttribute>( Akonadi::Collection::AddIfMissing )->setActiveIconName( mUnreadIconButton->icon() );
  }
  else if ( col.hasAttribute<Akonadi::EntityDisplayAttribute>() ) {
    col.attribute<Akonadi::EntityDisplayAttribute>()->setIconName( QString() );
    col.attribute<Akonadi::EntityDisplayAttribute>()->setActiveIconName( QString() );
  }
}

<|endoftext|>


<commit_before>#include "addressbookpage.h"
#include "ui_addressbookpage.h"

#include "addresstablemodel.h"
#include "optionsmodel.h"
#include "bitcoingui.h"
#include "editaddressdialog.h"
#include "csvmodelwriter.h"
#include "guiutil.h"

#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QMessageBox>
#include <QMenu>

#ifdef USE_QRCODE
#include "qrcodedialog.h"
#endif

AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AddressBookPage),
    model(0),
    optionsModel(0),
    mode(mode),
    tab(tab)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->newAddressButton->setIcon(QIcon());
    ui->copyToClipboard->setIcon(QIcon());
    ui->deleteButton->setIcon(QIcon());
#endif

#ifndef USE_QRCODE
    ui->showQRCode->setVisible(false);
#endif

    switch(mode)
    {
    case ForSending:
        connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        break;
    case ForEditing:
        ui->buttonBox->setVisible(false);
        break;
    }
    switch(tab)
    {
    case SendingTab:
        ui->labelExplanation->setVisible(false);
        ui->deleteButton->setVisible(true);
        ui->signMessage->setVisible(false);
        ui->verifyMessage->setVisible(true);
        ui->stakeForCharityPushButton->setVisible(true);
        break;
    case ReceivingTab:
        ui->deleteButton->setVisible(false);
        ui->signMessage->setVisible(true);
        ui->verifyMessage->setVisible(false);
        ui->stakeForCharityPushButton->setVisible(false);
        break;
    }

    // Context menu actions
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
    QAction *editAction = new QAction(tr("&Edit"), this);
    QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
    QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
    QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
    QAction *stakeForCharityAction = new QAction(ui->stakeForCharityPushButton->text(), this);
    deleteAction = new QAction(ui->deleteButton->text(), this);

    // Build context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if(tab == SendingTab)
        contextMenu->addAction(deleteAction);
    contextMenu->addSeparator();
    contextMenu->addAction(showQRCodeAction);
    if(tab == ReceivingTab)
        contextMenu->addAction(signMessageAction);
    else if(tab == SendingTab)
    {
        contextMenu->addAction(verifyMessageAction);
        contextMenu->addAction(stakeForCharityAction);
    }
    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
    connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
    connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
    connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));
    connect(stakeForCharityAction, SIGNAL(triggered()), this, SLOT(on_stakeForCharityPushButton_clicked()));
    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    // Pass through accept action from button box
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}

AddressBookPage::~AddressBookPage()
{
    delete ui;
}

void AddressBookPage::setModel(AddressTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    proxyModel->setDynamicSortFilter(true);
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    switch(tab)
    {
    case ReceivingTab:
        // Receive filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Receive);
        break;
    case SendingTab:
        // Send filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Send);
        break;
    }
    ui->tableView->setModel(proxyModel);
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);

    // Set column widths
    ui->tableView->horizontalHeader()->resizeSection(
            AddressTableModel::Address, 320);
    ui->tableView->horizontalHeader()->setResizeMode(
            AddressTableModel::Label, QHeaderView::Stretch);

    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(selectionChanged()));

    // Select row for newly created address
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(selectNewAddress(QModelIndex,int,int)));

    selectionChanged();
}

void AddressBookPage::setOptionsModel(OptionsModel *optionsModel)
{
    this->optionsModel = optionsModel;
}

void AddressBookPage::on_copyToClipboard_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

void AddressBookPage::onCopyLabelAction()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
}

void AddressBookPage::onEditAction()
{
    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::EditSendingAddress :
            EditAddressDialog::EditReceivingAddress);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_signMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit signMessage(addr);
}

void AddressBookPage::on_verifyMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit verifyMessage(addr);
}

void AddressBookPage::on_stakeForCharityPushButton_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit stakeForCharitySignal(addr);
}

void AddressBookPage::on_newAddressButton_clicked()
{
    if(!model)
        return;
    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::NewSendingAddress :
            EditAddressDialog::NewReceivingAddress, this);
    dlg.setModel(model);
    if(dlg.exec())
    {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteButton_clicked()
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;
    QModelIndexList indexes = table->selectionModel()->selectedRows();
    if(!indexes.isEmpty())
    {
        table->model()->removeRow(indexes.at(0).row());
    }
}

void AddressBookPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        switch(tab)
        {
        case SendingTab:
            // In sending tab, allow deletion of selection
            ui->deleteButton->setEnabled(true);
            ui->deleteButton->setVisible(true);
            deleteAction->setEnabled(true);
            ui->signMessage->setEnabled(false);
            ui->signMessage->setVisible(false);
            ui->verifyMessage->setEnabled(true);
            ui->verifyMessage->setVisible(true);
            ui->stakeForCharityPushButton->setEnabled(true);
            ui->stakeForCharityPushButton->setVisible(true);
            break;
        case ReceivingTab:
            // Deleting receiving addresses, however, is not allowed
            ui->deleteButton->setEnabled(false);
            ui->deleteButton->setVisible(false);
            deleteAction->setEnabled(false);
            ui->signMessage->setEnabled(true);
            ui->signMessage->setVisible(true);
            ui->verifyMessage->setEnabled(false);
            ui->verifyMessage->setVisible(false);
            ui->stakeForCharityPushButton->setEnabled(false);
            ui->stakeForCharityPushButton->setVisible(false);
            break;
        }
        ui->copyToClipboard->setEnabled(true);
        ui->showQRCode->setEnabled(true);
    }
    else
    {
        ui->deleteButton->setEnabled(false);
        ui->showQRCode->setEnabled(false);
        ui->copyToClipboard->setEnabled(false);
        ui->signMessage->setEnabled(false);
        ui->verifyMessage->setEnabled(false);
        ui->stakeForCharityPushButton->setEnabled(false);
    }
}

void AddressBookPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;
    // When this is a tab/widget and not a model dialog, ignore "done"
    if(mode == ForEditing)
        return;

    // Figure out which address was selected, and return it
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QVariant address = table->model()->data(index);
        returnValue = address.toString();
    }

    if(returnValue.isEmpty())
    {
        // If no address entry selected, return rejected
        retval = Rejected;
    }

    QDialog::done(retval);
}

void AddressBookPage::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Address Book Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(proxyModel);
    writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
    writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void AddressBookPage::on_showQRCode_clicked()
{
#ifdef USE_QRCODE
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();

        QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
        if(optionsModel)
            dialog->setModel(optionsModel);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
        dialog->show();
    }
#endif
}

void AddressBookPage::contextualMenu(const QPoint &point)
{
    QModelIndex index = ui->tableView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent));
    if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
    {
        // Select row of newly created address, once
        ui->tableView->setFocus();
        ui->tableView->selectRow(idx.row());
        newAddressToSelect.clear();
    }
}
<commit_msg>Add conditions for popup address book dialogs to not display unusable options. Only display options currently available in given address book situations.<commit_after>#include "addressbookpage.h"
#include "ui_addressbookpage.h"

#include "addresstablemodel.h"
#include "optionsmodel.h"
#include "bitcoingui.h"
#include "editaddressdialog.h"
#include "csvmodelwriter.h"
#include "guiutil.h"

#include <QSortFilterProxyModel>
#include <QClipboard>
#include <QMessageBox>
#include <QMenu>

#ifdef USE_QRCODE
#include "qrcodedialog.h"
#endif

AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AddressBookPage),
    model(0),
    optionsModel(0),
    mode(mode),
    tab(tab)
{
    ui->setupUi(this);

#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    ui->newAddressButton->setIcon(QIcon());
    ui->copyToClipboard->setIcon(QIcon());
    ui->deleteButton->setIcon(QIcon());
#endif

#ifndef USE_QRCODE
    ui->showQRCode->setVisible(false);
#endif

    switch(mode)
    {
    case ForSending:
        connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
        ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
        ui->tableView->setFocus();
        break;
    case ForEditing:
        ui->buttonBox->setVisible(false);
        break;
    }
    switch(tab)
    {
    case SendingTab:
        ui->labelExplanation->setVisible(false);
        ui->deleteButton->setVisible(true);
        ui->signMessage->setVisible(false);
        if(window()->windowTitle() != "Address Book")
        {
            ui->verifyMessage->setVisible(true);
            ui->stakeForCharityPushButton->setVisible(true);
        }
        else
        {
            ui->verifyMessage->setVisible(false);
            ui->stakeForCharityPushButton->setVisible(false);
        }
        break;
    case ReceivingTab:
        ui->deleteButton->setVisible(false);
        ui->signMessage->setVisible(false);
        ui->verifyMessage->setVisible(false);
        ui->stakeForCharityPushButton->setVisible(false);
        break;
    }

    // Context menu actions
    QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
    QAction *copyAddressAction = new QAction(ui->copyToClipboard->text(), this);
    QAction *editAction = new QAction(tr("&Edit"), this);
    QAction *showQRCodeAction = new QAction(ui->showQRCode->text(), this);
    QAction *signMessageAction = new QAction(ui->signMessage->text(), this);
    QAction *verifyMessageAction = new QAction(ui->verifyMessage->text(), this);
    QAction *stakeForCharityAction = new QAction(ui->stakeForCharityPushButton->text(), this);
    deleteAction = new QAction(ui->deleteButton->text(), this);

    // Build context menu
    contextMenu = new QMenu();
    contextMenu->addAction(copyAddressAction);
    contextMenu->addAction(copyLabelAction);
    contextMenu->addAction(editAction);
    if(tab == SendingTab)
        contextMenu->addAction(deleteAction);
    contextMenu->addSeparator();
    contextMenu->addAction(showQRCodeAction);
    if(tab == ReceivingTab && window()->windowTitle() != "Address Book")
        contextMenu->addAction(signMessageAction);
    if(tab == SendingTab && window()->windowTitle() != "Address Book")
    {
        contextMenu->addAction(verifyMessageAction);
        contextMenu->addAction(stakeForCharityAction);
    }
    // Connect signals for context menu actions
    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
    connect(showQRCodeAction, SIGNAL(triggered()), this, SLOT(on_showQRCode_clicked()));
    connect(signMessageAction, SIGNAL(triggered()), this, SLOT(on_signMessage_clicked()));
    connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(on_verifyMessage_clicked()));
    connect(stakeForCharityAction, SIGNAL(triggered()), this, SLOT(on_stakeForCharityPushButton_clicked()));
    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));

    // Pass through accept action from button box
    connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
}

AddressBookPage::~AddressBookPage()
{
    delete ui;
}

void AddressBookPage::setModel(AddressTableModel *model)
{
    this->model = model;
    if(!model)
        return;

    proxyModel = new QSortFilterProxyModel(this);
    proxyModel->setSourceModel(model);
    proxyModel->setDynamicSortFilter(true);
    proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    switch(tab)
    {
    case ReceivingTab:
        // Receive filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Receive);
        break;
    case SendingTab:
        // Send filter
        proxyModel->setFilterRole(AddressTableModel::TypeRole);
        proxyModel->setFilterFixedString(AddressTableModel::Send);
        break;
    }
    ui->tableView->setModel(proxyModel);
    ui->tableView->sortByColumn(0, Qt::AscendingOrder);

    // Set column widths
    ui->tableView->horizontalHeader()->resizeSection(
            AddressTableModel::Address, 320);
    ui->tableView->horizontalHeader()->setResizeMode(
            AddressTableModel::Label, QHeaderView::Stretch);

    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(selectionChanged()));

    // Select row for newly created address
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(selectNewAddress(QModelIndex,int,int)));

    selectionChanged();
}

void AddressBookPage::setOptionsModel(OptionsModel *optionsModel)
{
    this->optionsModel = optionsModel;
}

void AddressBookPage::on_copyToClipboard_clicked()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
}

void AddressBookPage::onCopyLabelAction()
{
    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
}

void AddressBookPage::onEditAction()
{
    if(!ui->tableView->selectionModel())
        return;
    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
    if(indexes.isEmpty())
        return;

    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::EditSendingAddress :
            EditAddressDialog::EditReceivingAddress);
    dlg.setModel(model);
    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
    dlg.loadRow(origIndex.row());
    dlg.exec();
}

void AddressBookPage::on_signMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit signMessage(addr);
}

void AddressBookPage::on_verifyMessage_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit verifyMessage(addr);
}

void AddressBookPage::on_stakeForCharityPushButton_clicked()
{
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
    QString addr;

    foreach (QModelIndex index, indexes)
    {
        QVariant address = index.data();
        addr = address.toString();
    }

    emit stakeForCharitySignal(addr);
}

void AddressBookPage::on_newAddressButton_clicked()
{
    if(!model)
        return;
    EditAddressDialog dlg(
            tab == SendingTab ?
            EditAddressDialog::NewSendingAddress :
            EditAddressDialog::NewReceivingAddress, this);
    dlg.setModel(model);
    if(dlg.exec())
    {
        newAddressToSelect = dlg.getAddress();
    }
}

void AddressBookPage::on_deleteButton_clicked()
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;
    QModelIndexList indexes = table->selectionModel()->selectedRows();
    if(!indexes.isEmpty())
    {
        table->model()->removeRow(indexes.at(0).row());
    }
}

void AddressBookPage::selectionChanged()
{
    // Set button states based on selected tab and selection
    QTableView *table = ui->tableView;
    if(!table->selectionModel())
        return;

    if(table->selectionModel()->hasSelection())
    {
        switch(tab)
        {
        case SendingTab:
            // In sending tab, allow deletion of selection
            ui->deleteButton->setEnabled(true);
            ui->deleteButton->setVisible(true);
            deleteAction->setEnabled(true);
            ui->signMessage->setEnabled(false);
            ui->signMessage->setVisible(false);
            if(window()->windowTitle() != "Address Book")
            {
                ui->verifyMessage->setEnabled(true);
                ui->verifyMessage->setVisible(true);
                ui->stakeForCharityPushButton->setEnabled(true);
                ui->stakeForCharityPushButton->setVisible(true);
            }
            break;
        case ReceivingTab:
            // Deleting receiving addresses, however, is not allowed
            ui->deleteButton->setEnabled(false);
            ui->deleteButton->setVisible(false);
            deleteAction->setEnabled(false);
            if(window()->windowTitle() != "Address Book")
            {
                ui->signMessage->setEnabled(true);
                ui->signMessage->setVisible(true);
            }
            ui->verifyMessage->setEnabled(false);
            ui->verifyMessage->setVisible(false);
            ui->stakeForCharityPushButton->setEnabled(false);
            ui->stakeForCharityPushButton->setVisible(false);
            break;
        }
        ui->copyToClipboard->setEnabled(true);
        ui->showQRCode->setEnabled(true);
    }
    else
    {
        ui->deleteButton->setEnabled(false);
        ui->showQRCode->setEnabled(false);
        ui->copyToClipboard->setEnabled(false);
        ui->signMessage->setEnabled(false);
        ui->verifyMessage->setEnabled(false);
        ui->stakeForCharityPushButton->setEnabled(false);
    }
}

void AddressBookPage::done(int retval)
{
    QTableView *table = ui->tableView;
    if(!table->selectionModel() || !table->model())
        return;
    // When this is a tab/widget and not a model dialog, ignore "done"
    if(mode == ForEditing)
        return;

    // Figure out which address was selected, and return it
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QVariant address = table->model()->data(index);
        returnValue = address.toString();
    }

    if(returnValue.isEmpty())
    {
        // If no address entry selected, return rejected
        retval = Rejected;
    }

    QDialog::done(retval);
}

void AddressBookPage::exportClicked()
{
    // CSV is currently the only supported format
    QString filename = GUIUtil::getSaveFileName(
            this,
            tr("Export Address Book Data"), QString(),
            tr("Comma separated file (*.csv)"));

    if (filename.isNull()) return;

    CSVModelWriter writer(filename);

    // name, column, role
    writer.setModel(proxyModel);
    writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
    writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);

    if(!writer.write())
    {
        QMessageBox::critical(this, tr("Error exporting"), tr("Could not write to file %1.").arg(filename),
                              QMessageBox::Abort, QMessageBox::Abort);
    }
}

void AddressBookPage::on_showQRCode_clicked()
{
#ifdef USE_QRCODE
    QTableView *table = ui->tableView;
    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);

    foreach (QModelIndex index, indexes)
    {
        QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString();

        QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this);
        if(optionsModel)
            dialog->setModel(optionsModel);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
        dialog->show();
    }
#endif
}

void AddressBookPage::contextualMenu(const QPoint &point)
{
    QModelIndex index = ui->tableView->indexAt(point);
    if(index.isValid())
    {
        contextMenu->exec(QCursor::pos());
    }
}

void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int end)
{
    QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent));
    if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
    {
        // Select row of newly created address, once
        ui->tableView->setFocus();
        ui->tableView->selectRow(idx.row());
        newAddressToSelect.clear();
    }
}
<|endoftext|>