<commit_before>////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program 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.
//
// 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.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

//#include <iostream> // TODO Remove.
#include <Context.h>
#include <text.h>
#include <TDB2.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
TF2::TF2 ()
: _read_only (false)
, _dirty (false)
, _loaded_tasks (false)
, _loaded_lines (false)
, _loaded_contents (false)
, _contents ("")
{
}

////////////////////////////////////////////////////////////////////////////////
TF2::~TF2 ()
{
}

////////////////////////////////////////////////////////////////////////////////
void TF2::target (const std::string& f)
{
  _file = File (f);
  _read_only = ! _file.writable ();

//  std::cout << "# TF2::target " << f << "\n";
}

////////////////////////////////////////////////////////////////////////////////
const std::vector <Task>& TF2::get_tasks ()
{
//  std::cout << "# TF2::get_tasks " << _file.data << "\n";

  if (! _loaded_tasks)
    load_tasks ();

  return _tasks;
}

////////////////////////////////////////////////////////////////////////////////
const std::vector <std::string>& TF2::get_lines ()
{
//  std::cout << "# TF2::get_lines " << _file.data << "\n";

  if (! _loaded_lines)
    load_lines ();

  return _lines;
}

////////////////////////////////////////////////////////////////////////////////
const std::string& TF2::get_contents ()
{
//  std::cout << "# TF2::get_contents " << _file.data << "\n";

  if (! _loaded_contents)
    load_contents ();

  return _contents;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::add_task (const Task& task)
{
//  std::cout << "# TF2::add_task " << _file.data << "\n";

  _tasks.push_back (task);           // For subsequent queries
  _added_tasks.push_back (task);     // For commit/synch
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::modify_task (const Task& task)
{
//  std::cout << "# TF2::modify_task " << _file.data << "\n";

  // Modify in-place.
  std::vector <Task>::iterator i;
  for (i = _tasks.begin (); i != _tasks.end (); ++i)
  {
    if (i->get ("uuid") == task.get ("uuid"))
    {
      *i = task;
      break;
    }
  }

  _modified_tasks.push_back (task);
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::add_line (const std::string& line)
{
//  std::cout << "# TF2::add_line " << _file.data << "\n";

  _added_lines.push_back (line);
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
// This is so that synch.key can just overwrite and not grow.
void TF2::clear_lines ()
{
//  std::cout << "# TF2::clear_lines " << _file.data << "\n";
  _lines.clear ();
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
// Top-down recomposition.
void TF2::commit ()
{
//  std::cout << "# TF2::commit " << _file.data << "\n";

  // The _dirty flag indicates that the file needs to be written.
  if (_dirty)
  {
    // Special case: added but no modified means just append to the file.
    if (!_modified_tasks.size () &&
        (_added_tasks.size () || _added_lines.size ()))
    {
      if (_file.open ())
      {
        if (context.config.getBoolean ("locking"))
          _file.lock ();

        // Write out all the added tasks.
        std::vector <Task>::iterator task;
        for (task = _added_tasks.begin ();
             task != _added_tasks.end ();
             ++task)
        {
          _file.append (task->composeF4 ());
        }

        _added_tasks.clear ();

        // Write out all the added lines.
        std::vector <std::string>::iterator line;
        for (line = _added_lines.begin ();
             line != _added_lines.end ();
             ++line)
        {
          _file.append (*line);
        }

        _added_lines.clear ();
        _file.close ();
      }
    }
    else
    {
      // TODO _file.truncate ();
      // TODO only write out _tasks, because any deltas have already been applied.
      // TODO append _added_lines.
    }

    _dirty = false;
  }

  // --------------------------- old implementation -------------------------
/*
  // Load the lowest form, to allow
  if (_dirty)
  {
    load_contents ();

    if (_modified_tasks.size ())
    {
      std::map <std::string, Task> modified;
      std::vector <Task>::iterator it;
      for (it = _modified_tasks.begin (); it != _modified_tasks.end (); ++it)
        modified[it->get ("uuid")] = *it;

//    for (it = _

     _modified_tasks.clear ();
    }

    if (_added_tasks.size ())
    {
      std::vector <Task>::iterator it;
      for (it = _added_tasks.begin (); it != _added_tasks.end (); ++it)
        _lines.push_back (it->composeF4 ());

      _added_tasks.clear ();
    }

    if (_added_lines.size ())
    {
      //_lines += _added_lines;
      _added_lines.clear ();
    }

// TODO This clobbers minimal case.

    _contents = "";  // TODO Verify no resize.
    join (_contents, "\n", _lines);
    _file.write (_contents);

    _dirty = false;
  }
*/
}

////////////////////////////////////////////////////////////////////////////////
void TF2::load_tasks ()
{
//  std::cout << "# TF2::load_tasks " << _file.data << "\n";

  if (! _loaded_lines)
    load_lines ();

  int id = 1;
  int line_number = 0;
  try
  {
    std::vector <std::string>::iterator i;
    for (i = _lines.begin (); i != _lines.end (); ++i)
    {
      ++line_number;
      Task task (*i);

      // Only set an ID for live tasks.
      Task::status status = task.getStatus ();
      if (status != Task::deleted &&
          status != Task::completed)
        task.id = id++;

      _tasks.push_back (task);

      // Maintain mapping for ease of link/dependency resolution.
      // Note that this mapping is not restricted by the filter, and is
      // therefore a complete set.
      if (task.id)
      {
        _I2U[task.id] = task.get ("uuid");
        _U2I[task.get ("uuid")] = task.id;
      }
    }

    _loaded_tasks = true;
  }

  catch (std::string& e)
  {
    throw e + format (" in {1} at line {2}", _file.data, line_number);
  }
}

////////////////////////////////////////////////////////////////////////////////
void TF2::load_lines ()
{
//  std::cout << "# TF2::load_lines " << _file.data << "\n";

  if (! _loaded_contents)
    load_contents ();

  split_minimal (_lines, _contents, '\n');
  _loaded_lines = true;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::load_contents ()
{
//  std::cout << "# TF2::load_contents " << _file.data << "\n";

  _contents = "";

  if (_file.open ())
  {
    if (context.config.getBoolean ("locking"))
      _file.lock ();

    _file.read (_contents);
    _loaded_contents = true;
  }
  // TODO Error handling?
}

////////////////////////////////////////////////////////////////////////////////
std::string TF2::uuid (int id)
{
  if (! _loaded_tasks)
    load_tasks ();

  std::map <int, std::string>::const_iterator i;
  if ((i = _I2U.find (id)) != _I2U.end ())
    return i->second;

  return "";
}

////////////////////////////////////////////////////////////////////////////////
int TF2::id (const std::string& uuid)
{
  if (! _loaded_tasks)
    load_tasks ();

  std::map <std::string, int>::const_iterator i;
  if ((i = _U2I.find (uuid)) != _U2I.end ())
    return i->second;

  return 0;
}

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
TDB2::TDB2 ()
: _location ("")
, _id (1)
{
}

////////////////////////////////////////////////////////////////////////////////
// Deliberately no file writes on destruct.  TDB2::commit should have been
// already called, if data is to be preserved.
TDB2::~TDB2 ()
{
}

////////////////////////////////////////////////////////////////////////////////
// Once a location is known, the files can be set up.  Note that they are not
// read.
void TDB2::set_location (const std::string& location)
{
//  std::cout << "# TDB2::set_location " << location << "\n";
  _location = location;

  pending.target   (location + "/pending.data");
  completed.target (location + "/completed.data");
  undo.target      (location + "/undo.data");
  backlog.target   (location + "/backlog.data");
  synch_key.target (location + "/synch.key");
}

////////////////////////////////////////////////////////////////////////////////
// Add the new task to the appropriate file.
void TDB2::add (const Task& task)
{
//  std::cout << "# TDB2::add\n";

  std::string status = task.get ("status");
  if (status == "completed" ||
      status == "deleted")
    completed.add_task (task);
  else
    pending.add_task (task);

  backlog.add_task (task);
}

////////////////////////////////////////////////////////////////////////////////
void TDB2::modify (const Task& task)
{
//  std::cout << "# TDB2::modify\n";

  std::string status = task.get ("status");
  if (status == "completed" ||
      status == "deleted")
    completed.modify_task (task);
  else
    pending.modify_task (task);

  backlog.modify_task (task);
}

////////////////////////////////////////////////////////////////////////////////
void TDB2::commit ()
{
  dump ();
//  std::cout << "# TDB2::commit\n";
  pending.commit ();
  completed.commit ();
  undo.commit ();
  backlog.commit ();
  synch_key.commit ();
  dump ();
}

////////////////////////////////////////////////////////////////////////////////
// Scans the pending tasks for any that are completed or deleted, and if so,
// moves them to the completed.data file.  Returns a count of tasks moved.
// Now reverts expired waiting tasks to pending.
// Now cleans up dangling dependencies.
int TDB2::gc ()
{
//  std::cout << "# TDB2::gc\n";
/*
  pending.load_tasks
  completed.load_tasks

  for each pending
    if status == completed || status == deleted
      pending.remove
      completed.add
    if status == waiting && wait < now
      status = pending
      wait.clear

  for each completed
    if status == pending || status == waiting
      completed.remove
      pending.add
*/

  // TODO Remove dangling dependencies
  // TODO Wake up expired waiting tasks

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
// Next ID is that of the last pending task plus one.
int TDB2::next_id ()
{
  if (! pending._loaded_tasks)
  pending.load_tasks ();

  _id = pending._tasks.back ().id + 1;
  return _id++;
}

////////////////////////////////////////////////////////////////////////////////
//
//  File           RW State Tasks + - ~ lines + - Bytes
//  -------------- -- ----- ----- - - - ----- - - -----
//  pending.data   rw clean   123t  +2t  -1t ~1t
//  completed.data rw clean   123t  +2t      ~1t
//  undo.data      rw clean   123t  +2t      ~1t
//  backlog.data   rw clean   123t  +2t      ~1t
//  synch-key.data rw clean                        123b
//
void TDB2::dump ()
{
  if (context.config.getBoolean ("debug"))
  {
    ViewText view;
    view.width (context.getWidth ());
    view.add (Column::factory ("string",       "File"));
    view.add (Column::factory ("string.right", "RW"));
    view.add (Column::factory ("string.right", "State"));
    view.add (Column::factory ("string.right", "Tasks"));
    view.add (Column::factory ("string.right", "+"));
    view.add (Column::factory ("string.right", "~"));
    view.add (Column::factory ("string.right", "Lines"));
    view.add (Column::factory ("string.right", "+"));
    view.add (Column::factory ("string.right", "Bytes"));

    dump_file (view, "pending.data", pending);
    dump_file (view, "completed.data", completed);
    dump_file (view, "undo.data", undo);
    dump_file (view, "backlog.data", backlog);
    dump_file (view, "synch_key.data", synch_key);
    context.debug (view.render ());
  }
}

////////////////////////////////////////////////////////////////////////////////
void TDB2::dump_file (ViewText& view, const std::string& label, TF2& tf)
{
  int row = view.addRow ();
  view.set (row, 0, label);
  view.set (row, 1, std::string (tf._file.readable () ? "r" : "-") +
                    std::string (tf._file.writable () ? "w" : "-"));
  view.set (row, 2, tf._dirty ? "dirty" : "clean");
  view.set (row, 3, tf._loaded_tasks ? (format ((int)tf._tasks.size ())) : "-");
  view.set (row, 4, (int)tf._added_tasks.size ());
  view.set (row, 5, (int)tf._modified_tasks.size ());
  view.set (row, 6, tf._loaded_lines ? (format ((int)tf._lines.size ())) : "-");
  view.set (row, 7, (int)tf._added_lines.size ());
  view.set (row, 8, tf._loaded_contents ? (format ((int)tf._contents.size ())) : "-");
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>TDB2 - Timing<commit_after>////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program 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.
//
// 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.,
//     51 Franklin Street, Fifth Floor,
//     Boston, MA
//     02110-1301
//     USA
//
////////////////////////////////////////////////////////////////////////////////

//#include <iostream> // TODO Remove.
#include <Context.h>
#include <Timer.h>
#include <text.h>
#include <TDB2.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
TF2::TF2 ()
: _read_only (false)
, _dirty (false)
, _loaded_tasks (false)
, _loaded_lines (false)
, _loaded_contents (false)
, _contents ("")
{
}

////////////////////////////////////////////////////////////////////////////////
TF2::~TF2 ()
{
}

////////////////////////////////////////////////////////////////////////////////
void TF2::target (const std::string& f)
{
  _file = File (f);
  _read_only = ! _file.writable ();

//  std::cout << "# TF2::target " << f << "\n";
}

////////////////////////////////////////////////////////////////////////////////
const std::vector <Task>& TF2::get_tasks ()
{
//  std::cout << "# TF2::get_tasks " << _file.data << "\n";
  Timer timer ("TF2::get_tasks " + _file.data);

  if (! _loaded_tasks)
    load_tasks ();

  return _tasks;
}

////////////////////////////////////////////////////////////////////////////////
const std::vector <std::string>& TF2::get_lines ()
{
//  std::cout << "# TF2::get_lines " << _file.data << "\n";

  if (! _loaded_lines)
    load_lines ();

  return _lines;
}

////////////////////////////////////////////////////////////////////////////////
const std::string& TF2::get_contents ()
{
//  std::cout << "# TF2::get_contents " << _file.data << "\n";

  if (! _loaded_contents)
    load_contents ();

  return _contents;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::add_task (const Task& task)
{
//  std::cout << "# TF2::add_task " << _file.data << "\n";

  _tasks.push_back (task);           // For subsequent queries
  _added_tasks.push_back (task);     // For commit/synch
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::modify_task (const Task& task)
{
//  std::cout << "# TF2::modify_task " << _file.data << "\n";

  // Modify in-place.
  std::vector <Task>::iterator i;
  for (i = _tasks.begin (); i != _tasks.end (); ++i)
  {
    if (i->get ("uuid") == task.get ("uuid"))
    {
      *i = task;
      break;
    }
  }

  _modified_tasks.push_back (task);
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::add_line (const std::string& line)
{
//  std::cout << "# TF2::add_line " << _file.data << "\n";

  _added_lines.push_back (line);
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
// This is so that synch.key can just overwrite and not grow.
void TF2::clear_lines ()
{
//  std::cout << "# TF2::clear_lines " << _file.data << "\n";
  _lines.clear ();
  _dirty = true;
}

////////////////////////////////////////////////////////////////////////////////
// Top-down recomposition.
void TF2::commit ()
{
//  std::cout << "# TF2::commit " << _file.data << "\n";

  // The _dirty flag indicates that the file needs to be written.
  if (_dirty)
  {
    // Special case: added but no modified means just append to the file.
    if (!_modified_tasks.size () &&
        (_added_tasks.size () || _added_lines.size ()))
    {
      if (_file.open ())
      {
        if (context.config.getBoolean ("locking"))
          _file.lock ();

        // Write out all the added tasks.
        std::vector <Task>::iterator task;
        for (task = _added_tasks.begin ();
             task != _added_tasks.end ();
             ++task)
        {
          _file.append (task->composeF4 ());
        }

        _added_tasks.clear ();

        // Write out all the added lines.
        std::vector <std::string>::iterator line;
        for (line = _added_lines.begin ();
             line != _added_lines.end ();
             ++line)
        {
          _file.append (*line);
        }

        _added_lines.clear ();
        _file.close ();
      }
    }
    else
    {
      // TODO _file.truncate ();
      // TODO only write out _tasks, because any deltas have already been applied.
      // TODO append _added_lines.
    }

    _dirty = false;
  }

  // --------------------------- old implementation -------------------------
/*
  // Load the lowest form, to allow
  if (_dirty)
  {
    load_contents ();

    if (_modified_tasks.size ())
    {
      std::map <std::string, Task> modified;
      std::vector <Task>::iterator it;
      for (it = _modified_tasks.begin (); it != _modified_tasks.end (); ++it)
        modified[it->get ("uuid")] = *it;

//    for (it = _

     _modified_tasks.clear ();
    }

    if (_added_tasks.size ())
    {
      std::vector <Task>::iterator it;
      for (it = _added_tasks.begin (); it != _added_tasks.end (); ++it)
        _lines.push_back (it->composeF4 ());

      _added_tasks.clear ();
    }

    if (_added_lines.size ())
    {
      //_lines += _added_lines;
      _added_lines.clear ();
    }

// TODO This clobbers minimal case.

    _contents = "";  // TODO Verify no resize.
    join (_contents, "\n", _lines);
    _file.write (_contents);

    _dirty = false;
  }
*/
}

////////////////////////////////////////////////////////////////////////////////
void TF2::load_tasks ()
{
//  std::cout << "# TF2::load_tasks " << _file.data << "\n";

  if (! _loaded_lines)
    load_lines ();

  int id = 1;
  int line_number = 0;
  try
  {
    std::vector <std::string>::iterator i;
    for (i = _lines.begin (); i != _lines.end (); ++i)
    {
      ++line_number;
      Task task (*i);

      // Only set an ID for live tasks.
      Task::status status = task.getStatus ();
      if (status != Task::deleted &&
          status != Task::completed)
        task.id = id++;

      _tasks.push_back (task);

      // Maintain mapping for ease of link/dependency resolution.
      // Note that this mapping is not restricted by the filter, and is
      // therefore a complete set.
      if (task.id)
      {
        _I2U[task.id] = task.get ("uuid");
        _U2I[task.get ("uuid")] = task.id;
      }
    }

    _loaded_tasks = true;
  }

  catch (std::string& e)
  {
    throw e + format (" in {1} at line {2}", _file.data, line_number);
  }
}

////////////////////////////////////////////////////////////////////////////////
void TF2::load_lines ()
{
//  std::cout << "# TF2::load_lines " << _file.data << "\n";

  if (! _loaded_contents)
    load_contents ();

  split_minimal (_lines, _contents, '\n');
  _loaded_lines = true;
}

////////////////////////////////////////////////////////////////////////////////
void TF2::load_contents ()
{
//  std::cout << "# TF2::load_contents " << _file.data << "\n";

  _contents = "";

  if (_file.open ())
  {
    if (context.config.getBoolean ("locking"))
      _file.lock ();

    _file.read (_contents);
    _loaded_contents = true;
  }
  // TODO Error handling?
}

////////////////////////////////////////////////////////////////////////////////
std::string TF2::uuid (int id)
{
  if (! _loaded_tasks)
    load_tasks ();

  std::map <int, std::string>::const_iterator i;
  if ((i = _I2U.find (id)) != _I2U.end ())
    return i->second;

  return "";
}

////////////////////////////////////////////////////////////////////////////////
int TF2::id (const std::string& uuid)
{
  if (! _loaded_tasks)
    load_tasks ();

  std::map <std::string, int>::const_iterator i;
  if ((i = _U2I.find (uuid)) != _U2I.end ())
    return i->second;

  return 0;
}

////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
TDB2::TDB2 ()
: _location ("")
, _id (1)
{
}

////////////////////////////////////////////////////////////////////////////////
// Deliberately no file writes on destruct.  TDB2::commit should have been
// already called, if data is to be preserved.
TDB2::~TDB2 ()
{
}

////////////////////////////////////////////////////////////////////////////////
// Once a location is known, the files can be set up.  Note that they are not
// read.
void TDB2::set_location (const std::string& location)
{
//  std::cout << "# TDB2::set_location " << location << "\n";
  _location = location;

  pending.target   (location + "/pending.data");
  completed.target (location + "/completed.data");
  undo.target      (location + "/undo.data");
  backlog.target   (location + "/backlog.data");
  synch_key.target (location + "/synch.key");
}

////////////////////////////////////////////////////////////////////////////////
// Add the new task to the appropriate file.
void TDB2::add (const Task& task)
{
//  std::cout << "# TDB2::add\n";

  std::string status = task.get ("status");
  if (status == "completed" ||
      status == "deleted")
    completed.add_task (task);
  else
    pending.add_task (task);

  backlog.add_task (task);
}

////////////////////////////////////////////////////////////////////////////////
void TDB2::modify (const Task& task)
{
//  std::cout << "# TDB2::modify\n";

  std::string status = task.get ("status");
  if (status == "completed" ||
      status == "deleted")
    completed.modify_task (task);
  else
    pending.modify_task (task);

  backlog.modify_task (task);
}

////////////////////////////////////////////////////////////////////////////////
void TDB2::commit ()
{
  dump ();
  Timer timer ("TDB2::commit");
  pending.commit ();
  completed.commit ();
  undo.commit ();
  backlog.commit ();
  synch_key.commit ();
  dump ();
}

////////////////////////////////////////////////////////////////////////////////
// Scans the pending tasks for any that are completed or deleted, and if so,
// moves them to the completed.data file.  Returns a count of tasks moved.
// Now reverts expired waiting tasks to pending.
// Now cleans up dangling dependencies.
int TDB2::gc ()
{
  Timer timer ("TDB2::gc");
/*
  pending.load_tasks
  completed.load_tasks

  for each pending
    if status == completed || status == deleted
      pending.remove
      completed.add
    if status == waiting && wait < now
      status = pending
      wait.clear

  for each completed
    if status == pending || status == waiting
      completed.remove
      pending.add
*/

  // TODO Remove dangling dependencies
  // TODO Wake up expired waiting tasks

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
// Next ID is that of the last pending task plus one.
int TDB2::next_id ()
{
  if (! pending._loaded_tasks)
  pending.load_tasks ();

  _id = pending._tasks.back ().id + 1;
  return _id++;
}

////////////////////////////////////////////////////////////////////////////////
//
//  File           RW State Tasks + - ~ lines + - Bytes
//  -------------- -- ----- ----- - - - ----- - - -----
//  pending.data   rw clean   123t  +2t  -1t ~1t
//  completed.data rw clean   123t  +2t      ~1t
//  undo.data      rw clean   123t  +2t      ~1t
//  backlog.data   rw clean   123t  +2t      ~1t
//  synch-key.data rw clean                        123b
//
void TDB2::dump ()
{
  if (context.config.getBoolean ("debug"))
  {
    ViewText view;
    view.width (context.getWidth ());
    view.add (Column::factory ("string",       "File"));
    view.add (Column::factory ("string.right", "RW"));
    view.add (Column::factory ("string.right", "State"));
    view.add (Column::factory ("string.right", "Tasks"));
    view.add (Column::factory ("string.right", "+"));
    view.add (Column::factory ("string.right", "~"));
    view.add (Column::factory ("string.right", "Lines"));
    view.add (Column::factory ("string.right", "+"));
    view.add (Column::factory ("string.right", "Bytes"));

    dump_file (view, "pending.data", pending);
    dump_file (view, "completed.data", completed);
    dump_file (view, "undo.data", undo);
    dump_file (view, "backlog.data", backlog);
    dump_file (view, "synch_key.data", synch_key);
    context.debug (view.render ());
  }
}

////////////////////////////////////////////////////////////////////////////////
void TDB2::dump_file (ViewText& view, const std::string& label, TF2& tf)
{
  int row = view.addRow ();
  view.set (row, 0, label);
  view.set (row, 1, std::string (tf._file.readable () ? "r" : "-") +
                    std::string (tf._file.writable () ? "w" : "-"));
  view.set (row, 2, tf._dirty ? "dirty" : "clean");
  view.set (row, 3, tf._loaded_tasks ? (format ((int)tf._tasks.size ())) : "-");
  view.set (row, 4, (int)tf._added_tasks.size ());
  view.set (row, 5, (int)tf._modified_tasks.size ());
  view.set (row, 6, tf._loaded_lines ? (format ((int)tf._lines.size ())) : "-");
  view.set (row, 7, (int)tf._added_lines.size ());
  view.set (row, 8, tf._loaded_contents ? (format ((int)tf._contents.size ())) : "-");
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Assistant of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qhelpprojectdata_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QStack>
#include <QtCore/QMap>
#include <QtCore/QRegExp>
#include <QtCore/QVariant>
#include <QtXml/QXmlStreamReader>

QT_BEGIN_NAMESPACE

class QHelpProjectDataPrivate : public QXmlStreamReader
{
public:
    void readData(const QByteArray &contents);

    QString virtualFolder;
    QString namespaceName;
    QString rootPath;

    QStringList fileList;
    QList<QHelpDataCustomFilter> customFilterList;
    QList<QHelpDataFilterSection> filterSectionList;
    QMap<QString, QVariant> metaData;

    QString errorMsg;

private:
    void readProject();
    void readCustomFilter();
    void readFilterSection();
    void readTOC();
    void readKeywords();
    void readFiles();
    void raiseUnknownTokenError();
    void addMatchingFiles(const QString &pattern);

    QMap<QString, QStringList> dirEntriesCache;
};

void QHelpProjectDataPrivate::raiseUnknownTokenError()
{
    raiseError(QCoreApplication::translate("QHelpProject", "Unknown token."));
}

void QHelpProjectDataPrivate::readData(const QByteArray &contents)
{
    addData(contents);
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("QtHelpProject")
                && attributes().value(QLatin1String("version")) == QLatin1String("1.0"))
                readProject();
            else
                raiseError(QCoreApplication::translate("QHelpProject",
                               "Unknown token. Expected \"QtHelpProject\"!"));
        }
    }

    if (hasError()) {
        raiseError(QCoreApplication::translate("QHelpProject",
                       "Error in line %1: %2").arg(lineNumber())
            .arg(errorString()));
    }
}

void QHelpProjectDataPrivate::readProject()
{
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("virtualFolder")) {
                virtualFolder = readElementText();
                if (virtualFolder.contains(QLatin1String("/")))
                    raiseError(QCoreApplication::translate("QHelpProject",
                                   "A virtual folder must not contain "
                                   "a \'/\' character!"));
            } else if (name() == QLatin1String("namespace")) {
                namespaceName = readElementText();
                if (namespaceName.contains(QLatin1String("/")))
                    raiseError(QCoreApplication::translate("QHelpProject",
                                   "A namespace must not contain a "
                                   "\'/\' character!"));
            } else if (name() == QLatin1String("customFilter")) {
                readCustomFilter();
            } else if (name() == QLatin1String("filterSection")) {
                readFilterSection();
            } else if (name() == QLatin1String("metaData")) {
                QString n = attributes().value(QLatin1String("name")).toString();
                if (!metaData.contains(n))
                    metaData[n]
                        = attributes().value(QLatin1String("value")).toString();
                else
                    metaData.insert(n, attributes().
                                    value(QLatin1String("value")).toString());
            } else {
                raiseUnknownTokenError();
            }
        } else if (isEndElement() && name() == QLatin1String("QtHelpProject")) {
            if (namespaceName.isEmpty())
                raiseError(QCoreApplication::translate("QHelpProject",
                              "Missing namespace in QtHelpProject."));
            else if (virtualFolder.isEmpty())
                raiseError(QCoreApplication::translate("QHelpProject",
                               "Missing virtual folder in QtHelpProject"));
            break;
        }
    }
}

void QHelpProjectDataPrivate::readCustomFilter()
{
    QHelpDataCustomFilter filter;
    filter.name = attributes().value(QLatin1String("name")).toString();
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("filterAttribute"))
                filter.filterAttributes.append(readElementText());
            else
                raiseUnknownTokenError();
        } else if (isEndElement() && name() == QLatin1String("customFilter")) {
            break;
        }
    }
    customFilterList.append(filter);
}

void QHelpProjectDataPrivate::readFilterSection()
{
    filterSectionList.append(QHelpDataFilterSection());
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("filterAttribute"))
                filterSectionList.last().addFilterAttribute(readElementText());
            else if (name() == QLatin1String("toc"))
                readTOC();
            else if (name() == QLatin1String("keywords"))
                readKeywords();
            else if (name() == QLatin1String("files"))
                readFiles();
            else
                raiseUnknownTokenError();
        } else if (isEndElement() && name() == QLatin1String("filterSection")) {
            break;
        }
    }
}

void QHelpProjectDataPrivate::readTOC()
{
    QStack<QHelpDataContentItem*> contentStack;
    QHelpDataContentItem *itm = 0;
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("section")) {
                QString title = attributes().value(QLatin1String("title")).toString();
                QString ref = attributes().value(QLatin1String("ref")).toString();
                if (contentStack.isEmpty()) {
                    itm = new QHelpDataContentItem(0, title, ref);
                    filterSectionList.last().addContent(itm);
                } else {
                    itm = new QHelpDataContentItem(contentStack.top(), title, ref);
                }
                contentStack.push(itm);
            } else {
                raiseUnknownTokenError();
            }
        } else if (isEndElement()) {
            if (name() == QLatin1String("section")) {
                contentStack.pop();
                continue;
            } else if (name() == QLatin1String("toc") && contentStack.isEmpty()) {
                break;
            } else {
                raiseUnknownTokenError();
            }
        }
    }
}

