<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik 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 any later version.
 *
 * This program 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "dbffile.hpp"
#include "utils.hpp"

#include <string>

dbf_file::dbf_file()
    : num_records_(0),
      num_fields_(0),
      record_length_(0),
      record_(0) {}

dbf_file::dbf_file(const char* file_name)
    :num_records_(0),
     num_fields_(0),
     record_length_(0),
     record_(0)
{
    file_.open(file_name);
    if (file_.is_open())
    {
        read_header();
    }
}

dbf_file::~dbf_file()
{
    ::operator delete(record_);
    file_.close();
}

bool dbf_file::open(const std::string& file_name)
{
    file_.open(file_name.c_str());
    if (file_.is_open())
        read_header();
    return file_?true:false;
}

bool dbf_file::is_open()
{
    return file_.is_open();
}

void dbf_file::close()
{
    if (file_ && file_.is_open())
        file_.close();
}

int dbf_file::num_records() const
{
    return num_records_;
}

int dbf_file::num_fields() const
{
    return num_fields_;
}

void dbf_file::move_to(int index)
{
    if (index>0 && index<=num_records_)
    {
        long pos=(num_fields_<<5)+34+(index-1)*(record_length_+1);
        file_.seekg(pos,std::ios::beg);
        file_.read(record_,record_length_);
    }
}

std::string dbf_file::string_value(int col) const
{
    if (col>=0 && col<num_fields_)
    {
        return std::string(record_+fields_[col].offset_,fields_[col].length_);
    }
    return "";
}

const field_descriptor& dbf_file::descriptor(int col) const
{
    assert(col>=0 && col<num_fields_);
    return fields_[col];
}

void dbf_file::add_attribute(int col,Feature const& f) const throw()
{
    if (col>=0 && col<num_fields_)
    {
        std::string name=fields_[col].name_;
	std::string str=trim(std::string(record_+fields_[col].offset_,fields_[col].length_));

        switch (fields_[col].type_)
        {
	case 'C':
	case 'D'://todo handle date?
	case 'M':
	case 'L':
	    f[name] = str;
	    break;
	case 'N':
        case 'F':
	    {
		if (str[0]=='*')
		{
		    boost::put(f,name,0);
		    break;
		}
		if (fields_[col].dec_>0)
		{
		    double d;
		    fromString(str,d);
		    boost::put(f,name,d);
		}
		else
		{
		    int i;
		    fromString(str,i);
		    boost::put(f,name,i);
		}
		break;
	    }
	}
    }
}

void dbf_file::read_header()
{
    char c=file_.get();
    if (c=='\3' || c=='\131')
    {
        skip(3);
        num_records_=read_int();
        assert(num_records_>0);
        num_fields_=read_short();
        assert(num_fields_>0);
        num_fields_=(num_fields_-33)/32;
        skip(22);
        int offset=0;
        char name[11];
        memset(&name,0,11);
        fields_.reserve(num_fields_);
        for (int i=0;i<num_fields_;++i)
        {
            field_descriptor desc;
            desc.index_=i;
            file_.read(name,10);
            desc.name_=trim_left(name);
            skip(1);
            desc.type_=file_.get();
            skip(4);
            desc.length_=file_.get();
            desc.dec_=file_.get();
            skip(14);
            desc.offset_=offset;
            offset+=desc.length_;
            fields_.push_back(desc);
        }
        record_length_=offset;
        if (record_length_>0)
        {
            record_=static_cast<char*>(::operator new (sizeof(char)*record_length_));
        }
    }
}

int dbf_file::read_short()
{
    char b[2];
    file_.read(b,2);
    return (b[0] & 0xff) | (b[1] & 0xff) << 8;
}

int dbf_file::read_int()
{
    char b[4];
    file_.read(b,4);
    return (b[0] & 0xff) | (b[1] & 0xff) << 8 |
	(b[2] & 0xff) << 16 | (b[3] & 0xff) <<24;
}

void dbf_file::skip(int bytes)
{
    file_.seekg(bytes,std::ios::cur);
}
<commit_msg>added explicit flags ios::in|ios::binary for win32 compat<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko
 *
 * Mapnik 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 any later version.
 *
 * This program 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include "dbffile.hpp"
#include "utils.hpp"
#include <boost/algorithm/string.hpp>
#include <string>

dbf_file::dbf_file()
    : num_records_(0),
      num_fields_(0),
      record_length_(0),
      record_(0) {}

dbf_file::dbf_file(const char* file_name)
    :num_records_(0),
     num_fields_(0),
     record_length_(0),
     record_(0)
{
    file_.open(file_name);
    if (file_.is_open())
    {
        read_header();
    }
}

dbf_file::~dbf_file()
{
    ::operator delete(record_);
    file_.close();
}

bool dbf_file::open(const std::string& file_name)
{
    file_.open(file_name.c_str(),std::ios::in|std::ios::binary);
    if (file_.is_open())
        read_header();
    return file_?true:false;
}

bool dbf_file::is_open()
{
    return file_.is_open();
}

void dbf_file::close()
{
    if (file_ && file_.is_open())
        file_.close();
}

int dbf_file::num_records() const
{
    return num_records_;
}

int dbf_file::num_fields() const
{
    return num_fields_;
}

void dbf_file::move_to(int index)
{
    if (index>0 && index<=num_records_)
    {
        long pos=(num_fields_<<5)+34+(index-1)*(record_length_+1);
        file_.seekg(pos,std::ios::beg);
        file_.read(record_,record_length_);
    }
}

std::string dbf_file::string_value(int col) const
{
    if (col>=0 && col<num_fields_)
    {
        return std::string(record_+fields_[col].offset_,fields_[col].length_);
    }
    return "";
}

const field_descriptor& dbf_file::descriptor(int col) const
{
    assert(col>=0 && col<num_fields_);
    return fields_[col];
}

void dbf_file::add_attribute(int col,Feature const& f) const throw()
{
    if (col>=0 && col<num_fields_)
    {
        std::string name=fields_[col].name_;
        std::string str=boost::trim_copy(std::string(record_+fields_[col].offset_,fields_[col].length_));

        switch (fields_[col].type_)
        {
        case 'C':
        case 'D'://todo handle date?
        case 'M':
        case 'L':
            f[name] = str;
            break;
        case 'N':
        case 'F':
            {
                if (str[0]=='*')
                {
                    boost::put(f,name,0);
                    break;
                }
                if (fields_[col].dec_>0)
                {
                    double d;
                    fromString(str,d);
                    boost::put(f,name,d);
                }
                else
                {
                    int i;
                    fromString(str,i);
                    boost::put(f,name,i);
                }
                break;
            }
        }
    }
}

void dbf_file::read_header()
{
    char c=file_.get();
    if (c=='\3' || c=='\131')
    {
        skip(3);
        num_records_=read_int();
        assert(num_records_>0);
        num_fields_=read_short();
        assert(num_fields_>0);
        num_fields_=(num_fields_-33)/32;
        skip(22);
        int offset=0;
        char name[11];
        memset(&name,0,11);
        fields_.reserve(num_fields_);
        for (int i=0;i<num_fields_;++i)
        {
            field_descriptor desc;
            desc.index_=i;
            file_.read(name,10);
            desc.name_=boost::trim_left_copy(std::string(name));
            std::clog << "name=" << name << std::endl;
            skip(1);
            desc.type_=file_.get();
            skip(4);
            desc.length_=file_.get();
            desc.dec_=file_.get();
            skip(14);
            desc.offset_=offset;
            offset+=desc.length_;
            fields_.push_back(desc);
        }
        record_length_=offset;
        if (record_length_>0)
        {
            record_=static_cast<char*>(::operator new (sizeof(char)*record_length_));
        }
    }
}

int dbf_file::read_short()
{
    char b[2];
    file_.read(b,2);
    return (b[0] & 0xff) | (b[1] & 0xff) << 8;
}

int dbf_file::read_int()
{
    char b[4];
    file_.read(b,4);
    return (b[0] & 0xff) | (b[1] & 0xff) << 8 |
        (b[2] & 0xff) << 16 | (b[3] & 0xff) <<24;
}

void dbf_file::skip(int bytes)
{
    file_.seekg(bytes,std::ios::cur);
}
<|endoftext|>


<commit_before>/**
 * PANDA 3D SOFTWARE
 * Copyright (c) Carnegie Mellon University.  All rights reserved.
 *
 * All use of this software is subject to the terms of the revised BSD
 * license.  You should have received a copy of this license along
 * with this source code in a file named "LICENSE."
 *
 * @file virtualFileSimple.cxx
 * @author drose
 * @date 2002-08-03
 */

#include "virtualFileSimple.h"
#include "virtualFileMount.h"
#include "virtualFileList.h"
#include "dcast.h"

TypeHandle VirtualFileSimple::_type_handle;

/**
 * Returns the VirtualFileSystem this file is associated with.
 */
VirtualFileSystem *VirtualFileSimple::
get_file_system() const {
  return _mount->get_file_system();
}

/**
 * Returns the full pathname to this file within the virtual file system.
 */
Filename VirtualFileSimple::
get_filename() const {
  string mount_point = _mount->get_mount_point();
  if (_local_filename.empty()) {
    if (mount_point.empty()) {
      return "/";
    } else {
      return string("/") + mount_point;
    }

  } else {
    if (mount_point.empty()) {
      return string("/") + _local_filename.get_fullpath();
    } else {
      return string("/") + mount_point + string("/") + _local_filename.get_fullpath();
    }
  }
}

/**
 * Returns true if this file exists, false otherwise.
 */
bool VirtualFileSimple::
has_file() const {
  return _mount->has_file(_local_filename);
}

/**
 * Returns true if this file represents a directory (and scan_directory() may
 * be called), false otherwise.
 */
bool VirtualFileSimple::
is_directory() const {
  return _mount->is_directory(_local_filename);
}

/**
 * Returns true if this file represents a regular file (and read_file() may be
 * called), false otherwise.
 */
bool VirtualFileSimple::
is_regular_file() const {
  return _mount->is_regular_file(_local_filename);
}

