/* QAD - Qt ADvanced Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef SQL_TABLE_WIDGET_H #define SQL_TABLE_WIDGET_H #include "qad_sql_table_export.h" #include "qpiconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct QAD_SQL_TABLE_EXPORT ColumnProperties { enum DataType { Unknown, Int, Float, Chars, Text, Binary, Date, Time, DateTime }; ColumnProperties(const QString & table_, const QString & type_, const QString & name_, const QString & def_, bool auto_, bool prim_, bool option_); bool isRelation() const { return (!relation_key.isEmpty() && !relation_column.isEmpty()); } QString shortName() const { if (!isRelation()) return name; return relation_column; } QString fullName() const { if (!isRelation()) return table + "." + name; return (relation_table.isEmpty() ? "" : relation_table + ".") + relation_column; } DataType getType() const { if (!isRelation()) return type; return relation_type; } static DataType typeFromString(const QString & n); DataType type; int size; bool auto_increment; bool primary; bool optional; bool visible; bool is_text; QString table; QString name; QString relation_table; QString relation_key; QString relation_column; QList> relation_list; // DataType relation_type; int key_column; QString def; }; struct QAD_SQL_TABLE_EXPORT TableColumns { int mapColumn(int abs_ind) const { if (abs_ind <= 0 || abs_ind >= column_indexes.size() + 1) return 0; return column_indexes[abs_ind - 1]; } QVector column_indexes; QList columns; }; class QAD_SQL_TABLE_EXPORT SQLQueryModel: public QSqlQueryModel { Q_OBJECT public: explicit SQLQueryModel(QString & t, QString & conn, QList & cp, QVector & ci, QObject * parent = 0) : QSqlQueryModel(parent) , table_(t) , column_props(cp) , column_indexes(ci) , conn_name(conn) { ; } virtual QVariant data(const QModelIndex & item, int role = Qt::DisplayRole) const; protected: virtual Qt::ItemFlags flags(const QModelIndex &) const { return (Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); } virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); int mapColumn(int abs_ind) const { if (abs_ind <= 0 || abs_ind >= column_indexes.size() + 1) return 0; return column_indexes[abs_ind - 1]; } QString & table_; QList & column_props; QVector & column_indexes; QString & conn_name; signals: void updateTable(bool save_selection); void tableChanged(); }; class QAD_SQL_TABLE_EXPORT SQLUniEdit: public QWidget { Q_OBJECT public: explicit SQLUniEdit(const ColumnProperties & prop, const QString & conn_name, QWidget * parent = 0); ~SQLUniEdit() { for (int i = 0; i < w_.size(); ++i) deleteW(*w_[i]); } void setProp(const ColumnProperties & p); QString value(bool for_insert = false); void clear() { setValue(QVariant()); } private: void deleteW(QWidget * w) { if (w != 0) delete w; } void resizeW(QWidget * w) { if (w != 0) w->setGeometry(QRect(0, 0, width(), height())); } void resizeEvent(QResizeEvent *) { for (int i = 0; i < w_.size(); ++i) resizeW(*w_[i]); } bool eventFilter(QObject * o, QEvent * e); QLineEdit * wtext; QSpinBox * wint; QDoubleSpinBox * wfloat; QDateEdit * wdate; QTimeEdit * wtime; QDateTimeEdit * wdatetime; QComboBox * wrelation; QList w_; ColumnProperties prop_; QString connection_name; private slots: void value_text(QString value) { valueChanged(value); } void value_int(int value) { valueChanged(value); } void value_float(double value) { valueChanged(value); } void value_date(QDate value) { valueChanged(value); } void value_time(QTime value) { valueChanged(value); } void value_datetime(QDateTime value) { valueChanged(value); } public slots: void setValue(const QVariant & value); void updateRelation(); signals: void valueChanged(const QVariant &); }; class QAD_SQL_TABLE_EXPORT SQLNewEdit: public QWidget { Q_OBJECT friend class SQLTableWidget; public: explicit SQLNewEdit(const ColumnProperties & prop, const QString & conn_name, QWidget * parent = 0); ~SQLNewEdit() { delete line; delete check; } void setProp(const ColumnProperties & p); bool isEnabled() const { return check->isChecked(); } QString value() const { return line->value(true); } void clear() { line->clear(); } private: ColumnProperties prop_; SQLUniEdit * line; QCheckBox * check; }; class QAD_SQL_TABLE_EXPORT SQLFilterEdit: public QWidget { Q_OBJECT friend class SQLTableWidget; public: explicit SQLFilterEdit(const ColumnProperties & prop, const QString & conn_name, QWidget * parent = 0); ~SQLFilterEdit() { delete line; delete combo; } void setProp(const ColumnProperties & p) { prop_ = p; line->setProp(p); } QString filter() const; bool isEmpty() const { return line->value().isEmpty() || combo->currentIndex() == 0; } void clear(); private: ColumnProperties prop_; SQLUniEdit * line; QComboBox * combo; private slots: void value_changed() { if (combo->currentIndex() == 0) combo->setCurrentIndex(prop_.is_text ? 2 : 1); } public slots: signals: void filterChanged(); }; class QAD_SQL_TABLE_EXPORT SQLItemDelegate: public QStyledItemDelegate { Q_OBJECT public: explicit SQLItemDelegate(QList & cp, QVector & ci, bool & ro, const QString & conn_name, QObject * parent = 0); ~SQLItemDelegate() { ; } private: QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const; QString displayText(const QVariant & value, const QLocale & locale) const; void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; int mapColumn(int abs_ind) const { if (abs_ind <= 0 || abs_ind >= column_indexes.size() + 1) return 0; return column_indexes[abs_ind - 1]; } void setConnectionName(const QString & conn_name) { connection_name = conn_name; } QList & column_props; QVector & column_indexes; bool & read_only; QString connection_name; private slots: public slots: signals: }; namespace Ui { class SQLTableWidget; } class QAD_SQL_TABLE_EXPORT SQLTableWidget: public QWidget { Q_OBJECT Q_PROPERTY(QString tableName READ tableName WRITE setTableName) Q_PROPERTY(QString connectionName READ connectionName WRITE setConnectionName) Q_PROPERTY(bool lineNewVisible READ lineNewVisible WRITE setLineNewVisible) Q_PROPERTY(bool lineFilterVisible READ lineFilterVisible WRITE setLineFilterVisible) Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly) Q_PROPERTY(bool debugEnabled READ isDebugEnabled WRITE setDebugEnabled) friend class SQLItemDelegate; friend class SQLUniEdit; public: SQLTableWidget(QWidget * parent = 0); virtual ~SQLTableWidget(); bool isTableExists() const { return table_opened; } const QString & tableName() const { return table_; } QTableView * tableView(); bool readOnly() const { return read_only; } void setDebugEnabled(bool on) { debug = on; } bool isDebugEnabled() const { return debug; } const ColumnProperties * columnProperty(int index) const { if (index < 0 || index >= column_props.count()) return 0; return &(column_props[index]); } const ColumnProperties * columnProperty(const QString & name) const { return columnProperty(columnByName(name)); } const QList & columnProperties() const { return column_props; } QStringList columnNames() const { QStringList sl; foreach(const ColumnProperties & i, column_props) sl << i.name; return sl; } int columnsCount() const { return column_props.size(); } bool isColumnVisible(int ind) { if (!columnExists(ind)) return false; return column_props[ind].visible; } bool isColumnVisible(const QString & name) { if (!columnExists(name)) return false; return column_props[columnByName(name)].visible; } bool isColumnHidden(int ind) { if (!columnExists(ind)) return true; return !column_props[ind].visible; } bool isColumnHidden(const QString & name) { if (!columnExists(name)) return true; return !column_props[columnByName(name)].visible; } void setColumnVisible(int ind, bool visible); void setColumnVisible(const QString & name, bool visible) { col_vis[name] = visible; setColumnVisible(columnByName(name), visible); } void setColumnHidden(int ind, bool hidden) { setColumnVisible(ind, !hidden); } void setColumnHidden(const QString & name, bool hidden) { col_vis[name] = !hidden; setColumnVisible(columnByName(name), !hidden); } bool lineNewVisible() const; bool lineFilterVisible() const; bool addRelation(const QString & this_column, const QString & other_table, const QString & other_key, const QString & other_column); void addTranslation(const QString & file); void addFixedColumnTranslation(const QString & col_name, const QString & col_tr, const QString & col_tt = QString()); void fetchMore() { if (model) model->fetchMore(); } void fetchAll() { if (model) while (model->canFetchMore()) model->fetchMore(); } void selectId(int id); void setAdditionalActions(QList a); QSqlRecord headerRecord() const { if (model) return model->record(); return QSqlRecord(); } QSqlRecord currentRecord() const; void setCustomQuery(const QString & q); void setCustomColumnNames(const QStringList & cn) { custom_col_names = cn; updateTable(); } static bool isTableExists(const QString & table, const QString & conn_name = QLatin1String(QSqlDatabase::defaultConnection)) { return QSqlDatabase::database(conn_name).tables().contains(table, Qt::CaseInsensitive); } static bool executeScript(const QString & text, QSqlDatabase db = QSqlDatabase::database(), bool skip_errors = false, bool sqlite = false); static bool executeScriptFile(const QString & file, QSqlDatabase db = QSqlDatabase::database(), bool skip_errors = false, bool sqlite = false); static bool isConnectedToDatabase(const QString & conn_name = QLatin1String(QSqlDatabase::defaultConnection)) { return QSqlDatabase::database(conn_name, false).isOpen(); } static bool connectToDatabase(const QString & config, const QString & conn_name = QLatin1String(QSqlDatabase::defaultConnection)); QString connectionName() const { return connection_name; } private: static QString preprocessScript(QString text); bool eventFilter(QObject * o, QEvent * e); void timerEvent(QTimerEvent *); void changeEvent(QEvent * e); void stopTimer() { if (timer != 0) killTimer(timer); timer = 0; } bool checkTable(); QStringList getTableColumns(const QString & t); QString getColumnType(const QString & t, const QString & c); static QList> getColumnValues(const QString & t, const QString & k, const QString & c, const QString & conn_name); void setTableVisible(bool on); int mapColumn(int abs_ind) const { if (abs_ind <= 0 || abs_ind >= column_indexes.size() + 1) return 0; return column_indexes[abs_ind - 1]; } int columnByName(const QString & name) const { for (int i = 0; i < column_props.size(); ++i) if (column_props[i].name == name) return i; return -1; } bool columnExists(int index) const { return (index >= 0 && index < column_props.size()); } bool columnExists(const QString & name) const { for (int i = 0; i < column_props.size(); ++i) if (column_props[i].name == name) return true; return false; } QPair trColumn(const QString & n); QString tableNames(); QString columnNames(); QString columnFilters(); QString columnRelations(); Ui::SQLTableWidget * ui; QString table_, cquery, custom_query; QStringList custom_col_names; SQLQueryModel * model; // QAction act_add, act_del; QList column_props; QList column_news; QList column_filters; QVector column_indexes; QStringList wait_rels; QMenu popup_menu, popup_col, popup_filter; QElapsedTimer tm; QActionGroup filters_group; QAction * action_del; QList add_actions; QMap> translates, fixed_translates; QMap col_vis; int timer; bool filters_active, table_opened, read_only, first_update, debug; static QString _dir; QPoint pp; QString connection_name; public slots: void setTableName(const QString & t); void setLineNewVisible(bool on); void setLineFilterVisible(bool on); void setReadOnly(bool yes); void updateTable(bool save_selection = false); void setConnectionName(const QString & conn_name); private slots: void on_buttonAdd_clicked(); void on_actionFiltersClear_triggered(); void on_view_clicked(const QModelIndex & index); void header_sectionResized(int logicalIndex, int oldSize, int newSize); void header_sortIndicatorChanged(int logicalIndex, Qt::SortOrder order); void scrolled(int value); void del_triggered(); void column_triggered(bool on); signals: void rowClicked(int row); void recordClicked(QSqlRecord rec); void selectionChanged(); void tableChanged(); }; #endif // MYSQLTABLE_H