void QHelpProjectDataPrivate::readKeywords()
{
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("keyword")) {
                if (attributes().value(QLatin1String("ref")).toString().isEmpty()
                    || (attributes().value(QLatin1String("name")).toString().isEmpty()
                    && attributes().value(QLatin1String("id")).toString().isEmpty()))
                    raiseError(QCoreApplication::translate("QHelpProject",
                                   "Missing attribute in keyword at line %1.")
                               .arg(lineNumber()));
                filterSectionList.last()
                    .addIndex(QHelpDataIndexItem(attributes().
                                  value(QLatin1String("name")).toString(),
                              attributes().value(QLatin1String("id")).toString(),
                              attributes().value(QLatin1String("ref")).toString()));
            } else {
                raiseUnknownTokenError();
            }
        } else if (isEndElement()) {
            if (name() == QLatin1String("keyword"))
                continue;
            else if (name() == QLatin1String("keywords"))
                break;
            else
                raiseUnknownTokenError();
        }
    }
}

void QHelpProjectDataPrivate::readFiles()
{
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("file"))
                addMatchingFiles(readElementText());
            else
                raiseUnknownTokenError();
        } else if (isEndElement()) {
            if (name() == QLatin1String("file"))
                continue;
            else if (name() == QLatin1String("files"))
                break;
            else
                raiseUnknownTokenError();
        }
    }
}

