/***************************************************************************
 *   Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org>                  *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#ifndef DEVICE_GUI_H
#define DEVICE_GUI_H

#include <tqpushbutton.h>
#include <tqlayout.h>
#include <tqcombobox.h>
class TQListViewItem;
class TQCheckBox;
#include <ktextbrowser.h>
class TDEListView;

#include "common/gui/key_gui.h"
#include "common/gui/dialog.h"
#include "device_editor.h"
#include "devices/pic/base/pic.h"
namespace Programmer { class Group; }
namespace Tool { class Group; }

namespace DeviceChooser
{

enum Type { Choose, ChooseWithAuto };
class View;

BEGIN_DECLARE_ENUM(ListType)
  FamilyTree = 0, Flat
END_DECLARE_ENUM_STD(ListType)

//-----------------------------------------------------------------------------
class Config : public GenericConfig
{
public:
  Config() : GenericConfig("device_chooser") {}
  const Programmer::Group *programmerGroup();
  void writeProgrammerGroup(const Programmer::Group *group);
  const Tool::Group *toolGroup();
  void writeToolGroup(const Tool::Group *group);
};

//-----------------------------------------------------------------------------
template <typename Enum>
class EnumComboBox
{
public:
  EnumComboBox(const TQString &key, TQWidget *parent) : _key(key) {
    _combo = new TQComboBox(parent);
    for (Enum type; type<Enum::Nb_Types; ++type) _combo->insertItem(type.label());
    Config config;
    Enum type = config.readEnumEntry(key, Enum(Enum::Nb_Types));
    if ( type!=Enum::Nb_Types ) _combo->setCurrentItem(type.type());
  }
  EnumComboBox(const TQString &emptyLabel, const TQString &key, TQWidget *parent) : _key(key) {
    _combo = new TQComboBox(parent);
    _combo->insertItem(emptyLabel);
    for (Enum type; type<Enum::Nb_Types; ++type) _combo->insertItem(type.label());
    Config config;
    Enum type = config.readEnumEntry(key, Enum(Enum::Nb_Types));
    if ( type!=Enum::Nb_Types ) _combo->setCurrentItem(type.type()+1);
  }
  TQComboBox *combo() { return _combo; }
  Enum value() const {
    if ( _combo->count()==Enum::Nb_Types ) return typename Enum::Type(_combo->currentItem());
    if ( _combo->currentItem()==0 ) return Enum::Nb_Types;
    return typename Enum::Type(_combo->currentItem()-1);
  }
  void reset() { _combo->setCurrentItem(0); }
  void writeConfig() {
    Config config;
    config.writeEnumEntry(_key, value());
  }

private:
  TQString    _key;
  TQComboBox *_combo;
};

//-----------------------------------------------------------------------------
class Dialog : public ::Dialog
{
TQ_OBJECT
  
public:
  Dialog(const TQString &device, Type type, TQWidget *parent);
  virtual ~Dialog();

  TQString device() const;

private slots:
  void listDoubleClicked(TQListViewItem *item);
  void currentChanged(TQListViewItem *item);
  void deviceChange(const TQString &device);
  void updateList();
  void resetFilters();

private:
  bool _withAuto;
  KeyComboBox<TQString> *_programmerCombo, *_toolCombo;
  EnumComboBox<ListType>                 *_listTypeCombo;
  EnumComboBox<Device::MemoryTechnology> *_memoryCombo;
  EnumComboBox<Device::Status>           *_statusCombo;
  EnumComboBox<Pic::Feature>             *_featureCombo;
  TDEListView   *_listView;
  View        *_deviceView;

  void updateList(const TQString &device);
  const Programmer::Group *programmerGroup() const;
  const Tool::Group *toolGroup() const;
};

//-----------------------------------------------------------------------------
class ComboBox : public TQComboBox
{
TQ_OBJECT
  
public:
  ComboBox(bool withAuto, TQWidget *parent);
  void setDevice(const TQString &device, const Device::Data *data = 0);
  TQString device() const;
  bool withAuto() const { return _withAuto; }

private:
  bool _withAuto;
};

//-----------------------------------------------------------------------------
class Button : public TQWidget
{
TQ_OBJECT
  
public:
  Button(bool withAuto, TQWidget *parent);
  void setDevice(const TQString &device) { _combo->setDevice(device); }
  TQString device() const { return _combo->device(); }

signals:
  void changed();

private slots:
  void chooseDevice();

private:
  ComboBox *_combo;
};

//-----------------------------------------------------------------------------
class Browser : public KTextBrowser
{
TQ_OBJECT
  
public:
  Browser(TQWidget *parent);

signals:
  void deviceChanged(const TQString &device);

public slots:
  virtual void setSource(const TQString &name);
};

//-----------------------------------------------------------------------------
class View : public TabWidget
{
TQ_OBJECT
  
public:
  View(TQWidget *parent);
  void clear();
  void setText(const TQString &text);
  void setDevice(const TQString &name, bool cannotChangeDevice);

signals:
  void deviceChanged(const TQString &device);

private:
  TQMimeSourceFactory _msf;
  Browser *_info, *_memory, *_vfg, *_pins;
};

//-----------------------------------------------------------------------------
class Editor : public DeviceEditor
{
TQ_OBJECT
  
public:
  Editor(const TQString &title, const TQString &tag, TQWidget *parent);
  virtual bool isModified() const { return false; }
  virtual bool isReadOnly() const { return true; }
  virtual void addGui() {}
  virtual void removeGui() {}
  virtual void setFocus() {}

signals:
  void deviceChanged(const TQString &device);

private:
  virtual TQWidget *createView(const Device::Data *data, TQWidget *parent);
  virtual void setModifiedInternal(bool) {}
  virtual void setReadOnlyInternal(bool) {}
};

} // namespace

#endif