/**
 * Returns true if this file represents a writable regular file (and
 * write_file() may be called), false otherwise.
 */
bool VirtualFileSimple::
is_writable() const {
  return _mount->is_writable(_local_filename);
}

/**
 * Attempts to delete this file or directory.  This can remove a single file
 * or an empty directory.  It will not remove a nonempty directory.  Returns
 * true on success, false on failure.
 */
bool VirtualFileSimple::
delete_file() {
  return _mount->delete_file(_local_filename);
}

/**
 * Attempts to move or rename this file or directory.  If the original file is
 * an ordinary file, it will quietly replace any already-existing file in the
 * new filename (but not a directory).  If the original file is a directory,
 * the new filename must not already exist.
 *
 * If the file is a directory, the new filename must be within the same mount
 * point.  If the file is an ordinary file, the new filename may be anywhere;
 * but if it is not within the same mount point then the rename operation is
 * automatically performed as a two-step copy-and-delete operation.
 */
bool VirtualFileSimple::
rename_file(VirtualFile *new_file) {
  if (new_file->is_of_type(VirtualFileSimple::get_class_type())) {
    VirtualFileSimple *new_file_simple = DCAST(VirtualFileSimple, new_file);
    if (new_file_simple->_mount == _mount) {
      // Same mount pount.
      if (_mount->rename_file(_local_filename, new_file_simple->_local_filename)) {
        return true;
      }
    }
  }

  // Different mount point, or the mount doesn't support renaming.  Do it by
  // hand.
  if (is_regular_file() && !new_file->is_directory()) {
    // copy-and-delete.
    new_file->delete_file();
    if (copy_file(new_file)) {
      delete_file();
      return true;
    }
  }

  return false;
}

/**
 * Attempts to copy the contents of this file to the indicated file.  Returns
 * true on success, false on failure.
 */
bool VirtualFileSimple::
copy_file(VirtualFile *new_file) {
  if (new_file->is_of_type(VirtualFileSimple::get_class_type())) {
    VirtualFileSimple *new_file_simple = DCAST(VirtualFileSimple, new_file);
    if (new_file_simple->_mount == _mount) {
      // Same mount pount.
      if (_mount->copy_file(_local_filename, new_file_simple->_local_filename)) {
        return true;
      }
    }
  }

  // Different mount point, or the mount doesn't support copying.  Do it by
  // hand.
  ostream *out = new_file->open_write_file(false, true);
  istream *in = open_read_file(false);

  static const size_t buffer_size = 4096;
  char buffer[buffer_size];

  in->read(buffer, buffer_size);
  size_t count = in->gcount();
  while (count != 0) {
    out->write(buffer, count);
    if (out->fail()) {
      new_file->close_write_file(out);
      close_read_file(in);
      new_file->delete_file();
      return false;
    }
    in->read(buffer, buffer_size);
    count = in->gcount();
  }

  if (!in->eof()) {
    new_file->close_write_file(out);
    close_read_file(in);
    new_file->delete_file();
    return false;
  }

  new_file->close_write_file(out);
  close_read_file(in);
  return true;
}

/**
 * Opens the file for reading.  Returns a newly allocated istream on success
 * (which you should eventually delete when you are done reading). Returns
 * NULL on failure.
 *
 * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
 * decompressed and the decompressed contents are returned.  This is different
 * than vfs-implicit-pz, which will automatically decompress a file if the
 * extension .pz is *not* given.
 */