// Expand file pattern and add matches into list. If the pattern does not match
// any files, insert the pattern itself so the QHelpGenerator will emit a
// meaningful warning later.
void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern)
{
    // The pattern matching is expensive, so we skip it if no
    // wildcard symbols occur in the string.
    if (!pattern.contains('?') && !pattern.contains('*')
        && !pattern.contains('[') && !pattern.contains(']')) {
        filterSectionList.last().addFile(pattern);
        return;
    }

    QFileInfo fileInfo(rootPath + '/' + pattern);
    const QDir &dir = fileInfo.dir();
    const QString &path = dir.canonicalPath();

    // QDir::entryList() is expensive, so we cache the results.
    QMap<QString, QStringList>::ConstIterator it = dirEntriesCache.find(path);
    const QStringList &entries = it != dirEntriesCache.constEnd() ?
                                 it.value() : dir.entryList(QDir::Files);
    if (it == dirEntriesCache.constEnd())
        dirEntriesCache.insert(path, entries);

    bool matchFound = false;
#ifdef Q_OS_WIN
    Qt::CaseSensitivity cs = Qt::CaseInsensitive;
#else
    Qt::CaseSensitivity cs = Qt::CaseSensitive;
#endif
    QRegExp regExp(fileInfo.fileName(), cs, QRegExp::Wildcard);
    foreach (const QString &file, entries) {
        if (regExp.exactMatch(file)) {
            matchFound = true;
            filterSectionList.last().
                addFile(QFileInfo(pattern).dir().path() + '/' + file);
        }
    }
    if (!matchFound)
        filterSectionList.last().addFile(pattern);
}

