/* This file is part of the KDE project
   Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
   Copyright (C) 2003-2007 Jarosław Staniek <staniek@kde.org>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library 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
   Library General Public License for more details.

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

#ifndef KEXIRELATIONSSCROLLAREA_H
#define KEXIRELATIONSSCROLLAREA_H

#include <QScrollArea>
#include <QSet>
#include <QMutableSetIterator>
#include <QHash>
#include <QMutableHashIterator>
#include <QMouseEvent>
#include <QKeyEvent>

#include <KDbTableSchema>

#include "KexiRelationsConnection.h"
#include "KexiRelationsTableContainer.h"

class KDbConnection;

typedef QHash<QString, KexiRelationsTableContainer*> TablesHash;
typedef QMutableHashIterator<QString, KexiRelationsTableContainer*> TablesHashMutableIterator;
typedef QHash<QString, KexiRelationsTableContainer*>::ConstIterator TablesHashConstIterator;
typedef QMutableSetIterator<KexiRelationsConnection*> ConnectionSetMutableIterator;
typedef QSet<KexiRelationsConnection*>::ConstIterator ConnectionSetIterator;

//! A data structure describing connection
struct SourceConnection {
    QString masterTable;
    QString detailsTable;
    QString masterField;
    QString detailsField;
};

/*! @short Provides a view for displaying relations between database tables.

 It is currently used for two purposes:
 - displaying global database relations
 - displaying relations defined for a database query

 The class is for displaying only - retrieving data and updating data on the backend side is implemented
 in KexiRelationWidget, and more specifically in: Kexi Relation Part and Kexi Query Part.
*/
class KEXIRELATIONSVIEW_EXPORT KexiRelationsScrollArea : public QScrollArea
{
    Q_OBJECT

public:
    explicit KexiRelationsScrollArea(QWidget *parent = 0);
    virtual ~KexiRelationsScrollArea();

    //! \return a hash of added tables
    TablesHash* tables() const;

    /*! Adds a table \a t to the area. This changes only visual representation.
     If \a rect is valid, table widget geometry will be initialized.
     \return added table container or 0 on failure.
     */
    KexiRelationsTableContainer* addTableContainer(KDbTableSchema *t,
            const QRect &rect = QRect());

    /*! \return table container for table \a t. */
    KexiRelationsTableContainer * tableContainer(KDbTableSchema *t) const;

    //! Adds a connection \a _conn to the area. This changes only visual representation.
    void addConnection(const SourceConnection& _conn);

    void setReadOnly(bool);

    KexiRelationsConnection* selectedConnection() const;

    KexiRelationsTableContainer* focusedTableContainer() const;

    virtual QSize sizeHint() const override;

    const QSet<KexiRelationsConnection*>* relationsConnections() const;

    //! @internal Handles mouse press event for area widget
    void handleMousePressEvent(QMouseEvent *ev);

    //! @internal Handles paint event for area widget
    void handlePaintEvent(QPaintEvent *event);

Q_SIGNALS:
    void tableContextMenuRequest(const QPoint& pos);
    void connectionContextMenuRequest(const QPoint& pos);
    void emptyAreaContextMenuRequest(const QPoint& pos);
    void tableViewGotFocus();
    void connectionViewGotFocus();
    void emptyAreaGotFocus();
    void tableHidden(KDbTableSchema* t);
    void tablePositionChanged(KexiRelationsTableContainer*);
    void aboutConnectionRemove(KexiRelationsConnection*);

public Q_SLOTS:
    //! Clears current selection - table/query or connection
    void clearSelection();

    /*! Removes all tables and connections from the view.
     Does not emit signals like tableHidden(). */
    void clear();

    /*! Removes all connections from the view. */
    void removeAllConnections();

    /*! Hides all tables except \a tables. */
    void hideAllTablesExcept(QList<KDbTableSchema*>* tables);

    //! removes selected table or connection
    void removeSelectedObject();

    void setConnection(KDbConnection *conn);

protected Q_SLOTS:
    void containerMoved(KexiRelationsTableContainer *c);
    void slotListUpdate(QObject *s);
    void slotTableViewEndDrag();
    void slotTableViewGotFocus();
    void slotAutoScrollTimeout();

protected:
    void contentsMousePressEvent(QMouseEvent *ev);
    virtual void keyPressEvent(QKeyEvent *ev) override;
    virtual void contextMenuEvent(QContextMenuEvent* event) override;

    void hideTable(KexiRelationsTableContainer* tableView);
    void removeConnection(KexiRelationsConnection *conn);

    //! Removes current value of iterator \a it, also deleted the container object.
    void hideTableInternal(TablesHashMutableIterator* it);

    //! Removes current value of iterator \a it, also deleted the connection object.
    void removeConnectionInternal(ConnectionSetMutableIterator* it);

private:
    class Private;
    Private* const d;
};

#endif