istream *VirtualFileSimple::
open_read_file(bool auto_unwrap) const {

  // Will we be automatically unwrapping a .pz file?
  bool do_uncompress = (_implicit_pz_file ||
    (auto_unwrap && (_local_filename.get_extension() == "pz" ||
                     _local_filename.get_extension() == "gz")));

  Filename local_filename(_local_filename);
  if (do_uncompress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->open_read_file(local_filename, do_uncompress);
}

/**
 * Closes a file opened by a previous call to open_read_file().  This really
 * just deletes the istream pointer, but it is recommended to use this
 * interface instead of deleting it explicitly, to help work around compiler
 * issues.
 */
void VirtualFileSimple::
close_read_file(istream *stream) const {
  _mount->close_read_file(stream);
}

/**
 * Opens the file for writing.  Returns a newly allocated ostream on success
 * (which you should eventually delete when you are done writing). Returns
 * NULL on failure.
 *
 * If auto_wrap is true, an explicitly-named .pz file is automatically
 * compressed while writing.  If truncate is true, the file is truncated to
 * zero length before writing.
 */
ostream *VirtualFileSimple::
open_write_file(bool auto_wrap, bool truncate) {
  // Will we be automatically wrapping a .pz file?
  bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz"));

  Filename local_filename(_local_filename);
  if (do_compress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->open_write_file(local_filename, do_compress, truncate);
}

/**
 * Works like open_write_file(), but the file is opened in append mode.  Like
 * open_write_file, the returned pointer should eventually be passed to
 * close_write_file().
 */
ostream *VirtualFileSimple::
open_append_file() {
  return _mount->open_append_file(_local_filename);
}

/**
 * Closes a file opened by a previous call to open_write_file().  This really
 * just deletes the ostream pointer, but it is recommended to use this
 * interface instead of deleting it explicitly, to help work around compiler
 * issues.
 */
void VirtualFileSimple::
close_write_file(ostream *stream) {
  _mount->close_write_file(stream);
}

/**
 * Opens the file for writing.  Returns a newly allocated iostream on success
 * (which you should eventually delete when you are done writing). Returns
 * NULL on failure.
 */
iostream *VirtualFileSimple::
open_read_write_file(bool truncate) {
  return _mount->open_read_write_file(_local_filename, truncate);
}

/**
 * Works like open_read_write_file(), but the file is opened in append mode.
 * Like open_read_write_file, the returned pointer should eventually be passed
 * to close_read_write_file().
 */
iostream *VirtualFileSimple::
open_read_append_file() {
  return _mount->open_read_append_file(_local_filename);
}

/**
 * Closes a file opened by a previous call to open_read_write_file().  This
 * really just deletes the iostream pointer, but it is recommended to use this
 * interface instead of deleting it explicitly, to help work around compiler
 * issues.
 */
void VirtualFileSimple::
close_read_write_file(iostream *stream) {
  _mount->close_read_write_file(stream);
}

/**
 * Returns the current size on disk (or wherever it is) of the already-open
 * file.  Pass in the stream that was returned by open_read_file(); some
 * implementations may require this stream to determine the size.
 */
streamsize VirtualFileSimple::
get_file_size(istream *stream) const {
  return _mount->get_file_size(_local_filename, stream);
}

/**
 * Returns the current size on disk (or wherever it is) of the file before it
 * has been opened.
 */
streamsize VirtualFileSimple::
get_file_size() const {
  return _mount->get_file_size(_local_filename);
}

/**
 * Returns a time_t value that represents the time the file was last modified,
 * to within whatever precision the operating system records this information
 * (on a Windows95 system, for instance, this may only be accurate to within 2
 * seconds).
 *
 * If the timestamp cannot be determined, either because it is not supported
 * by the operating system or because there is some error (such as file not
 * found), returns 0.
 */
time_t VirtualFileSimple::
get_timestamp() const {
  return _mount->get_timestamp(_local_filename);
}

/**
 * Populates the SubfileInfo structure with the data representing where the
 * file actually resides on disk, if this is knowable.  Returns true if the
 * file might reside on disk, and the info is populated, or false if it does
 * not (or it is not known where the file resides), in which case the info is
 * meaningless.
 */
bool VirtualFileSimple::
get_system_info(SubfileInfo &info) {
  return _mount->get_system_info(_local_filename, info);
}

/**
 * See Filename::atomic_compare_and_exchange_contents().
 */
bool VirtualFileSimple::
atomic_compare_and_exchange_contents(string &orig_contents,
                                     const string &old_contents,
                                     const string &new_contents) {
  return _mount->atomic_compare_and_exchange_contents(_local_filename, orig_contents, old_contents, new_contents);
}

/**
 * See Filename::atomic_read_contents().
 */
bool VirtualFileSimple::
atomic_read_contents(string &contents) const {
  return _mount->atomic_read_contents(_local_filename, contents);
}

/**
 * Fills up the indicated pvector with the contents of the file, if it is a
 * regular file.  Returns true on success, false otherwise.
 */
bool VirtualFileSimple::
read_file(pvector<unsigned char> &result, bool auto_unwrap) const {

  // Will we be automatically unwrapping a .pz file?
  bool do_uncompress = (_implicit_pz_file ||
    (auto_unwrap && (_local_filename.get_extension() == "pz" ||
                     _local_filename.get_extension() == "gz")));

  Filename local_filename(_local_filename);
  if (do_uncompress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->read_file(local_filename, do_uncompress, result);
}

/**
 * Writes the indicated data to the file, if it is writable.  Returns true on
 * success, false otherwise.
 */
bool VirtualFileSimple::
write_file(const unsigned char *data, size_t data_size, bool auto_wrap) {
  // Will we be automatically wrapping a .pz file?
  bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz"));

  Filename local_filename(_local_filename);
  if (do_compress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->write_file(local_filename, do_compress, data, data_size);
}

/**
 * Fills file_list up with the list of files that are within this directory,
 * excluding those whose basenames are listed in mount_points.  Returns true
 * if successful, false if the file is not a directory or the directory cannot
 * be read.
 */
bool VirtualFileSimple::
scan_local_directory(VirtualFileList *file_list,
                     const ov_set<string> &mount_points) const {
  vector_string names;
  if (!_mount->scan_directory(names, _local_filename)) {
    return false;
  }

  // Now the scan above gave us a list of basenames.  Turn these back into
  // VirtualFile pointers.

  // Each of the files returned by the mount will be just a simple file within
  // the same mount tree, unless it is shadowed by a mount point listed in
  // mount_points.

  vector_string::const_iterator ni;
  for (ni = names.begin(); ni != names.end(); ++ni) {
    const string &basename = (*ni);
    if (mount_points.find(basename) == mount_points.end()) {
      Filename filename(_local_filename, basename);
      VirtualFileSimple *file = new VirtualFileSimple(_mount, filename, false, 0);
      file_list->add_file(file);
    }
  }

  return true;
}
<commit_msg>vfs: don't crash if copy_file can't open output file (LP 1687283)<commit_after>/**
 * PANDA 3D SOFTWARE
 * Copyright (c) Carnegie Mellon University.  All rights reserved.
 *
 * All use of this software is subject to the terms of the revised BSD
 * license.  You should have received a copy of this license along
 * with this source code in a file named "LICENSE."
 *
 * @file virtualFileSimple.cxx
 * @author drose
 * @date 2002-08-03
 */

#include "virtualFileSimple.h"
#include "virtualFileMount.h"
#include "virtualFileList.h"
#include "dcast.h"

TypeHandle VirtualFileSimple::_type_handle;

/**
 * Returns the VirtualFileSystem this file is associated with.
 */
VirtualFileSystem *VirtualFileSimple::
get_file_system() const {
  return _mount->get_file_system();
}

/**
 * Returns the full pathname to this file within the virtual file system.
 */
Filename VirtualFileSimple::
get_filename() const {
  string mount_point = _mount->get_mount_point();
  if (_local_filename.empty()) {
    if (mount_point.empty()) {
      return "/";
    } else {
      return string("/") + mount_point;
    }

  } else {
    if (mount_point.empty()) {
      return string("/") + _local_filename.get_fullpath();
    } else {
      return string("/") + mount_point + string("/") + _local_filename.get_fullpath();
    }
  }
}

/**
 * Returns true if this file exists, false otherwise.
 */
bool VirtualFileSimple::
has_file() const {
  return _mount->has_file(_local_filename);
}

/**
 * Returns true if this file represents a directory (and scan_directory() may
 * be called), false otherwise.
 */
bool VirtualFileSimple::
is_directory() const {
  return _mount->is_directory(_local_filename);
}

/**
 * Returns true if this file represents a regular file (and read_file() may be
 * called), false otherwise.
 */
bool VirtualFileSimple::
is_regular_file() const {
  return _mount->is_regular_file(_local_filename);
}

/**
 * Returns true if this file represents a writable regular file (and
 * write_file() may be called), false otherwise.
 */
bool VirtualFileSimple::
is_writable() const {
  return _mount->is_writable(_local_filename);
}

/**
 * Attempts to delete this file or directory.  This can remove a single file
 * or an empty directory.  It will not remove a nonempty directory.  Returns
 * true on success, false on failure.
 */
bool VirtualFileSimple::
delete_file() {
  return _mount->delete_file(_local_filename);
}

/**
 * Attempts to move or rename this file or directory.  If the original file is
 * an ordinary file, it will quietly replace any already-existing file in the
 * new filename (but not a directory).  If the original file is a directory,
 * the new filename must not already exist.
 *
 * If the file is a directory, the new filename must be within the same mount
 * point.  If the file is an ordinary file, the new filename may be anywhere;
 * but if it is not within the same mount point then the rename operation is
 * automatically performed as a two-step copy-and-delete operation.
 */
bool VirtualFileSimple::
rename_file(VirtualFile *new_file) {
  if (new_file->is_of_type(VirtualFileSimple::get_class_type())) {
    VirtualFileSimple *new_file_simple = DCAST(VirtualFileSimple, new_file);
    if (new_file_simple->_mount == _mount) {
      // Same mount pount.
      if (_mount->rename_file(_local_filename, new_file_simple->_local_filename)) {
        return true;
      }
    }
  }

  // Different mount point, or the mount doesn't support renaming.  Do it by
  // hand.
  if (is_regular_file() && !new_file->is_directory()) {
    // copy-and-delete.
    new_file->delete_file();
    if (copy_file(new_file)) {
      delete_file();
      return true;
    }
  }

  return false;
}

/**
 * Attempts to copy the contents of this file to the indicated file.  Returns
 * true on success, false on failure.
 */
bool VirtualFileSimple::
copy_file(VirtualFile *new_file) {
  if (new_file->is_of_type(VirtualFileSimple::get_class_type())) {
    VirtualFileSimple *new_file_simple = DCAST(VirtualFileSimple, new_file);
    if (new_file_simple->_mount == _mount) {
      // Same mount pount.
      if (_mount->copy_file(_local_filename, new_file_simple->_local_filename)) {
        return true;
      }
    }
  }

  // Different mount point, or the mount doesn't support copying.  Do it by
  // hand.
  ostream *out = new_file->open_write_file(false, true);
  if (out == nullptr) {
    return false;
  }

  istream *in = open_read_file(false);
  if (in == nullptr) {
    new_file->close_write_file(out);
    new_file->delete_file();
    return false;
  }

  static const size_t buffer_size = 4096;
  char buffer[buffer_size];

  in->read(buffer, buffer_size);
  size_t count = in->gcount();
  while (count != 0) {
    out->write(buffer, count);
    if (out->fail()) {
      new_file->close_write_file(out);
      close_read_file(in);
      new_file->delete_file();
      return false;
    }
    in->read(buffer, buffer_size);
    count = in->gcount();
  }

  if (!in->eof()) {
    new_file->close_write_file(out);
    close_read_file(in);
    new_file->delete_file();
    return false;
  }

  new_file->close_write_file(out);
  close_read_file(in);
  return true;
}

/**
 * Opens the file for reading.  Returns a newly allocated istream on success
 * (which you should eventually delete when you are done reading). Returns
 * NULL on failure.
 *
 * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
 * decompressed and the decompressed contents are returned.  This is different
 * than vfs-implicit-pz, which will automatically decompress a file if the
 * extension .pz is *not* given.
 */
istream *VirtualFileSimple::
open_read_file(bool auto_unwrap) const {

  // Will we be automatically unwrapping a .pz file?
  bool do_uncompress = (_implicit_pz_file ||
    (auto_unwrap && (_local_filename.get_extension() == "pz" ||
                     _local_filename.get_extension() == "gz")));

  Filename local_filename(_local_filename);
  if (do_uncompress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->open_read_file(local_filename, do_uncompress);
}

/**
 * Closes a file opened by a previous call to open_read_file().  This really
 * just deletes the istream pointer, but it is recommended to use this
 * interface instead of deleting it explicitly, to help work around compiler
 * issues.
 */
void VirtualFileSimple::
close_read_file(istream *stream) const {
  _mount->close_read_file(stream);
}

/**
 * Opens the file for writing.  Returns a newly allocated ostream on success
 * (which you should eventually delete when you are done writing). Returns
 * NULL on failure.
 *
 * If auto_wrap is true, an explicitly-named .pz file is automatically
 * compressed while writing.  If truncate is true, the file is truncated to
 * zero length before writing.
 */
ostream *VirtualFileSimple::
open_write_file(bool auto_wrap, bool truncate) {
  // Will we be automatically wrapping a .pz file?
  bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz"));

  Filename local_filename(_local_filename);
  if (do_compress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->open_write_file(local_filename, do_compress, truncate);
}

/**
 * Works like open_write_file(), but the file is opened in append mode.  Like
 * open_write_file, the returned pointer should eventually be passed to
 * close_write_file().
 */
ostream *VirtualFileSimple::
open_append_file() {
  return _mount->open_append_file(_local_filename);
}

/**
 * Closes a file opened by a previous call to open_write_file().  This really
 * just deletes the ostream pointer, but it is recommended to use this
 * interface instead of deleting it explicitly, to help work around compiler
 * issues.
 */
void VirtualFileSimple::
close_write_file(ostream *stream) {
  _mount->close_write_file(stream);
}

/**
 * Opens the file for writing.  Returns a newly allocated iostream on success
 * (which you should eventually delete when you are done writing). Returns
 * NULL on failure.
 */
iostream *VirtualFileSimple::
open_read_write_file(bool truncate) {
  return _mount->open_read_write_file(_local_filename, truncate);
}

/**
 * Works like open_read_write_file(), but the file is opened in append mode.
 * Like open_read_write_file, the returned pointer should eventually be passed
 * to close_read_write_file().
 */
iostream *VirtualFileSimple::
open_read_append_file() {
  return _mount->open_read_append_file(_local_filename);
}

/**
 * Closes a file opened by a previous call to open_read_write_file().  This
 * really just deletes the iostream pointer, but it is recommended to use this
 * interface instead of deleting it explicitly, to help work around compiler
 * issues.
 */
void VirtualFileSimple::
close_read_write_file(iostream *stream) {
  _mount->close_read_write_file(stream);
}

/**
 * Returns the current size on disk (or wherever it is) of the already-open
 * file.  Pass in the stream that was returned by open_read_file(); some
 * implementations may require this stream to determine the size.
 */
streamsize VirtualFileSimple::
get_file_size(istream *stream) const {
  return _mount->get_file_size(_local_filename, stream);
}

/**
 * Returns the current size on disk (or wherever it is) of the file before it
 * has been opened.
 */
streamsize VirtualFileSimple::
get_file_size() const {
  return _mount->get_file_size(_local_filename);
}

/**
 * Returns a time_t value that represents the time the file was last modified,
 * to within whatever precision the operating system records this information
 * (on a Windows95 system, for instance, this may only be accurate to within 2
 * seconds).
 *
 * If the timestamp cannot be determined, either because it is not supported
 * by the operating system or because there is some error (such as file not
 * found), returns 0.
 */
time_t VirtualFileSimple::
get_timestamp() const {
  return _mount->get_timestamp(_local_filename);
}

/**
 * Populates the SubfileInfo structure with the data representing where the
 * file actually resides on disk, if this is knowable.  Returns true if the
 * file might reside on disk, and the info is populated, or false if it does
 * not (or it is not known where the file resides), in which case the info is
 * meaningless.
 */
bool VirtualFileSimple::
get_system_info(SubfileInfo &info) {
  return _mount->get_system_info(_local_filename, info);
}

/**
 * See Filename::atomic_compare_and_exchange_contents().
 */
bool VirtualFileSimple::
atomic_compare_and_exchange_contents(string &orig_contents,
                                     const string &old_contents,
                                     const string &new_contents) {
  return _mount->atomic_compare_and_exchange_contents(_local_filename, orig_contents, old_contents, new_contents);
}

/**
 * See Filename::atomic_read_contents().
 */
bool VirtualFileSimple::
atomic_read_contents(string &contents) const {
  return _mount->atomic_read_contents(_local_filename, contents);
}

/**
 * Fills up the indicated pvector with the contents of the file, if it is a
 * regular file.  Returns true on success, false otherwise.
 */
bool VirtualFileSimple::
read_file(pvector<unsigned char> &result, bool auto_unwrap) const {

  // Will we be automatically unwrapping a .pz file?
  bool do_uncompress = (_implicit_pz_file ||
    (auto_unwrap && (_local_filename.get_extension() == "pz" ||
                     _local_filename.get_extension() == "gz")));

  Filename local_filename(_local_filename);
  if (do_uncompress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->read_file(local_filename, do_uncompress, result);
}

/**
 * Writes the indicated data to the file, if it is writable.  Returns true on
 * success, false otherwise.
 */
bool VirtualFileSimple::
write_file(const unsigned char *data, size_t data_size, bool auto_wrap) {
  // Will we be automatically wrapping a .pz file?
  bool do_compress = (_implicit_pz_file || (auto_wrap && _local_filename.get_extension() == "pz"));

  Filename local_filename(_local_filename);
  if (do_compress) {
    // .pz files are always binary, of course.
    local_filename.set_binary();
  }

  return _mount->write_file(local_filename, do_compress, data, data_size);
}

/**
 * Fills file_list up with the list of files that are within this directory,
 * excluding those whose basenames are listed in mount_points.  Returns true
 * if successful, false if the file is not a directory or the directory cannot
 * be read.
 */
bool VirtualFileSimple::
scan_local_directory(VirtualFileList *file_list,
                     const ov_set<string> &mount_points) const {
  vector_string names;
  if (!_mount->scan_directory(names, _local_filename)) {
    return false;
  }

  // Now the scan above gave us a list of basenames.  Turn these back into
  // VirtualFile pointers.

  // Each of the files returned by the mount will be just a simple file within
  // the same mount tree, unless it is shadowed by a mount point listed in
  // mount_points.

  vector_string::const_iterator ni;
  for (ni = names.begin(); ni != names.end(); ++ni) {
    const string &basename = (*ni);
    if (mount_points.find(basename) == mount_points.end()) {
      Filename filename(_local_filename, basename);
      VirtualFileSimple *file = new VirtualFileSimple(_mount, filename, false, 0);
      file_list->add_file(file);
    }
  }

  return true;
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>
    Copyright (C) 2014  David Edmundson <davidedmundson@kde.org>

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

    This library 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
    Lesser General Public License for more details.

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

#include "im-persons-data-source.h"

#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/Presence>
#include <TelepathyQt/Utils>

#include "KTp/contact-factory.h"
#include "KTp/global-contact-manager.h"
#include "KTp/types.h"
#include "debug.h"

#include <KPeopleBackend/AllContactsMonitor>

#include <KPluginFactory>
#include <KPluginLoader>
#include <KConfig>
#include <KConfigGroup>

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QPixmap>

using namespace KPeople;

class KTpAllContacts : public AllContactsMonitor
{
    Q_OBJECT
public:
    KTpAllContacts();
    ~KTpAllContacts();
    virtual QMap<QString, AbstractContact::Ptr> contacts() Q_DECL_OVERRIDE;

private Q_SLOTS:
    void loadCache(const QString &accountId = QString());
    void onAccountManagerReady(Tp::PendingOperation *op);
    void onContactChanged();
    void onContactInvalidated();
    void onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved);
    void onAccountCurrentPresenceChanged(const Tp::Presence &currentPresence);

private:
    QString createUri(const KTp::ContactPtr &contact) const;

    //presence names indexed by ConnectionPresenceType
    QHash<QString, KTp::ContactPtr> m_contacts;
    QMap<QString, AbstractContact::Ptr> m_contactVCards;
};

class TelepathyContact : public KPeople::AbstractContact
{
public:
    virtual QVariant customProperty(const QString &key) const Q_DECL_OVERRIDE
    {
        // Check if the contact is valid first
        if (m_contact && m_contact->manager() && m_contact->manager()->connection() && m_account) {
            if (key == AbstractContact::NameProperty)
                return m_contact->alias();
            else if(key == AbstractContact::GroupsProperty)
                return m_contact->groups();
            else if(key == S_KPEOPLE_PROPERTY_CONTACT_ID)
                return m_contact->id();
            else if(key == S_KPEOPLE_PROPERTY_ACCOUNT_PATH)
                return m_account->objectPath();
            else if(key == S_KPEOPLE_PROPERTY_PRESENCE)
                return s_presenceStrings.value(m_contact->presence().type());
            else if (key == AbstractContact::PictureProperty)
                return m_contact->avatarPixmap();
        }
        return m_properties[key];
    }

    void insertProperty(const QString &key, const QVariant &value)
    {
        m_properties[key] = value;
    }

    void setContact(const KTp::ContactPtr &contact)
    {
        m_contact = contact;
    }

    void setAccount(const Tp::AccountPtr &account)
    {
        m_account = account;
    }

private:
    KTp::ContactPtr m_contact;
    Tp::AccountPtr m_account;
    QVariantMap m_properties;
};

KTpAllContacts::KTpAllContacts()
{
    Tp::registerTypes();

    loadCache();
}

KTpAllContacts::~KTpAllContacts()
{
}

void KTpAllContacts::loadCache(const QString &accountId)
{
    QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("ktpCache"));
    QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/ktp");
    QDir().mkpath(path);
    db.setDatabaseName(path+QStringLiteral("/cache.db"));
    if (!db.open()) {
        qWarning() << "couldn't open database" << db.databaseName();
    }

    QSqlQuery query(db);
    query.exec(QLatin1String("SELECT DISTINCT groupName FROM groups ORDER BY groupId;"));

    QStringList groupsList;
    while (query.next()) {
        groupsList.append(query.value(0).toString());
    }

    QString queryPrep = QStringLiteral("SELECT accountId, contactId, alias, avatarFileName, isBlocked");
    if (!groupsList.isEmpty()) {
        queryPrep.append(QStringLiteral(", groupsIds"));
    }
    queryPrep.append(QStringLiteral(" FROM contacts"));

    if (!accountId.isEmpty()) {
        queryPrep.append(QStringLiteral(" WHERE accountId = ?;"));
        query.prepare(queryPrep);
        query.bindValue(0, accountId);
    } else {
        queryPrep.append(QStringLiteral(";"));
        query.prepare(queryPrep);
    }

    query.exec();

    KConfig config(QLatin1String("ktelepathy-avatarsrc"));
    QString cacheDir = QString::fromLatin1(qgetenv("XDG_CACHE_HOME"));
    if (cacheDir.isEmpty()) {
        cacheDir = QStringLiteral("%1/.cache").arg(QLatin1String(qgetenv("HOME")));
    }

    while (query.next()) {
        QExplicitlySharedDataPointer<TelepathyContact> addressee(new TelepathyContact);

        const QString accountId =  query.value(0).toString();
        const QString contactId =  query.value(1).toString();
        QString avatarFileName = query.value(3).toString();
        addressee->insertProperty(AbstractContact::NameProperty, query.value(2).toString());

        if (avatarFileName.isEmpty()) {
            KConfigGroup avatarTokenGroup = config.group(contactId);
            QString avatarToken = avatarTokenGroup.readEntry(QLatin1String("avatarToken"));
            //only bother loading the pixmap if the token is not empty
            if (!avatarToken.isEmpty()) {
                // the accountId is in form of "connection manager name / protocol / username...",
                // so let's look for the first / after the very first / (ie. second /)
                QString path = QStringLiteral("%1/telepathy/avatars/%2").
                    arg(cacheDir).arg(accountId.left(accountId.indexOf(QLatin1Char('/'), accountId.indexOf(QLatin1Char('/')) + 1)));

                avatarFileName = QStringLiteral("%1/%2").arg(path).arg(Tp::escapeAsIdentifier(avatarToken));
            }
        }

        addressee->insertProperty(AbstractContact::PictureProperty, QUrl::fromLocalFile(avatarFileName));
        addressee->insertProperty(S_KPEOPLE_PROPERTY_IS_BLOCKED, query.value(4).toBool());

        if (!groupsList.isEmpty()) {
            QVariantList contactGroups;

            Q_FOREACH (const QString &groupIdStr, query.value(5).toString().split(QLatin1Char('/'))) {
                bool convSuccess;
                int groupId = groupIdStr.toInt(&convSuccess);
                if ((!convSuccess) || (groupId >= groupsList.count()))
                    continue;

                contactGroups.append(groupsList.at(groupId));
            }

            addressee->insertProperty(AbstractContact::GroupsProperty, contactGroups);
        }

        addressee->insertProperty(S_KPEOPLE_PROPERTY_CONTACT_ID, contactId);
        addressee->insertProperty(S_KPEOPLE_PROPERTY_ACCOUNT_PATH, TP_QT_ACCOUNT_OBJECT_PATH_BASE + QLatin1Char('/') + accountId);
        addressee->insertProperty(S_KPEOPLE_PROPERTY_PRESENCE, s_presenceStrings[Tp::ConnectionPresenceTypeOffline]);

        const QString uri = QLatin1String("ktp://") + accountId + QLatin1Char('?') + contactId;

        QMap<QString, AbstractContact::Ptr>::const_iterator it = m_contactVCards.constFind(uri);
        if (it != m_contactVCards.constEnd()) {
            Q_EMIT contactChanged(uri, addressee);
        } else {
            Q_EMIT contactAdded(uri, addressee);
        }

        m_contactVCards[uri] = addressee;
    }

    //now start fetching the up-to-date information
    connect(KTp::accountManager()->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
        this, SLOT(onAccountManagerReady(Tp::PendingOperation*)), Qt::UniqueConnection);

    emitInitialFetchComplete(true);
}

QString KTpAllContacts::createUri(const KTp::ContactPtr &contact) const
{
    // so real ID will look like
    // ktp://gabble/jabber/blah/asdfjwer?foo@bar.com
    // ? is used as it is not a valid character in the dbus path that makes up the account UID
    return QLatin1String("ktp://") + contact->accountUniqueIdentifier() + QLatin1Char('?') + contact->id();
}

void KTpAllContacts::onAccountManagerReady(Tp::PendingOperation *op)
{
    if (op->isError()) {
        qCWarning(KTP_KPEOPLE) << "Failed to initialize AccountManager:" << op->errorName();
        qCWarning(KTP_KPEOPLE) << op->errorMessage();

        return;
    }

    qCDebug(KTP_KPEOPLE) << "Account manager ready";

    Q_FOREACH (const Tp::AccountPtr &account, KTp::accountManager()->allAccounts()) {
        connect(account.data(), &Tp::Account::currentPresenceChanged, this, &KTpAllContacts::onAccountCurrentPresenceChanged);
    }

    connect(KTp::contactManager(), SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)),
            this, SLOT(onAllKnownContactsChanged(Tp::Contacts,Tp::Contacts)));

    onAllKnownContactsChanged(KTp::contactManager()->allKnownContacts(), Tp::Contacts());
}

void KTpAllContacts::onAccountCurrentPresenceChanged(const Tp::Presence &currentPresence)
{
    Tp::Account *account = qobject_cast<Tp::Account*>(sender());
    if (!account) {
        return;
    }

    if (currentPresence.type() == Tp::ConnectionPresenceTypeOffline) {
        loadCache(account->uniqueIdentifier());
    }
}

void KTpAllContacts::onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved)
{
    if (!m_contacts.isEmpty()) {
        Q_FOREACH (const Tp::ContactPtr &c, contactsRemoved) {
            const KTp::ContactPtr &contact = KTp::ContactPtr::qObjectCast(c);
            const QString uri = createUri(contact);
            m_contacts.remove(uri);
            m_contactVCards.remove(uri);
            Q_EMIT contactRemoved(uri);
        }
    }

    Q_FOREACH (const Tp::ContactPtr &contact, contactsAdded) {
        KTp::ContactPtr ktpContact = KTp::ContactPtr::qObjectCast(contact);
        const QString uri = createUri(ktpContact);

        AbstractContact::Ptr vcard = m_contactVCards.value(uri);
        bool added = false;
        if (!vcard) {
            vcard = AbstractContact::Ptr(new TelepathyContact);
            m_contactVCards[uri] = vcard;
            added = true;
        }
        static_cast<TelepathyContact*>(vcard.data())->setContact(ktpContact);
        static_cast<TelepathyContact*>(vcard.data())->setAccount(KTp::contactManager()->accountForContact(ktpContact));

        m_contacts.insert(uri, ktpContact);

        if (added) {
            Q_EMIT contactAdded(uri, vcard);
        } else {
            Q_EMIT contactChanged(uri, vcard);
        }

        connect(ktpContact.data(), SIGNAL(presenceChanged(Tp::Presence)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(invalidated()),
                this, SLOT(onContactInvalidated()));

        connect(ktpContact.data(), SIGNAL(avatarDataChanged(Tp::AvatarData)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(addedToGroup(QString)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(removedFromGroup(QString)),
                this, SLOT(onContactChanged()));
    }
}

void KTpAllContacts::onContactChanged()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    const QString uri = createUri(contact);
    Q_EMIT contactChanged(uri, m_contactVCards.value(uri));
}

void KTpAllContacts::onContactInvalidated()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    const QString uri = createUri(contact);

    m_contacts.remove(uri);

    //set to offline and emit changed
    AbstractContact::Ptr vcard = m_contactVCards[uri];
    TelepathyContact *tpContact = static_cast<TelepathyContact*>(vcard.data());
    tpContact->insertProperty(S_KPEOPLE_PROPERTY_PRESENCE, QStringLiteral("offline"));
    Q_EMIT contactChanged(uri, vcard);
}

QMap<QString, AbstractContact::Ptr> KTpAllContacts::contacts()
{
    return m_contactVCards;
}

IMPersonsDataSource::IMPersonsDataSource(QObject *parent, const QVariantList &args)
    : BasePersonsDataSource(parent)
{
    Q_UNUSED(args);
}

IMPersonsDataSource::~IMPersonsDataSource()
{
}

QString IMPersonsDataSource::sourcePluginId() const
{
    return QStringLiteral("ktp");
}

AllContactsMonitor* IMPersonsDataSource::createAllContactsMonitor()
{
    return new KTpAllContacts();
}

K_PLUGIN_FACTORY( IMPersonsDataSourceFactory, registerPlugin<IMPersonsDataSource>(); )
K_EXPORT_PLUGIN( IMPersonsDataSourceFactory("im_persons_data_source_plugin") )

#include "im-persons-data-source.moc"
<commit_msg>Don't create null fields if uri is not available<commit_after>/*
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>
    Copyright (C) 2014  David Edmundson <davidedmundson@kde.org>

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

    This library 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
    Lesser General Public License for more details.

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

#include "im-persons-data-source.h"

#include <TelepathyQt/AccountManager>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/Presence>
#include <TelepathyQt/Utils>

#include "KTp/contact-factory.h"
#include "KTp/global-contact-manager.h"
#include "KTp/types.h"
#include "debug.h"

#include <KPeopleBackend/AllContactsMonitor>

#include <KPluginFactory>
#include <KPluginLoader>
#include <KConfig>
#include <KConfigGroup>

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QPixmap>

using namespace KPeople;

class KTpAllContacts : public AllContactsMonitor
{
    Q_OBJECT
public:
    KTpAllContacts();
    ~KTpAllContacts();
    virtual QMap<QString, AbstractContact::Ptr> contacts() Q_DECL_OVERRIDE;

private Q_SLOTS:
    void loadCache(const QString &accountId = QString());
    void onAccountManagerReady(Tp::PendingOperation *op);
    void onContactChanged();
    void onContactInvalidated();
    void onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved);
    void onAccountCurrentPresenceChanged(const Tp::Presence &currentPresence);

private:
    QString createUri(const KTp::ContactPtr &contact) const;

    //presence names indexed by ConnectionPresenceType
    QHash<QString, KTp::ContactPtr> m_contacts;
    QMap<QString, AbstractContact::Ptr> m_contactVCards;
};

class TelepathyContact : public KPeople::AbstractContact
{
public:
    virtual QVariant customProperty(const QString &key) const Q_DECL_OVERRIDE
    {
        // Check if the contact is valid first
        if (m_contact && m_contact->manager() && m_contact->manager()->connection() && m_account) {
            if (key == AbstractContact::NameProperty)
                return m_contact->alias();
            else if(key == AbstractContact::GroupsProperty)
                return m_contact->groups();
            else if(key == S_KPEOPLE_PROPERTY_CONTACT_ID)
                return m_contact->id();
            else if(key == S_KPEOPLE_PROPERTY_ACCOUNT_PATH)
                return m_account->objectPath();
            else if(key == S_KPEOPLE_PROPERTY_PRESENCE)
                return s_presenceStrings.value(m_contact->presence().type());
            else if (key == AbstractContact::PictureProperty)
                return m_contact->avatarPixmap();
        }
        return m_properties[key];
    }

    void insertProperty(const QString &key, const QVariant &value)
    {
        m_properties[key] = value;
    }

    void setContact(const KTp::ContactPtr &contact)
    {
        m_contact = contact;
    }

    void setAccount(const Tp::AccountPtr &account)
    {
        m_account = account;
    }

private:
    KTp::ContactPtr m_contact;
    Tp::AccountPtr m_account;
    QVariantMap m_properties;
};

KTpAllContacts::KTpAllContacts()
{
    Tp::registerTypes();

    loadCache();
}

KTpAllContacts::~KTpAllContacts()
{
}

void KTpAllContacts::loadCache(const QString &accountId)
{
    QSqlDatabase db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("ktpCache"));
    QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/ktp");
    QDir().mkpath(path);
    db.setDatabaseName(path+QStringLiteral("/cache.db"));
    if (!db.open()) {
        qWarning() << "couldn't open database" << db.databaseName();
    }

    QSqlQuery query(db);
    query.exec(QLatin1String("SELECT DISTINCT groupName FROM groups ORDER BY groupId;"));

    QStringList groupsList;
    while (query.next()) {
        groupsList.append(query.value(0).toString());
    }

    QString queryPrep = QStringLiteral("SELECT accountId, contactId, alias, avatarFileName, isBlocked");
    if (!groupsList.isEmpty()) {
        queryPrep.append(QStringLiteral(", groupsIds"));
    }
    queryPrep.append(QStringLiteral(" FROM contacts"));

    if (!accountId.isEmpty()) {
        queryPrep.append(QStringLiteral(" WHERE accountId = ?;"));
        query.prepare(queryPrep);
        query.bindValue(0, accountId);
    } else {
        queryPrep.append(QStringLiteral(";"));
        query.prepare(queryPrep);
    }

    query.exec();

    KConfig config(QLatin1String("ktelepathy-avatarsrc"));
    QString cacheDir = QString::fromLatin1(qgetenv("XDG_CACHE_HOME"));
    if (cacheDir.isEmpty()) {
        cacheDir = QStringLiteral("%1/.cache").arg(QLatin1String(qgetenv("HOME")));
    }

    while (query.next()) {
        QExplicitlySharedDataPointer<TelepathyContact> addressee(new TelepathyContact);

        const QString accountId =  query.value(0).toString();
        const QString contactId =  query.value(1).toString();
        QString avatarFileName = query.value(3).toString();
        addressee->insertProperty(AbstractContact::NameProperty, query.value(2).toString());

        if (avatarFileName.isEmpty()) {
            KConfigGroup avatarTokenGroup = config.group(contactId);
            QString avatarToken = avatarTokenGroup.readEntry(QLatin1String("avatarToken"));
            //only bother loading the pixmap if the token is not empty
            if (!avatarToken.isEmpty()) {
                // the accountId is in form of "connection manager name / protocol / username...",
                // so let's look for the first / after the very first / (ie. second /)
                QString path = QStringLiteral("%1/telepathy/avatars/%2").
                    arg(cacheDir).arg(accountId.left(accountId.indexOf(QLatin1Char('/'), accountId.indexOf(QLatin1Char('/')) + 1)));

                avatarFileName = QStringLiteral("%1/%2").arg(path).arg(Tp::escapeAsIdentifier(avatarToken));
            }
        }

        addressee->insertProperty(AbstractContact::PictureProperty, QUrl::fromLocalFile(avatarFileName));
        addressee->insertProperty(S_KPEOPLE_PROPERTY_IS_BLOCKED, query.value(4).toBool());

        if (!groupsList.isEmpty()) {
            QVariantList contactGroups;

            Q_FOREACH (const QString &groupIdStr, query.value(5).toString().split(QLatin1Char('/'))) {
                bool convSuccess;
                int groupId = groupIdStr.toInt(&convSuccess);
                if ((!convSuccess) || (groupId >= groupsList.count()))
                    continue;

                contactGroups.append(groupsList.at(groupId));
            }

            addressee->insertProperty(AbstractContact::GroupsProperty, contactGroups);
        }

        addressee->insertProperty(S_KPEOPLE_PROPERTY_CONTACT_ID, contactId);
        addressee->insertProperty(S_KPEOPLE_PROPERTY_ACCOUNT_PATH, TP_QT_ACCOUNT_OBJECT_PATH_BASE + QLatin1Char('/') + accountId);
        addressee->insertProperty(S_KPEOPLE_PROPERTY_PRESENCE, s_presenceStrings[Tp::ConnectionPresenceTypeOffline]);

        const QString uri = QLatin1String("ktp://") + accountId + QLatin1Char('?') + contactId;

        QMap<QString, AbstractContact::Ptr>::const_iterator it = m_contactVCards.constFind(uri);
        if (it != m_contactVCards.constEnd()) {
            Q_EMIT contactChanged(uri, addressee);
        } else {
            Q_EMIT contactAdded(uri, addressee);
        }

        m_contactVCards[uri] = addressee;
    }

    //now start fetching the up-to-date information
    connect(KTp::accountManager()->becomeReady(), SIGNAL(finished(Tp::PendingOperation*)),
        this, SLOT(onAccountManagerReady(Tp::PendingOperation*)), Qt::UniqueConnection);

    emitInitialFetchComplete(true);
}

QString KTpAllContacts::createUri(const KTp::ContactPtr &contact) const
{
    // so real ID will look like
    // ktp://gabble/jabber/blah/asdfjwer?foo@bar.com
    // ? is used as it is not a valid character in the dbus path that makes up the account UID
    return QLatin1String("ktp://") + contact->accountUniqueIdentifier() + QLatin1Char('?') + contact->id();
}

void KTpAllContacts::onAccountManagerReady(Tp::PendingOperation *op)
{
    if (op->isError()) {
        qCWarning(KTP_KPEOPLE) << "Failed to initialize AccountManager:" << op->errorName();
        qCWarning(KTP_KPEOPLE) << op->errorMessage();

        return;
    }

    qCDebug(KTP_KPEOPLE) << "Account manager ready";

    Q_FOREACH (const Tp::AccountPtr &account, KTp::accountManager()->allAccounts()) {
        connect(account.data(), &Tp::Account::currentPresenceChanged, this, &KTpAllContacts::onAccountCurrentPresenceChanged);
    }

    connect(KTp::contactManager(), SIGNAL(allKnownContactsChanged(Tp::Contacts,Tp::Contacts)),
            this, SLOT(onAllKnownContactsChanged(Tp::Contacts,Tp::Contacts)));

    onAllKnownContactsChanged(KTp::contactManager()->allKnownContacts(), Tp::Contacts());
}

void KTpAllContacts::onAccountCurrentPresenceChanged(const Tp::Presence &currentPresence)
{
    Tp::Account *account = qobject_cast<Tp::Account*>(sender());
    if (!account) {
        return;
    }

    if (currentPresence.type() == Tp::ConnectionPresenceTypeOffline) {
        loadCache(account->uniqueIdentifier());
    }
}

void KTpAllContacts::onAllKnownContactsChanged(const Tp::Contacts &contactsAdded, const Tp::Contacts &contactsRemoved)
{
    if (!m_contacts.isEmpty()) {
        Q_FOREACH (const Tp::ContactPtr &c, contactsRemoved) {
            const KTp::ContactPtr &contact = KTp::ContactPtr::qObjectCast(c);
            const QString uri = createUri(contact);
            m_contacts.remove(uri);
            m_contactVCards.remove(uri);
            Q_EMIT contactRemoved(uri);
        }
    }

    Q_FOREACH (const Tp::ContactPtr &contact, contactsAdded) {
        KTp::ContactPtr ktpContact = KTp::ContactPtr::qObjectCast(contact);
        const QString uri = createUri(ktpContact);

        AbstractContact::Ptr vcard = m_contactVCards.value(uri);
        bool added = false;
        if (!vcard) {
            vcard = AbstractContact::Ptr(new TelepathyContact);
            m_contactVCards[uri] = vcard;
            added = true;
        }
        static_cast<TelepathyContact*>(vcard.data())->setContact(ktpContact);
        static_cast<TelepathyContact*>(vcard.data())->setAccount(KTp::contactManager()->accountForContact(ktpContact));

        m_contacts.insert(uri, ktpContact);

        if (added) {
            Q_EMIT contactAdded(uri, vcard);
        } else {
            Q_EMIT contactChanged(uri, vcard);
        }

        connect(ktpContact.data(), SIGNAL(presenceChanged(Tp::Presence)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(capabilitiesChanged(Tp::ContactCapabilities)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(invalidated()),
                this, SLOT(onContactInvalidated()));

        connect(ktpContact.data(), SIGNAL(avatarDataChanged(Tp::AvatarData)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(addedToGroup(QString)),
                this, SLOT(onContactChanged()));

        connect(ktpContact.data(), SIGNAL(removedFromGroup(QString)),
                this, SLOT(onContactChanged()));
    }
}

void KTpAllContacts::onContactChanged()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    const QString uri = createUri(contact);
    Q_EMIT contactChanged(uri, m_contactVCards.value(uri));
}

void KTpAllContacts::onContactInvalidated()
{
    const KTp::ContactPtr contact(qobject_cast<KTp::Contact*>(sender()));
    const QString uri = createUri(contact);

    m_contacts.remove(uri);

    //set to offline and emit changed
    AbstractContact::Ptr vcard = m_contactVCards.value(uri);
    TelepathyContact *tpContact = static_cast<TelepathyContact*>(vcard.data());
    tpContact->insertProperty(S_KPEOPLE_PROPERTY_PRESENCE, QStringLiteral("offline"));
    Q_EMIT contactChanged(uri, vcard);
}

QMap<QString, AbstractContact::Ptr> KTpAllContacts::contacts()
{
    return m_contactVCards;
}

IMPersonsDataSource::IMPersonsDataSource(QObject *parent, const QVariantList &args)
    : BasePersonsDataSource(parent)
{
    Q_UNUSED(args);
}

IMPersonsDataSource::~IMPersonsDataSource()
{
}

QString IMPersonsDataSource::sourcePluginId() const
{
    return QStringLiteral("ktp");
}

AllContactsMonitor* IMPersonsDataSource::createAllContactsMonitor()
{
    return new KTpAllContacts();
}

K_PLUGIN_FACTORY( IMPersonsDataSourceFactory, registerPlugin<IMPersonsDataSource>(); )
K_EXPORT_PLUGIN( IMPersonsDataSourceFactory("im_persons_data_source_plugin") )

#include "im-persons-data-source.moc"
<|endoftext|>


<commit_before>#pragma once
#include "util.cpp"

//return intervals during which the satellite can photograph the object
//ignoring the photos the satellite should already take
vector<pair<ll, ll>> possible_intervals(Input& input, Satellite& satellite, Object& object) {
	vector<pair<ll, ll>> ret(1);
	ret[0] = make_pair(0, input.t-1);
	return ret;
}
<commit_msg>Added possible intervals function<commit_after>#pragma once
#include "util.cpp"
#include <cmath>

const int ROTATION = -15;
const int LOW_LAT = -324000;
const int UP_LAT = 324000;
const int LOW_LON = -648000;
const int UP_LON = 647999;
const int INTERV_LON = UP_LON - LOW_LON;
const int INVER_LAT = UP_LAT - LOW_LAT;

double checkBounds_x(double x)
{
	if (x < LOW_LON)
		return x + INTERV_LON;
	else if (x > LOW_LON)
		return x - INTERV_LON;
	return x;
}

double projectUp(ll x, ll y, double v, int x_speed)
{
	double t = 1.0 * (UP_LON - y) / abs(v);
	double pos = x + t * x_speed;
	return checkBounds_x(pos);
}

double projectDown(ll x, ll y, double v, int x_speed)
{
	double t = 1.0 * (y - LOW_LON) / abs(v);
	double pos = x + t * x_speed;
	return checkBounds_x(pos);
}

double distX(double x1, double x2)
{
	if (x1 > x2)
		swap(x1, x2);
	return min(x2 - x1, x1 - LOW_LON + UP_LON - x2);
}

//return intervals during which the satellite can photograph the object
//ignoring the photos the satellite should already take
vector<pair<ll, ll>> possible_intervals(Input& input, Satellite& satellite, Object& object)
{
	double crossTime = 1.0 * INVER_LAT / abs(satellite.v);
	double crossLen = crossTime * ROTATION;

	vector<double> up_positions;
	vector<double> down_positions;
	vector<double> up_times;
	vector<double> down_times;

	bool isUp;
	double time;
	double len;
	if (satellite.v > 0)
	{
		len = projectUp(satellite.lon, satellite.lat, satellite.v, ROTATION);
		up_positions.push_back(len);
		time = (UP_LAT - satellite.lat) / satellite.v;
		up_times.push_back(time);
		isUp = true;
	}
	else
	{
		len = projectDown(satellite.lon, satellite.lat, satellite.v, ROTATION);
		down_positions.push_back(len);
		time = (satellite.lat - LOW_LAT) / satellite.v;
		down_times.push_back(time);
		isUp = false;
	}

	while (time + crossTime < input.t)
	{
		time += crossTime;
		len = checkBounds_x(len + crossLen);
		isUp = !isUp;

		if (isUp)
		{
			up_positions.push_back(len);
			up_times.push_back(time);
		}
		else
		{
			down_positions.push_back(len);
			down_times.push_back(time);
		}
	}

	// project object
	double obj_up_pos = projectUp(object.lon, object.lat, satellite.v, -ROTATION);
	double obj_down_pos = projectDown(object.lon, object.lat, satellite.v, ROTATION);

	vector<pair<ll, ll>> intervals;
	for (int i = 0; i < up_positions.size(); i++)
	{
		if (distX(obj_up_pos, up_positions[i]) < satellite.d)
		{
			double t_star = up_times[i] + 1.0 * (UP_LAT - object.lat) / satellite.v;
			intervals.push_back(make_pair(floor(t_star), ceil(t_star)));
		}
	}

	for (int i = 0; i < down_positions.size(); i++)
	{
		if (distX(obj_down_pos, down_positions[i]) < satellite.d)
		{
			double t_star = down_times[i] + 1.0 * (object.lat - LOW_LAT) / satellite.v;
			intervals.push_back(make_pair(floor(t_star), ceil(t_star)));
		}
	}

	return intervals;
}

<|endoftext|>


<commit_before><commit_msg>nitpick: avoid triple redirection inside loop, fdo#75264 related<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: acredlin.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 16:44:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_ACREDLIN_HXX
#define SC_ACREDLIN_HXX

#ifndef VCL
#endif

#ifndef _MOREBTN_HXX //autogen
#include <vcl/morebtn.hxx>
#endif
#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif
#ifndef _GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif

#ifndef _HEADBAR_HXX //autogen
#include <svtools/headbar.hxx>
#endif

#ifndef _SVTABBX_HXX //autogen
#include <svtools/svtabbx.hxx>
#endif

#ifndef SC_RANGENAM_HXX
#include "rangenam.hxx"
#endif

#ifndef SC_ANYREFDG_HXX
#include "anyrefdg.hxx"
#endif

#ifndef _SV_LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _SVX_ACREDLIN_HXX
#include <svx/ctredlin.hxx>
#endif

#ifndef _SVX_SIMPTABL_HXX
#include <svx/simptabl.hxx>
#endif

#ifndef _SVARRAY_HXX
#define _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif

#ifndef SC_CHGTRACK_HXX
#include "chgtrack.hxx"
#endif

#ifndef SC_CHGVISET_HXX
#include "chgviset.hxx"
#endif

#ifndef _SV_TIMER_HXX //autogen
#include <vcl/timer.hxx>
#endif

class ScViewData;
class ScDocument;

#define FLT_DATE_BEFORE     0
#define FLT_DATE_SINCE      1
#define FLT_DATE_EQUAL      2
#define FLT_DATE_NOTEQUAL   3
#define FLT_DATE_BETWEEN    4
#define FLT_DATE_SAVE       5

class ScViewEntryPtr
{
private:
    String*         pAction;
    String*         pPos;
    String*         pAuthor;
    String*         pDate;
    String*         pComment;
    void*           pData;

public:

    String*         GetpAction()    {return pAction; }
    String*         GetpPos()       {return pPos;    }
    String*         GetpAuthor()    {return pAuthor; }
    String*         GetpDate()      {return pDate;   }
    String*         GetpComment()   {return pComment;}
    void*           GetpData()      {return pData;   }

    void        SetpAction (String* pString)    {pAction= pString;}
    void        SetpPos    (String* pString)    {pPos   = pString;}
    void        SetpAuthor (String* pString)    {pAuthor= pString;}
    void        SetpDate   (String* pString)    {pDate  = pString;}
    void        SetpComment(String* pString)    {pComment=pString;}
    void        SetpData   (void*   pdata)      {pData   =pdata;}
};

class ScViewEntryPtrList
{
    ScViewEntryPtrList* pNext;
    ScViewEntryPtrList* pLast;

    ScViewEntryPtr* pData;
};

class ScRedlinData : public RedlinData
{
public:

                    ScRedlinData();
                    ~ScRedlinData();
    USHORT          nTable;
    USHORT          nCol;
    USHORT          nRow;
    ULONG           nActionNo;
    ULONG           nInfo;
    BOOL            bIsRejectable;
    BOOL            bIsAcceptable;
};

typedef long LExpNum;

//@ Expand-Entrys nicht eindeutig, daher gestrichen
//DECLARE_TABLE( ScChgTrackExps, LExpNum)
//==================================================================

class ScAcceptChgDlg : public SfxModelessDialog
{
private:

    Timer                   aSelectionTimer;
    Timer                   aReOpenTimer;
    SvxAcceptChgCtr         aAcceptChgCtr;
    ScViewData*             pViewData;
    ScDocument*             pDoc;
    ScRangeName             aLocalRangeName;
    Selection               theCurSel;
    SvxTPFilter*            pTPFilter;
    SvxTPView*              pTPView;
    SvxRedlinTable*         pTheView;
    Size                    MinSize;
    ScRangeList             aRangeList;
    ScChangeViewSettings    aChangeViewSet;
    International           aInter;
    String                  aStrInsertCols;
    String                  aStrInsertRows;
    String                  aStrInsertTabs;
    String                  aStrDeleteCols;
    String                  aStrDeleteRows;
    String                  aStrDeleteTabs;
    String                  aStrMove;
    String                  aStrContent;
    String                  aStrReject;
    String                  aUnknown;
    String                  aStrAllAccepted;
    String                  aStrAllRejected;
    String                  aStrNoEntry;
    String                  aStrContentWithChild;
    String                  aStrChildContent;
    String                  aStrChildOrgContent;
    String                  aStrEmpty;
    Bitmap                  aExpBmp;
    Bitmap                  aCollBmp;
    Bitmap                  aCloseBmp;
    Bitmap                  aOpenBmp;
    Bitmap                  aEndBmp;
    Bitmap                  aErrorBmp;
    ULONG                   nAcceptCount;
    ULONG                   nRejectCount;
    BOOL                    bAcceptEnableFlag;
    BOOL                    bRejectEnableFlag;
    BOOL                    bNeedsUpdate;
    BOOL                    bIgnoreMsg;
    BOOL                    bNoSelection;
    BOOL                    bHasFilterEntry;
    BOOL                    bUseColor;
    //ScChgTrackExps            aExpandArray;

    void            Init();
    void            InitFilter();
    void            SetMyStaticData();

    DECL_LINK( FilterHandle, SvxTPFilter* );
    DECL_LINK( RefHandle, SvxTPFilter* );
    DECL_LINK( FilterModified, SvxTPFilter* );
    DECL_LINK( MinSizeHandle, SvxAcceptChgCtr*);
    DECL_LINK( RejectHandle, SvxTPView*);
    DECL_LINK( AcceptHandle, SvxTPView*);
    DECL_LINK( RejectAllHandle, SvxTPView*);
    DECL_LINK( AcceptAllHandle, SvxTPView*);
    DECL_LINK( ExpandingHandle, SvxRedlinTable*);
    DECL_LINK( SelectHandle, SvxRedlinTable*);
    DECL_LINK( RefInfoHandle, String*);

    DECL_LINK( UpdateSelectionHdl, Timer*);
    DECL_LINK( ChgTrackModHdl, ScChangeTrack*);
    DECL_LINK( CommandHdl, Control*);
    DECL_LINK( ReOpenTimerHdl, Timer*);
    DECL_LINK( ColCompareHdl, SvSortData*);

protected:

    virtual void    Resize();
    virtual BOOL    Close();

    void            RejectFiltered();
    void            AcceptFiltered();

    BOOL            IsValidAction(const ScChangeAction* pScChangeAction);

    String*         MakeTypeString(ScChangeActionType eType);

    SvLBoxEntry*    InsertChangeAction(const ScChangeAction* pScChangeAction,ScChangeActionState eState,
                                    SvLBoxEntry* pParent=NULL,BOOL bDelMaster=FALSE,
                                    BOOL bDisabled=FALSE,ULONG nPos=LIST_APPEND);

    SvLBoxEntry*    InsertFilteredAction(const ScChangeAction* pScChangeAction,ScChangeActionState eState,
                                    SvLBoxEntry* pParent=NULL,BOOL bDelMaster=FALSE,
                                    BOOL bDisabled=FALSE,ULONG nPos=LIST_APPEND);

    SvLBoxEntry*    InsertChangeActionContent(const ScChangeActionContent* pScChangeAction,
                                              SvLBoxEntry* pParent,ULONG nSpecial);

    void            GetDependents( const ScChangeAction* pScChangeAction,
                                ScChangeActionTable& aActionTable,
                                SvLBoxEntry* pEntry);

    BOOL            InsertContentChilds(ScChangeActionTable* pActionTable,SvLBoxEntry* pParent);

    BOOL            InsertAcceptedORejected(SvLBoxEntry* pParent);

    BOOL            InsertDeletedChilds(const ScChangeAction *pChangeAction, ScChangeActionTable* pActionTable,
                                        SvLBoxEntry* pParent);

    BOOL            InsertChilds(ScChangeActionTable* pActionTable,SvLBoxEntry* pParent);

    void            AppendChanges(ScChangeTrack* pChanges,ULONG nStartAction, ULONG nEndAction,
                                    ULONG nPos=LIST_APPEND);

    void            RemoveEntrys(ULONG nStartAction,ULONG nEndAction);
    void            UpdateEntrys(ScChangeTrack* pChgTrack, ULONG nStartAction,ULONG nEndAction);

    void            UpdateView();
    void            ClearView();

    BOOL            Expand(ScChangeTrack* pChanges,const ScChangeAction* pScChangeAction,
                            SvLBoxEntry* pEntry, BOOL bFilter=FALSE);

public:
                    ScAcceptChgDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent,
                               ScViewData*      ptrViewData);

                    ~ScAcceptChgDlg();

    void            ReInit(ScViewData* ptrViewData);

    virtual long    PreNotify( NotifyEvent& rNEvt );

    void            Initialize (SfxChildWinInfo* pInfo);
    virtual void    FillInfo(SfxChildWinInfo&) const;

};

#endif // SC_NAMEDLG_HXX

<commit_msg>del: International<commit_after>/*************************************************************************
 *
 *  $RCSfile: acredlin.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: er $ $Date: 2001-03-14 14:34:29 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_ACREDLIN_HXX
#define SC_ACREDLIN_HXX

#ifndef VCL
#endif

#ifndef _MOREBTN_HXX //autogen
#include <vcl/morebtn.hxx>
#endif
#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif
#ifndef _GROUP_HXX //autogen
#include <vcl/group.hxx>
#endif

#ifndef _HEADBAR_HXX //autogen
#include <svtools/headbar.hxx>
#endif

#ifndef _SVTABBX_HXX //autogen
#include <svtools/svtabbx.hxx>
#endif

#ifndef SC_RANGENAM_HXX
#include "rangenam.hxx"
#endif

#ifndef SC_ANYREFDG_HXX
#include "anyrefdg.hxx"
#endif

#ifndef _SV_LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _SVX_ACREDLIN_HXX
#include <svx/ctredlin.hxx>
#endif

#ifndef _SVX_SIMPTABL_HXX
#include <svx/simptabl.hxx>
#endif

#ifndef _SVARRAY_HXX
#define _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif

#ifndef SC_CHGTRACK_HXX
#include "chgtrack.hxx"
#endif

#ifndef SC_CHGVISET_HXX
#include "chgviset.hxx"
#endif

#ifndef _SV_TIMER_HXX //autogen
#include <vcl/timer.hxx>
#endif

class ScViewData;
class ScDocument;

#define FLT_DATE_BEFORE     0
#define FLT_DATE_SINCE      1
#define FLT_DATE_EQUAL      2
#define FLT_DATE_NOTEQUAL   3
#define FLT_DATE_BETWEEN    4
#define FLT_DATE_SAVE       5

class ScViewEntryPtr
{
private:
    String*         pAction;
    String*         pPos;
    String*         pAuthor;
    String*         pDate;
    String*         pComment;
    void*           pData;

public:

    String*         GetpAction()    {return pAction; }
    String*         GetpPos()       {return pPos;    }
    String*         GetpAuthor()    {return pAuthor; }
    String*         GetpDate()      {return pDate;   }
    String*         GetpComment()   {return pComment;}
    void*           GetpData()      {return pData;   }

    void        SetpAction (String* pString)    {pAction= pString;}
    void        SetpPos    (String* pString)    {pPos   = pString;}
    void        SetpAuthor (String* pString)    {pAuthor= pString;}
    void        SetpDate   (String* pString)    {pDate  = pString;}
    void        SetpComment(String* pString)    {pComment=pString;}
    void        SetpData   (void*   pdata)      {pData   =pdata;}
};

class ScViewEntryPtrList
{
    ScViewEntryPtrList* pNext;
    ScViewEntryPtrList* pLast;

    ScViewEntryPtr* pData;
};

class ScRedlinData : public RedlinData
{
public:

                    ScRedlinData();
                    ~ScRedlinData();
    USHORT          nTable;
    USHORT          nCol;
    USHORT          nRow;
    ULONG           nActionNo;
    ULONG           nInfo;
    BOOL            bIsRejectable;
    BOOL            bIsAcceptable;
};

typedef long LExpNum;

//@ Expand-Entrys nicht eindeutig, daher gestrichen
//DECLARE_TABLE( ScChgTrackExps, LExpNum)
//==================================================================

class ScAcceptChgDlg : public SfxModelessDialog
{
private:

    Timer                   aSelectionTimer;
    Timer                   aReOpenTimer;
    SvxAcceptChgCtr         aAcceptChgCtr;
    ScViewData*             pViewData;
    ScDocument*             pDoc;
    ScRangeName             aLocalRangeName;
    Selection               theCurSel;
    SvxTPFilter*            pTPFilter;
    SvxTPView*              pTPView;
    SvxRedlinTable*         pTheView;
    Size                    MinSize;
    ScRangeList             aRangeList;
    ScChangeViewSettings    aChangeViewSet;
    String                  aStrInsertCols;
    String                  aStrInsertRows;
    String                  aStrInsertTabs;
    String                  aStrDeleteCols;
    String                  aStrDeleteRows;
    String                  aStrDeleteTabs;
    String                  aStrMove;
    String                  aStrContent;
    String                  aStrReject;
    String                  aUnknown;
    String                  aStrAllAccepted;
    String                  aStrAllRejected;
    String                  aStrNoEntry;
    String                  aStrContentWithChild;
    String                  aStrChildContent;
    String                  aStrChildOrgContent;
    String                  aStrEmpty;
    Bitmap                  aExpBmp;
    Bitmap                  aCollBmp;
    Bitmap                  aCloseBmp;
    Bitmap                  aOpenBmp;
    Bitmap                  aEndBmp;
    Bitmap                  aErrorBmp;
    ULONG                   nAcceptCount;
    ULONG                   nRejectCount;
    BOOL                    bAcceptEnableFlag;
    BOOL                    bRejectEnableFlag;
    BOOL                    bNeedsUpdate;
    BOOL                    bIgnoreMsg;
    BOOL                    bNoSelection;
    BOOL                    bHasFilterEntry;
    BOOL                    bUseColor;
    //ScChgTrackExps            aExpandArray;

    void            Init();
    void            InitFilter();
    void            SetMyStaticData();

    DECL_LINK( FilterHandle, SvxTPFilter* );
    DECL_LINK( RefHandle, SvxTPFilter* );
    DECL_LINK( FilterModified, SvxTPFilter* );
    DECL_LINK( MinSizeHandle, SvxAcceptChgCtr*);
    DECL_LINK( RejectHandle, SvxTPView*);
    DECL_LINK( AcceptHandle, SvxTPView*);
    DECL_LINK( RejectAllHandle, SvxTPView*);
    DECL_LINK( AcceptAllHandle, SvxTPView*);
    DECL_LINK( ExpandingHandle, SvxRedlinTable*);
    DECL_LINK( SelectHandle, SvxRedlinTable*);
    DECL_LINK( RefInfoHandle, String*);

    DECL_LINK( UpdateSelectionHdl, Timer*);
    DECL_LINK( ChgTrackModHdl, ScChangeTrack*);
    DECL_LINK( CommandHdl, Control*);
    DECL_LINK( ReOpenTimerHdl, Timer*);
    DECL_LINK( ColCompareHdl, SvSortData*);

protected:

    virtual void    Resize();
    virtual BOOL    Close();

    void            RejectFiltered();
    void            AcceptFiltered();

    BOOL            IsValidAction(const ScChangeAction* pScChangeAction);

    String*         MakeTypeString(ScChangeActionType eType);

    SvLBoxEntry*    InsertChangeAction(const ScChangeAction* pScChangeAction,ScChangeActionState eState,
                                    SvLBoxEntry* pParent=NULL,BOOL bDelMaster=FALSE,
                                    BOOL bDisabled=FALSE,ULONG nPos=LIST_APPEND);

    SvLBoxEntry*    InsertFilteredAction(const ScChangeAction* pScChangeAction,ScChangeActionState eState,
                                    SvLBoxEntry* pParent=NULL,BOOL bDelMaster=FALSE,
                                    BOOL bDisabled=FALSE,ULONG nPos=LIST_APPEND);

    SvLBoxEntry*    InsertChangeActionContent(const ScChangeActionContent* pScChangeAction,
                                              SvLBoxEntry* pParent,ULONG nSpecial);

    void            GetDependents( const ScChangeAction* pScChangeAction,
                                ScChangeActionTable& aActionTable,
                                SvLBoxEntry* pEntry);

    BOOL            InsertContentChilds(ScChangeActionTable* pActionTable,SvLBoxEntry* pParent);

    BOOL            InsertAcceptedORejected(SvLBoxEntry* pParent);

    BOOL            InsertDeletedChilds(const ScChangeAction *pChangeAction, ScChangeActionTable* pActionTable,
                                        SvLBoxEntry* pParent);

    BOOL            InsertChilds(ScChangeActionTable* pActionTable,SvLBoxEntry* pParent);

    void            AppendChanges(ScChangeTrack* pChanges,ULONG nStartAction, ULONG nEndAction,
                                    ULONG nPos=LIST_APPEND);

    void            RemoveEntrys(ULONG nStartAction,ULONG nEndAction);
    void            UpdateEntrys(ScChangeTrack* pChgTrack, ULONG nStartAction,ULONG nEndAction);

    void            UpdateView();
    void            ClearView();

    BOOL            Expand(ScChangeTrack* pChanges,const ScChangeAction* pScChangeAction,
                            SvLBoxEntry* pEntry, BOOL bFilter=FALSE);

public:
                    ScAcceptChgDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent,
                               ScViewData*      ptrViewData);

                    ~ScAcceptChgDlg();

    void            ReInit(ScViewData* ptrViewData);

    virtual long    PreNotify( NotifyEvent& rNEvt );

    void            Initialize (SfxChildWinInfo* pInfo);
    virtual void    FillInfo(SfxChildWinInfo&) const;

};

#endif // SC_NAMEDLG_HXX

<|endoftext|>


<commit_before><commit_msg>tdf#91015 - CSV dialog crasher.<commit_after><|endoftext|>