/*!
    \internal
    \class QHelpProjectData
    \since 4.4
    \brief The QHelpProjectData class stores all information found
    in a Qt help project file.

    The structure is filled with data by calling readData(). The
    specified file has to have the Qt help project file format in
    order to be read successfully. Possible reading errors can be
    retrieved by calling errorMessage().
*/

/*!
    Constructs a Qt help project data structure.
*/
QHelpProjectData::QHelpProjectData()
{
    d = new QHelpProjectDataPrivate;
}

/*!
    Destroys the help project data.
*/
QHelpProjectData::~QHelpProjectData()
{
    delete d;
}

/*!
    Reads the file \a fileName and stores the help data. The file has to
    have the Qt help project file format. Returns true if the file
    was successfully read, otherwise false.

    \sa errorMessage()
*/
bool QHelpProjectData::readData(const QString &fileName)
{
    d->rootPath = QFileInfo(fileName).absolutePath();
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        d->errorMsg = QCoreApplication::translate("QHelpProject",
                          "The input file %1 could not be opened!").arg(fileName);
        return false;
    }

    d->readData(file.readAll());
    return !d->hasError();
}

/*!
    Returns an error message if the reading of the Qt help project
    file failed. Otherwise, an empty QString is returned.

    \sa readData()
*/
QString QHelpProjectData::errorMessage() const
{
    if (d->hasError())
        return d->errorString();
    return d->errorMsg;
}

/*!
    \internal
*/
QString QHelpProjectData::namespaceName() const
{
    return d->namespaceName;
}

/*!
    \internal
*/
QString QHelpProjectData::virtualFolder() const
{
    return d->virtualFolder;
}

/*!
    \internal
*/
QList<QHelpDataCustomFilter> QHelpProjectData::customFilters() const
{
    return d->customFilterList;
}

/*!
    \internal
*/
QList<QHelpDataFilterSection> QHelpProjectData::filterSections() const
{
    return d->filterSectionList;
}

/*!
    \internal
*/
QMap<QString, QVariant> QHelpProjectData::metaData() const
{
    return d->metaData;
}

/*!
    \internal
*/
QString QHelpProjectData::rootPath() const
{
    return d->rootPath;
}

QT_END_NAMESPACE
<commit_msg>Assistant: Check namespace and virtual folder syntax of help projects.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Assistant of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qhelpprojectdata_p.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QStack>
#include <QtCore/QMap>
#include <QtCore/QRegExp>
#include <QtCore/QUrl>
#include <QtCore/QVariant>
#include <QtXml/QXmlStreamReader>

QT_BEGIN_NAMESPACE

class QHelpProjectDataPrivate : public QXmlStreamReader
{
public:
    void readData(const QByteArray &contents);

    QString virtualFolder;
    QString namespaceName;
    QString rootPath;

    QStringList fileList;
    QList<QHelpDataCustomFilter> customFilterList;
    QList<QHelpDataFilterSection> filterSectionList;
    QMap<QString, QVariant> metaData;

    QString errorMsg;

private:
    void readProject();
    void readCustomFilter();
    void readFilterSection();
    void readTOC();
    void readKeywords();
    void readFiles();
    void raiseUnknownTokenError();
    void addMatchingFiles(const QString &pattern);
    bool hasValidSyntax(const QString &nameSpace, const QString &vFolder) const;

    QMap<QString, QStringList> dirEntriesCache;
};

void QHelpProjectDataPrivate::raiseUnknownTokenError()
{
    raiseError(QCoreApplication::translate("QHelpProject", "Unknown token."));
}

void QHelpProjectDataPrivate::readData(const QByteArray &contents)
{
    addData(contents);
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("QtHelpProject")
                && attributes().value(QLatin1String("version")) == QLatin1String("1.0"))
                readProject();
            else
                raiseError(QCoreApplication::translate("QHelpProject",
                               "Unknown token. Expected \"QtHelpProject\"!"));
        }
    }

    if (hasError()) {
        raiseError(QCoreApplication::translate("QHelpProject",
                       "Error in line %1: %2").arg(lineNumber())
            .arg(errorString()));
    }
}

void QHelpProjectDataPrivate::readProject()
{
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("virtualFolder")) {
                virtualFolder = readElementText();
                if (!hasValidSyntax(QLatin1String("test"), virtualFolder))
                    raiseError(QCoreApplication::translate("QHelpProject",
                                   "Virtual folder has invalid syntax."));
            } else if (name() == QLatin1String("namespace")) {
                namespaceName = readElementText();
                if (!hasValidSyntax(namespaceName, QLatin1String("test")))
                    raiseError(QCoreApplication::translate("QHelpProject",
                                   "Namespace has invalid syntax."));
            } else if (name() == QLatin1String("customFilter")) {
                readCustomFilter();
            } else if (name() == QLatin1String("filterSection")) {
                readFilterSection();
            } else if (name() == QLatin1String("metaData")) {
                QString n = attributes().value(QLatin1String("name")).toString();
                if (!metaData.contains(n))
                    metaData[n]
                        = attributes().value(QLatin1String("value")).toString();
                else
                    metaData.insert(n, attributes().
                                    value(QLatin1String("value")).toString());
            } else {
                raiseUnknownTokenError();
            }
        } else if (isEndElement() && name() == QLatin1String("QtHelpProject")) {
            if (namespaceName.isEmpty())
                raiseError(QCoreApplication::translate("QHelpProject",
                              "Missing namespace in QtHelpProject."));
            else if (virtualFolder.isEmpty())
                raiseError(QCoreApplication::translate("QHelpProject",
                               "Missing virtual folder in QtHelpProject"));
            break;
        }
    }
}

void QHelpProjectDataPrivate::readCustomFilter()
{
    QHelpDataCustomFilter filter;
    filter.name = attributes().value(QLatin1String("name")).toString();
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("filterAttribute"))
                filter.filterAttributes.append(readElementText());
            else
                raiseUnknownTokenError();
        } else if (isEndElement() && name() == QLatin1String("customFilter")) {
            break;
        }
    }
    customFilterList.append(filter);
}

void QHelpProjectDataPrivate::readFilterSection()
{
    filterSectionList.append(QHelpDataFilterSection());
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("filterAttribute"))
                filterSectionList.last().addFilterAttribute(readElementText());
            else if (name() == QLatin1String("toc"))
                readTOC();
            else if (name() == QLatin1String("keywords"))
                readKeywords();
            else if (name() == QLatin1String("files"))
                readFiles();
            else
                raiseUnknownTokenError();
        } else if (isEndElement() && name() == QLatin1String("filterSection")) {
            break;
        }
    }
}

void QHelpProjectDataPrivate::readTOC()
{
    QStack<QHelpDataContentItem*> contentStack;
    QHelpDataContentItem *itm = 0;
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("section")) {
                QString title = attributes().value(QLatin1String("title")).toString();
                QString ref = attributes().value(QLatin1String("ref")).toString();
                if (contentStack.isEmpty()) {
                    itm = new QHelpDataContentItem(0, title, ref);
                    filterSectionList.last().addContent(itm);
                } else {
                    itm = new QHelpDataContentItem(contentStack.top(), title, ref);
                }
                contentStack.push(itm);
            } else {
                raiseUnknownTokenError();
            }
        } else if (isEndElement()) {
            if (name() == QLatin1String("section")) {
                contentStack.pop();
                continue;
            } else if (name() == QLatin1String("toc") && contentStack.isEmpty()) {
                break;
            } else {
                raiseUnknownTokenError();
            }
        }
    }
}

void QHelpProjectDataPrivate::readKeywords()
{
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("keyword")) {
                if (attributes().value(QLatin1String("ref")).toString().isEmpty()
                    || (attributes().value(QLatin1String("name")).toString().isEmpty()
                    && attributes().value(QLatin1String("id")).toString().isEmpty()))
                    raiseError(QCoreApplication::translate("QHelpProject",
                                   "Missing attribute in keyword at line %1.")
                               .arg(lineNumber()));
                filterSectionList.last()
                    .addIndex(QHelpDataIndexItem(attributes().
                                  value(QLatin1String("name")).toString(),
                              attributes().value(QLatin1String("id")).toString(),
                              attributes().value(QLatin1String("ref")).toString()));
            } else {
                raiseUnknownTokenError();
            }
        } else if (isEndElement()) {
            if (name() == QLatin1String("keyword"))
                continue;
            else if (name() == QLatin1String("keywords"))
                break;
            else
                raiseUnknownTokenError();
        }
    }
}

void QHelpProjectDataPrivate::readFiles()
{
    while (!atEnd()) {
        readNext();
        if (isStartElement()) {
            if (name() == QLatin1String("file"))
                addMatchingFiles(readElementText());
            else
                raiseUnknownTokenError();
        } else if (isEndElement()) {
            if (name() == QLatin1String("file"))
                continue;
            else if (name() == QLatin1String("files"))
                break;
            else
                raiseUnknownTokenError();
        }
    }
}

// Expand file pattern and add matches into list. If the pattern does not match
// any files, insert the pattern itself so the QHelpGenerator will emit a
// meaningful warning later.
void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern)
{
    // The pattern matching is expensive, so we skip it if no
    // wildcard symbols occur in the string.
    if (!pattern.contains('?') && !pattern.contains('*')
        && !pattern.contains('[') && !pattern.contains(']')) {
        filterSectionList.last().addFile(pattern);
        return;
    }

    QFileInfo fileInfo(rootPath + '/' + pattern);
    const QDir &dir = fileInfo.dir();
    const QString &path = dir.canonicalPath();

    // QDir::entryList() is expensive, so we cache the results.
    QMap<QString, QStringList>::ConstIterator it = dirEntriesCache.find(path);
    const QStringList &entries = it != dirEntriesCache.constEnd() ?
                                 it.value() : dir.entryList(QDir::Files);
    if (it == dirEntriesCache.constEnd())
        dirEntriesCache.insert(path, entries);

    bool matchFound = false;
#ifdef Q_OS_WIN
    Qt::CaseSensitivity cs = Qt::CaseInsensitive;
#else
    Qt::CaseSensitivity cs = Qt::CaseSensitive;
#endif
    QRegExp regExp(fileInfo.fileName(), cs, QRegExp::Wildcard);
    foreach (const QString &file, entries) {
        if (regExp.exactMatch(file)) {
            matchFound = true;
            filterSectionList.last().
                addFile(QFileInfo(pattern).dir().path() + '/' + file);
        }
    }
    if (!matchFound)
        filterSectionList.last().addFile(pattern);
}

bool QHelpProjectDataPrivate::hasValidSyntax(const QString &nameSpace,
                                             const QString &vFolder) const
{
    const QLatin1Char slash('/');
    if (nameSpace.contains(slash) || vFolder.contains(slash))
        return false;
    QUrl url;
    const QLatin1String scheme("qthelp");
    url.setScheme(scheme);
    url.setHost(nameSpace);
    url.setPath(vFolder);

    const QString expectedUrl(scheme + QLatin1String("://") + nameSpace + slash + vFolder);
    return url.isValid() && url.toString() == expectedUrl;
}

/*!
    \internal
    \class QHelpProjectData
    \since 4.4
    \brief The QHelpProjectData class stores all information found
    in a Qt help project file.

    The structure is filled with data by calling readData(). The
    specified file has to have the Qt help project file format in
    order to be read successfully. Possible reading errors can be
    retrieved by calling errorMessage().
*/

/*!
    Constructs a Qt help project data structure.
*/
QHelpProjectData::QHelpProjectData()
{
    d = new QHelpProjectDataPrivate;
}

/*!
    Destroys the help project data.
*/
QHelpProjectData::~QHelpProjectData()
{
    delete d;
}

/*!
    Reads the file \a fileName and stores the help data. The file has to
    have the Qt help project file format. Returns true if the file
    was successfully read, otherwise false.

    \sa errorMessage()
*/
bool QHelpProjectData::readData(const QString &fileName)
{
    d->rootPath = QFileInfo(fileName).absolutePath();
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly)) {
        d->errorMsg = QCoreApplication::translate("QHelpProject",
                          "The input file %1 could not be opened!").arg(fileName);
        return false;
    }

    d->readData(file.readAll());
    return !d->hasError();
}

/*!
    Returns an error message if the reading of the Qt help project
    file failed. Otherwise, an empty QString is returned.

    \sa readData()
*/
QString QHelpProjectData::errorMessage() const
{
    if (d->hasError())
        return d->errorString();
    return d->errorMsg;
}

/*!
    \internal
*/
QString QHelpProjectData::namespaceName() const
{
    return d->namespaceName;
}

/*!
    \internal
*/
QString QHelpProjectData::virtualFolder() const
{
    return d->virtualFolder;
}

/*!
    \internal
*/
QList<QHelpDataCustomFilter> QHelpProjectData::customFilters() const
{
    return d->customFilterList;
}

/*!
    \internal
*/
QList<QHelpDataFilterSection> QHelpProjectData::filterSections() const
{
    return d->filterSectionList;
}

/*!
    \internal
*/
QMap<QString, QVariant> QHelpProjectData::metaData() const
{
    return d->metaData;
}

/*!
    \internal
*/
QString QHelpProjectData::rootPath() const
{
    return d->rootPath;
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pcrservices.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: fs $ $Date: 2001-01-12 11:30:30 $
 *
 *  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 EXPRESS 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 _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif

//---------------------------------------------------------------------------------------

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL createRegistryInfo_OPropertyBrowserController();

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL pcr_createRegistryInfo()
{
    static sal_Bool s_bInit = sal_False;
    if (!s_bInit)
    {
        createRegistryInfo_OPropertyBrowserController();
        s_bInit = sal_True;
    }
}

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                const sal_Char  **ppEnvTypeName,
                uno_Environment **ppEnv
            )
{
    pcr_createRegistryInfo();
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
                void* pServiceManager,
                void* pRegistryKey
            )
{
    if (pRegistryKey)
    try
    {
        return ::pcr::OModule::writeComponentInfos(
            static_cast<XMultiServiceFactory*>(pServiceManager),
            static_cast<XRegistryKey*>(pRegistryKey));
    }
    catch (InvalidRegistryException& )
    {
        OSL_ASSERT("pcr::component_writeInfo: could not create a registry key (InvalidRegistryException) !");
    }

    return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
                    const sal_Char* pImplementationName,
                    void* pServiceManager,
                    void* pRegistryKey)
{
    Reference< XInterface > xRet;
    if (pServiceManager && pImplementationName)
    {
        xRet = ::pcr::OModule::getComponentFactory(
            ::rtl::OUString::createFromAscii(pImplementationName),
            static_cast< XMultiServiceFactory* >(pServiceManager));
    }

    if (xRet.is())
        xRet->acquire();
    return xRet.get();
};

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *
 *  Revision 1.0 11.01.01 09:14:45  fs
 ************************************************************************/

<commit_msg>#86096# pcr_createRegistryInfo_OControlFontDialog (new service in this module)<commit_after>/*************************************************************************
 *
 *  $RCSfile: pcrservices.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: fs $ $Date: 2001-06-11 11:33:45 $
 *
 *  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 EXPRESS 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 _EXTENSIONS_PROPCTRLR_MODULEPRC_HXX_
#include "modulepcr.hxx"
#endif

//---------------------------------------------------------------------------------------

using namespace ::rtl;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL createRegistryInfo_OPropertyBrowserController();
extern "C" void SAL_CALL createRegistryInfo_OControlFontDialog();

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL dbi_initializeModule()
{
    static sal_Bool s_bInit = sal_False;
    if (!s_bInit)
    {
        createRegistryInfo_OPropertyBrowserController();
        createRegistryInfo_OControlFontDialog();
        ::pcr::OModule::setResourceFilePrefix("pcr");
        s_bInit = sal_True;
    }
}

//---------------------------------------------------------------------------------------

extern "C" void SAL_CALL component_getImplementationEnvironment(
                const sal_Char  **ppEnvTypeName,
                uno_Environment **ppEnv
            )
{
    dbi_initializeModule();
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

//---------------------------------------------------------------------------------------
extern "C" sal_Bool SAL_CALL component_writeInfo(
                void* pServiceManager,
                void* pRegistryKey
            )
{
    if (pRegistryKey)
    try
    {
        return ::pcr::OModule::writeComponentInfos(
            static_cast<XMultiServiceFactory*>(pServiceManager),
            static_cast<XRegistryKey*>(pRegistryKey));
    }
    catch (InvalidRegistryException& )
    {
        OSL_ASSERT("pcr::component_writeInfo: could not create a registry key (InvalidRegistryException) !");
    }

    return sal_False;
}

//---------------------------------------------------------------------------------------
extern "C" void* SAL_CALL component_getFactory(
                    const sal_Char* pImplementationName,
                    void* pServiceManager,
                    void* pRegistryKey)
{
    Reference< XInterface > xRet;
    if (pServiceManager && pImplementationName)
    {
        xRet = ::pcr::OModule::getComponentFactory(
            ::rtl::OUString::createFromAscii(pImplementationName),
            static_cast< XMultiServiceFactory* >(pServiceManager));
    }

    if (xRet.is())
        xRet->acquire();
    return xRet.get();
};

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *  Revision 1.1  2001/01/12 11:30:30  fs
 *  initial checkin - outsourced the form property browser
 *
 *
 *  Revision 1.0 11.01.01 09:14:45  fs
 ************************************************************************/

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: usercontrol.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 20:32:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_USERCONTROL_HXX_
#define _EXTENSIONS_PROPCTRLR_USERCONTROL_HXX_

#ifndef _EXTENSIONS_PROPCTRLR_COMMONCONTROL_HXX_
#include "commoncontrol.hxx"
#endif
#define _ZFORLIST_DECLARE_TABLE
#ifndef _FMTFIELD_HXX_
#include <svtools/fmtfield.hxx>
#endif
#ifndef SVTOOLS_FILEURLBOX_HXX
#include <svtools/fileurlbox.hxx>
#endif
#ifndef _EXTENSIONS_PROPCTRLR_STANDARDCONTROL_HXX_
#include "standardcontrol.hxx"
#endif

class SvNumberFormatsSupplierObj;

//............................................................................
namespace pcr
{
//............................................................................

    //========================================================================
    //= OFormatDescriptionControl
    //========================================================================
    class OFormatDescriptionControl : public OCommonBehaviourControl, FormattedField
    {
    protected:
            virtual long                    PreNotify( NotifyEvent& rNEvt );

    public:
                                            OFormatDescriptionControl( Window* pParent, WinBits nWinStyle = WB_TABSTOP);

            virtual void                    SetProperty(const ::rtl::OUString &rString,sal_Bool bIsUnknown=sal_False);
            virtual ::rtl::OUString         GetProperty()const;

            virtual void                    SetFormatSupplier(const SvNumberFormatsSupplierObj* pSupplier);
    };

    //========================================================================
    //= FormatDescription
    //========================================================================
    struct FormatDescription
    {
        SvNumberFormatsSupplierObj*     pSupplier;
        sal_Int32                       nKey;
    };

    //========================================================================
    //= OFormattedNumericControl
    //========================================================================
    class OFormattedNumericControl : public OCommonBehaviourControl, FormattedField
    {
            sal_Int32                       m_nLastDecimalDigits;

    protected:
            virtual long                    PreNotify( NotifyEvent& rNEvt );

    public:
                                            OFormattedNumericControl( Window* pParent, WinBits nWinStyle = WB_TABSTOP);
                                            ~OFormattedNumericControl();

            virtual void                    SetProperty(const ::rtl::OUString &rString,sal_Bool bIsUnknown=sal_False);
            virtual ::rtl::OUString         GetProperty()const;

            virtual void                    SetFormatDescription(const FormatDescription& rDesc);

            // make some FormattedField methods available
            virtual void                    SetDecimalDigits(sal_uInt16 nPrecision) { FormattedField::SetDecimalDigits(nPrecision); m_nLastDecimalDigits = nPrecision; }
            virtual void                    SetDefaultValue(double dDef) { FormattedField::SetDefaultValue(dDef); }
            virtual void                    EnableEmptyField(sal_Bool bEnable) { FormattedField::EnableEmptyField(bEnable); }
            virtual void                    SetThousandsSep(sal_Bool bEnable) { FormattedField::SetThousandsSep(bEnable); }
    };

    //========================================================================
    //= OFileUrlControl
    //========================================================================
    typedef ::svt::FileURLBox OFileUrlControl_Base;
    class OFileUrlControl : public OCommonBehaviourControl, OFileUrlControl_Base
    {
    protected:
        virtual long                    PreNotify( NotifyEvent& rNEvt );

    public:
        OFileUrlControl( Window* pParent, WinBits nWinStyle = WB_TABSTOP);
        ~OFileUrlControl();

        virtual void                    SetProperty( const ::rtl::OUString& _rString, sal_Bool bIsUnknown = sal_False );
        virtual ::rtl::OUString         GetProperty() const;

        void                            SetBaseURL( const String& _rURL ) { OFileUrlControl_Base::SetBaseURL( _rURL ); }
    };

    //========================================================================
    //= TimeDurationInput
    //========================================================================
    class TimeDurationInput : public ONumericControl
    {
    public:
        TimeDurationInput( ::Window* pParent, WinBits nWinStyle = WB_TABSTOP);
        ~TimeDurationInput();

    protected:
        virtual void CustomConvert();
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_USERCONTROL_HXX_

<commit_msg>INTEGRATION: CWS pbrwuno (1.3.294); FILE MERGED 2005/10/05 07:14:42 fs 1.3.294.3: RESYNC: (1.3-1.4); FILE MERGED 2005/09/05 07:41:56 fs 1.3.294.2: #i53095# phase 3, part 1: introduced XPropertyControl and relatives, describing one control in the ObjectInspector, responsible for one property known issues: - rebuildPropertyUI can cause problems now: If the user clicks into   the control for property A, which causes property B to be committed,   which causes the UI for property A to be rebuilt, then this will   crash currently. Reason: rebuildPropertyUI now synchronously replaces   the VCL-Window of the rebuilt control, which is exactly the one   which is still in some MouseButtonDown-handler.   possible solutions:   - see if rebuiltPropertyUI can be obsoleted - handlers should be able     to just obtain the XPropertyControl from the PropertyUI, and     re-initialize the control. Shouldn't they?`   - make one of the steps in the chain (mouse-click, handler-call,     rebuildPropertyUI-callback) asynchronous. 2005/08/09 14:00:09 fs 1.3.294.1: #i53095# phase 1: - don't use strings to transver values between controls and introspectee, but Anys - first version of a dedicated property handler for form-component-related properties   (not yet completed) known regressions over previous phase: - handlers for events not yet implemented, thus some assertions - click handlers for form-component-related properties do not yet work,   thus the browse buttons mostly do not work<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: usercontrol.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2006-03-14 11:34:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_USERCONTROL_HXX_
#define _EXTENSIONS_PROPCTRLR_USERCONTROL_HXX_

#ifndef _EXTENSIONS_PROPCTRLR_COMMONCONTROL_HXX_
#include "commoncontrol.hxx"
#endif
#define _ZFORLIST_DECLARE_TABLE
#ifndef _FMTFIELD_HXX_
#include <svtools/fmtfield.hxx>
#endif
#ifndef SVTOOLS_FILEURLBOX_HXX
#include <svtools/fileurlbox.hxx>
#endif
#ifndef _EXTENSIONS_PROPCTRLR_STANDARDCONTROL_HXX_
#include "standardcontrol.hxx"
#endif

class SvNumberFormatsSupplierObj;

//............................................................................
namespace pcr
{
//............................................................................

    //========================================================================
    //= NumberFormatSampleField
    //========================================================================
    class NumberFormatSampleField : public ControlWindow< FormattedField >
    {
    private:
        typedef ControlWindow< FormattedField > BaseClass;

    public:
        NumberFormatSampleField( Window* _pParent, WinBits _nStyle )
            :BaseClass( _pParent, _nStyle )
        {
        }

        void SetFormatSupplier( const SvNumberFormatsSupplierObj* pSupplier );

    protected:
        virtual long PreNotify( NotifyEvent& rNEvt );
    };

    //========================================================================
    //= OFormatSampleControl
    //========================================================================
    typedef CommonBehaviourControl< ::com::sun::star::inspection::XPropertyControl, NumberFormatSampleField > OFormatSampleControl_Base;
    class OFormatSampleControl : public OFormatSampleControl_Base
    {
    public:
        OFormatSampleControl( Window* pParent, WinBits nWinStyle );

        // XPropertyControl
        virtual ::com::sun::star::uno::Any SAL_CALL getValue() throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setValue( const ::com::sun::star::uno::Any& _value ) throw (::com::sun::star::beans::IllegalTypeException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Type SAL_CALL getValueType() throw (::com::sun::star::uno::RuntimeException);

        inline void SetFormatSupplier( const SvNumberFormatsSupplierObj* _pSupplier )
        {
            getTypedControlWindow()->SetFormatSupplier( _pSupplier );
        }
    };

    //========================================================================
    //= FormatDescription
    //========================================================================
    struct FormatDescription
    {
        SvNumberFormatsSupplierObj*     pSupplier;
        sal_Int32                       nKey;
    };

    //========================================================================
    //= OFormattedNumericControl
    //========================================================================
    typedef CommonBehaviourControl< ::com::sun::star::inspection::XPropertyControl, ControlWindow< FormattedField > > OFormattedNumericControl_Base;
    class OFormattedNumericControl : public OFormattedNumericControl_Base
    {
    private:
        sal_Int32   m_nLastDecimalDigits;

    public:
        OFormattedNumericControl( Window* pParent, WinBits nWinStyle = WB_TABSTOP);

        // XPropertyControl
        virtual ::com::sun::star::uno::Any SAL_CALL getValue() throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setValue( const ::com::sun::star::uno::Any& _value ) throw (::com::sun::star::beans::IllegalTypeException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Type SAL_CALL getValueType() throw (::com::sun::star::uno::RuntimeException);

        void SetFormatDescription( const FormatDescription& rDesc );

        // make some FormattedField methods available
        void SetDecimalDigits(sal_uInt16 nPrecision) { getTypedControlWindow()->SetDecimalDigits(nPrecision); m_nLastDecimalDigits = nPrecision; }
        void SetDefaultValue(double dDef) { getTypedControlWindow()->SetDefaultValue(dDef); }
        void EnableEmptyField(sal_Bool bEnable) { getTypedControlWindow()->EnableEmptyField(bEnable); }
        void SetThousandsSep(sal_Bool bEnable) { getTypedControlWindow()->SetThousandsSep(bEnable); }

    protected:
        ~OFormattedNumericControl();
    };

    //========================================================================
    //= OFileUrlControl
    //========================================================================
    typedef CommonBehaviourControl< ::com::sun::star::inspection::XPropertyControl, ControlWindow< ::svt::FileURLBox > > OFileUrlControl_Base;
    class OFileUrlControl : public OFileUrlControl_Base
    {
    public:
        OFileUrlControl( Window* pParent, WinBits nWinStyle );

        // XPropertyControl
        virtual ::com::sun::star::uno::Any SAL_CALL getValue() throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setValue( const ::com::sun::star::uno::Any& _value ) throw (::com::sun::star::beans::IllegalTypeException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Type SAL_CALL getValueType() throw (::com::sun::star::uno::RuntimeException);

    protected:
        ~OFileUrlControl();
    };

    //========================================================================
    //= OTimeDurationControl
    //========================================================================
    class OTimeDurationControl : public ONumericControl
    {
    public:
        OTimeDurationControl( ::Window* pParent, WinBits nWinStyle );
        ~OTimeDurationControl();

    private:
        DECL_LINK( OnCustomConvert, MetricField* );
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_USERCONTROL_HXX_

<|endoftext|>