diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md
new file mode 100644
index 0000000000..4d054a0f2e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Bug_report.md
@@ -0,0 +1,38 @@
+---
+name: Report a bug
+about: Instructions on how to report pgModeler bugs. Before report any bug please
+ check if someone already has submited issues similiar to yours. Duplicated issues
+ will be ignored.
+
+---
+
+**Bug description**
+_A clear and concise description of what the bug is._
+
+**How to reproduce**
+_Please, if the bug can be reproduceable describe the steps in full details. If possible provide a sample model and/or a SQL dump for test purposes._
+
+**Expected behavior**
+_A clear and concise description of what you expected to happen._
+
+**Screenshots**
+_If applicable, add screenshots to help explain your problem._
+
+**Info about your desktop**
+ - OS:
+ - Version:
+ - Window manager:
+ - pgModeler version:
+ - Qt version:
+
+**Stacktrace / Debug info**
+_If pgModeler crashed after the bug raised attach the stacktrace below_
+
+```
+
+ Put the stacktrace here!
+
+```
+
+**Additional info**
+_Add any other information that you may find useful to help in the problem solving._
diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md
new file mode 100644
index 0000000000..219c04f5c1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Custom.md
@@ -0,0 +1,8 @@
+---
+name: General discussion
+about: For any discussion not related to bugs or feature requests please use this
+ one.
+
+---
+
+
diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md
new file mode 100644
index 0000000000..f3ad5eb15b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/Feature_request.md
@@ -0,0 +1,14 @@
+---
+name: Feature request / improvement
+about: Give your suggestions for improvements to this project.
+
+---
+
+**Feature description**
+_A clear and concise description of what the problem is._
+
+**Sample image**
+_If the feature requested is a visual improvement, please, attach some images to make it clear._
+
+**Additional info**
+_Add any other context or screenshots about the feature request here._
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6ac057b6c7..005b7d7ba2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,55 @@
Change Log
---------
+v0.9.1
+------
+Release date: May 14, 2018
+
+* [New] Added support to line selection by clicking and moving the mouse over the line numbers widget in any source code field.
+* [New] The validator now checks if the model has columns referencing spatial data types and creates the postgis extension automatically when fixing the model.
+* [New] Added support to RESTART IDENTITY on truncate tables in DatabaseExplorerWidget.
+* [New] Added an custom option checkbox in Messagebox for general purpose usage.
+* [New] Added support to diff operation in CLI.
+* [New] Added support to import database from CLI.
+* [New] Adding missing types regrole and regnamespace.
+* [Change] Improved the copy/duplicate operation in order to copy rules, index, trigger and policies together to their parents.
+* [Change] Added column names to the code completion widget used in the filter widget at DataManipulationForm.
+* [Change] Improved the SQLExecutionWidget in such way that it'll display large amount of data more quickly and consuming less memory.
+* [Change] Minor improvement in SQLExecutionWidget to show the amount of time took to run a query.
+* [Change] Minor improvement in the text find widgets in SQL tool in order to make them closable via dedicated button.
+* [Change] Improved the set tag operation in ModelWidget in order to cleanup the assigned tags to a set of objects.
+* [Change] Minor improvement on DatabaseExplorerWidget to show the rls attributes labels correctly in the attributes grid.
+* [Change] Refactored all the CLI options.
+* [Change] Minor change in Connection::generateConnectionString in order to put the dbname param in the start of the string.
+* [Change] Improved the performance of the row duplication action in DataManipulationForm.
+* [Change] Minor improvement in order to update the schemas boxes when the tables have their extended attributes box toggled.
+* [Change] Improved the performance of "Move to schema" operation.
+* [Change] Added an busy cursor while closing a model.
+* [Change] Improved the object selection in object finder.
+* [Change] Changed the behaviour of select and fade buttons in ObjectFinderWidget in such way to enable the user to select/fade the objects in the listing (or not included in the results).
+* [Fix] Fixed a bug when import identity columns in certain cases when the identity column was followed by another column which data type was not accepted for identity, e.g, text after smallint.
+* [Fix] Fixed the check boxes disabling when dealing with identifier relationships.
+* [Fix] Disabled the drag & drop for items in the side listing at ConfigurationForm.
+* [Fix] Fixed the tab behavior on comment box in all editing forms of database objects.
+* [Fix] Fixed the catalog query for user defined types.
+* [Fix] Fixed the import of user defined types which names contains uppercase characters.
+* [Fix] Minor typo fixes in CLI.
+* [Fix] Fix window scaling on HiDPI/Retina screens.
+* [Fix] Minor fix in Connection::getConnectionId in order to omit port when that parameter is not configured in the connection.
+* [Fix] Fixed a bug in ModelExportHelper that was failing to remane the database when the command appeared.
+* [Fix] Fixed a bug in CollationWidget that was referencing the collation attributes LC_??? using the wrong constant.
+* [Fix] Fixed the behaviour of the message box that warns about the need of validate the model prior to export, save or diff. Now rejecting the dialog (i.e. closing it) will be considered that the user wants to proceed with the pending operation even with an invalid model.
+* [Fix] Fixed the import of comments for constraints,triggers, index and rules.
+* [Fix] The value input in BulkDataEditWidget will be focused as soon as the widget appears.
+* [Fix] Fixed a bug in the aggregate import process.
+* [Fix] Minor fix in DataManipulationForm to avoid the generation of a where clause when the filter is filled only with spaces.
+* [Fix] Minor fix in the magnfier tool to use the same render hints as the canvas viewport.
+* [Fix] Fixed a bug in the diff process that was trying to recreate the whole database when the "Force recreation" option was set.
+* [Fix] Fixed a bug when showing the source of tables in DatabaseExplorerWidget when these objects have permissions assigned.
+* [Fix] Adjusting tables position when the parent schema is moved and the alignment to grid is enabled.
+* [Fix] Minor fix in the CLI menu.
+* [Fix] Fixed the saving process for large models by stopping the threads related to temp models saving while the model file is being written.
+
v0.9.1-beta1
------
Release date: April 6, 2018
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 3840d69f48..f77074d8b2 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -1,50 +1,49 @@
-v0.9.1-beta1
+v0.9.1
------
-Release date: April 6, 2018
-Changes since: v0.9.1-beta
-
-Summary: finally we've reached the last beta release of the 0.9.1! This time pgModeler brings important fixes and new features requested long ago which are finally implemented in experimental stage.
-
-The first new feature we have in this release is the support to multiples relationships for the same pair of tables. In previous versions, pgModeler would refuse to create a second relationship between the tables A and B. From now on, pgModeler will accept the creation of one-to-many and many-to-many relationships linking A and B more then once. For the other kinds of relationships (generalization, copy, one-to-one) the old rule is still valid: only one relationship per table pair is accepted.
-
-Some missing features of PostgreSQL are present in this version too being them: row level security (RLS) and identity columns. For RLS, introduced in PostgreSQL 9.5, we have added the related options to toggle it in tables (ENABLE|FORCE RLS) as well the support to policy objects which are the main part of this new security modality. The identity columns, introduced in PostgreSQL 10, are now fully supported by pgModeler and you can make use of them from the column editing form.
-
-Other new feature is the support to multiple check constraints by domains. Actually, this is more a patch than a new feature because pgModeler was unaware that domains could support more than one check constraint, so we have fixed that now.
-
-Now, talking about changes, we fixed an old missinterpretation of the PostgreSQL's documentations by changing the way extensions are stored in the database model. Previously, this kind of objects were stored at schemas level but the right way to store them is at database level. So now instead of seeing extensions in the schema's subtree you'll see them in the database subtree. All validation rules, export, import and diff processes were fixed in such way to reflect the right way to treat these objects.
-
-Another important change, and that one is related to an annoying behaviour of the tool, is that pgModeler will silently ignore the absence of the plugins folder and proceed with the normal startup avoiding the display of a message box regarding the missing folder and automatically disabling the plugins search mechanism.
-
-In the fixes section, we've included a patch for a bug that was causing recurrent crashes on macOS when the user tried to load a second model file making almost impossible the working on two or more database models at once. Also, we've patched the reverse engineering in such way to avoid the duplication of data types related to tables, sequences and views which was causing problems in the validation process. Another fix was done in the diff process that was generating a malformed DROP command for extensions.
-
-The set of changes of this release has 47 entries between new features, changes, improvements and bug fixes. Below we highlight some of them, for the complete list, please, consider reading the CHANGELOG.md.
-
-* [New] Added the ability to create multiples one-to-many and many-to-many relatationships between the same pair of tables.
-* [New] Added the ability to use more special ascii chars in the middle of object names.
-* [New] Added support to multi line comments in UI.
-* [New] Added full support to row level security (RLS), including export, import and diff of this kind of object.
-* [New] Added support to bulk data editing in DataManipulationForm.
-* [New] Added an option to diff process to force the generation of DROP commands for columns and constraints even if the missing objects need to be preserved. This is useful to work with partial models and the user need to remove columns/constraints and preserve the rest of objects.
-* [New] Added support to identity columns (PostgreSQL 10).
-* [New] Added the support to BYPASSRLS option on roles.
-* [New] Added support to IS_TEMPLATE and ALLOW_CONNECTIONS options in database object.
-* [New] Added the procedures to fix old style domains in CLI.
-* [New] Added support to multiple check constraint in domains.
-* [New] Added support to sort items alphabetically (ascending) or by oid in DatabaseExplorerWidget.
-* [Change] Changed the input mode of the password field in ConnectionsConfigWidget in order to hide the passwords in the form. NOTE: the passwords are still in plain text in the config file.
-* [Change] Moved extensions from schema level to database level in order to reproduce better the PostgreSQL's behavior.
-* [Change] In GeneralConfigWidget when restoring default settings the default settings for syntax highlight are restored as well.
-* [Change] pgModeler will not try to create the plugins path anymore. This will avoid constant error messages during startup. Now, it'll silently ignore the absence of that folder and skip the plugin loading.
-* [Change] Improved the source editing in external application. The use is informed about the app running state and the contents for the source editor field are locked until the user closes the external app.
-* [Fix] Fixed the query catalog for built-in types to include the types related to domains.
-* [Fix] Fixed the extension creation, allowing only one instance of the named extension per database no matter the schema used to allocate its children objects.
-* [Fix] Fixed a bug when dropping Functions in DatabaseExplorerWidget.
-* [Fix] Fixed a bug that was causing the disabling of connections for database models created prior to 0.9.1-beta1.
-* [Fix] Fixed a bug on import process that was wrongly creating types derivated from tables/sequence/views causing duplication problems during validation.
-* [Fix] Fixed a crash on macOs when opening a second model.
-* [Fix] Fixed an issue in diff process that was generating a malformed DROP command for extensions.
-* [Fix] Fixed the diff for domains which contain multiple check constraints.
-* [Fix] Fixed a bug that was not selecting the correct spatial type in the widget.
-* [Fix] Fixed a conflict of shortcuts in DatabaseExplorerWidget. Now F5 updates a leaf/subtree and Alt+F5 performs quick refresh of the tree.
-* [Fix] Fixed a problem with sqlexecutionwidget.ui that is not building properly in Qt 5.10.
+Release date: May 14, 2018
+Changes since: v0.9.1-beta1
+
+Summary: after eight months of hard work we finally have the stable release 0.9.1. This version is a mark in the pgModeler's development and so important as the release 0.8.2 in terms of improvements because it brought features requested long ago and that will make pgModeler even better to work with, being some of them: crow's foot notation support, multiple relationships for the same table pair, support to row level security, identity columns and much more.
+
+For this release specifically (considering only the work after 0.9.1-beta1), the golden rule was to fix bugs, adjust the current features and introduce few new things and thus was done: 21 bug fixes, 14 changes/improvements and 7 new features.
+
+The majority of new features are related to the CLI which received the ability to import and diff databases which can make it even better to integrate to automtated deployment processess or run quick tasks over models or databases without the need to open pgModeler's GUI.
+
+Some important improvements were done in the overall performance of the SQL tool. The query execution and results display are a lot better now being quicker and less eager in terms of memory consumption avoiding crashes when querying large tables. The data manipulation also received a patch that makes the row duplication more efficient.
+
+Now, for the fixes, another patch was introduced in order to resize correctly dialogs in HiDPI/Retina displays. Several reverse engineering bugs were fixes and now databases are imported more precisely compared to previous releases. Lastly, a bug that seems to happen only on macOS while dealing with large models is finally fixed and was related to some running threads messing around with the main process avoiding it to correctly save the model and causing hang ups sometimes.
+
+The whole set of changes of this release (considering the alpha and beta stages) has 152 entries being 43 new features, 47 changes/improvements and 62 bug fixes. Below we highlight some of news for the work since 0.9.1-beta1, for the complete list of changes, please, take a look into the CHANGELOG.md.
+
+* [New] Added support to line selection by clicking and moving the mouse over the line numbers widget in any source code field.
+* [New] The validator now checks if the model has columns referencing spatial data types and creates the postgis extension automatically when fixing the model.
+* [New] Added support to RESTART IDENTITY on truncate tables in DatabaseExplorerWidget.
+* [New] Added support to diff operation in CLI.
+* [New] Added support to import database from CLI.
+* [New] Adding missing types regrole and regnamespace.
+* [Change] Improved the copy/duplicate operation in order to copy rules, index, trigger and policies together to their parents.
+* [Change] Added column names to the code completion widget used in the filter widget at DataManipulationForm.
+* [Change] Improved the SQLExecutionWidget in such way that it'll display large amount of data more quickly and consuming less memory.
+* [Change] Minor improvement in SQLExecutionWidget to show the amount of time took to run a query.
+* [Change] Minor improvement in the text find widgets in SQL tool in order to make them closable via dedicated button.
+* [Change] Improved the set tag operation in ModelWidget in order to cleanup the assigned tags to a set of objects.
+* [Change] Refactored all the CLI options.
+* [Change] Improved the performance of the row duplication action in DataManipulationForm.
+* [Change] Improved the performance of "Move to schema" operation.
+* [Change] Changed the behaviour of select and fade buttons in ObjectFinderWidget in such way to enable the user to select/fade the objects in the listing (or not included in the results).
+* [Fix] Fixed a bug when import identity columns in certain cases when the identity column was followed by another column which data type was not accepted for identity, e.g, text after smallint.
+* [Fix] Fixed the tab behavior on comment box in all editing forms of database objects.
+* [Fix] Fixed the catalog query for user defined types.
+* [Fix] Fixed the import of user defined types which names contains uppercase characters.
+* [Fix] Fix window scaling on HiDPI/Retina screens.
+* [Fix] Fixed a bug in ModelExportHelper that was failing to remane the database when the command appeared.
+* [Fix] Fixed a bug in CollationWidget that was referencing the collation attributes LC_??? using the wrong constant.
+* [Fix] Fixed the behaviour of the message box that warns about the need of validate the model prior to export, save or diff. Now rejecting the dialog (i.e. closing it) will be considered that the user wants to proceed with the pending operation even with an invalid model.
+* [Fix] Fixed the import of comments for constraints,triggers, index and rules.
+* [Fix] Fixed a bug in the aggregate import process.
+* [Fix] Minor fix in DataManipulationForm to avoid the generation of a where clause when the filter is filled only with spaces.
+* [Fix] Minor fix in the magnfier tool to use the same render hints as the canvas viewport.
+* [Fix] Fixed a bug in the diff process that was trying to recreate the whole database when the "Force recreation" option was set.
+* [Fix] Fixed a bug when showing the source of tables in DatabaseExplorerWidget when these objects have permissions assigned.
+* [Fix] Fixed the saving process for large models by stopping the threads related to temp models saving while the model file is being written.
diff --git a/conf/defaults/pgmodeler.conf b/conf/defaults/pgmodeler.conf
index 0d280ddfa2..38405c783c 100644
--- a/conf/defaults/pgmodeler.conf
+++ b/conf/defaults/pgmodeler.conf
@@ -37,8 +37,7 @@
align-objs-to-grid="true"
min-object-opacity="10"
history-max-length="1000"
- use-curved-lines="true"
- max-result-rows="20000"/>
+ use-curved-lines="true"/>
diff --git a/conf/dtd/pgmodeler.dtd b/conf/dtd/pgmodeler.dtd
index cdea216667..51768e16d0 100644
--- a/conf/dtd/pgmodeler.dtd
+++ b/conf/dtd/pgmodeler.dtd
@@ -44,7 +44,6 @@
-
diff --git a/conf/pgmodeler.conf b/conf/pgmodeler.conf
index 0d280ddfa2..38405c783c 100644
--- a/conf/pgmodeler.conf
+++ b/conf/pgmodeler.conf
@@ -37,8 +37,7 @@
align-objs-to-grid="true"
min-object-opacity="10"
history-max-length="1000"
- use-curved-lines="true"
- max-result-rows="20000"/>
+ use-curved-lines="true"/>
diff --git a/conf/schemas/pgmodeler.sch b/conf/schemas/pgmodeler.sch
index d68dd6ad17..74715d9844 100644
--- a/conf/schemas/pgmodeler.sch
+++ b/conf/schemas/pgmodeler.sch
@@ -48,10 +48,6 @@ $sp [ QFrame
}
AboutWidget > QFrame > QLabel#title_lbl,
-AboutWidget > QFrame > QLabel#slogan_lbl,
AboutWidget > QFrame > QLabel#about_lbl,
-AboutWidget > QFrame > QLabel#pgmodeler_ver_lbl,
AboutWidget > QFrame > QLabel#build_lbl,
AboutWidget > QFrame > QLabel#copyright_lbl {
- color: #000;
+ color: #000;
+}
+
+AboutWidget > QFrame > QLabel#pgmodeler_ver_lbl {
+ color: #4C7DD0;
}
DonateWidget > QFrame > QLabel#title_lbl,
@@ -436,23 +438,8 @@ QTabWidget#models_tbw > QTabBar::tab:selected {
margin-top: 0px;
}
-/*QSplitter#h_splitter::handle {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFAFA , stop: 1 #E0E0E0);
-} */
-
-/*QSplitter#h_splitter_opr_objs::handle {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFAFA , stop: 1 #E0E0E0);
- border-left: 1px solid #404040;
-}*/
-
-/*QSplitter#v_splitter::handle, QSplitter#v_splitter1::handle,QSplitter#v_splitter2::handle {
- background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFAFA , stop: 1 #E0E0E0);
-} */
-
SQLToolWidget > QWidget#bg_frame {
- /*background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FAFAFA , stop: 1 #E0E0E0);*/
- /*border-bottom: 1px solid #d0d0d0;
- border-top: transparent;*/
+
}
/* Floating hint widget member of HintTextWidget */
@@ -471,7 +458,6 @@ HintTextWidget > QWidget
HintTextWidget > QWidget > QLabel
{
color: #0000c0;
- /*font-size: 8pt;*/
}
QTabWidget#databases_tbw > QTabBar::close-button {
diff --git a/libobjrenderer/src/baseobjectview.cpp b/libobjrenderer/src/baseobjectview.cpp
index 396741816e..1a21cd06a7 100644
--- a/libobjrenderer/src/baseobjectview.cpp
+++ b/libobjrenderer/src/baseobjectview.cpp
@@ -638,10 +638,12 @@ double BaseObjectView::getFontFactor(void)
double BaseObjectView::getScreenDpiFactor(void)
{
- double factor = qApp->screens().at(qApp->desktop()->screenNumber(qApp->activeWindow()))->logicalDotsPerInch() / 96.0f;
+ QScreen *screen = qApp->screens().at(qApp->desktop()->screenNumber(qApp->activeWindow()));
+ double factor = screen->logicalDotsPerInch() / 96.0f;
+ double pixel_ratio = screen->devicePixelRatio();
if(factor < 1)
return (1);
- return(factor);
+ return(factor * pixel_ratio);
}
diff --git a/libobjrenderer/src/basetableview.cpp b/libobjrenderer/src/basetableview.cpp
index 1e50e9beda..362d3f76f2 100644
--- a/libobjrenderer/src/basetableview.cpp
+++ b/libobjrenderer/src/basetableview.cpp
@@ -356,13 +356,14 @@ void BaseTableView::__configureObject(float width)
QPen pen = ext_attribs_body->pen();
float py = 0;
float factor = qApp->screens().at(qApp->desktop()->screenNumber(qApp->activeWindow()))->logicalDotsPerInch() / 96.0f;
+ float pixel_ratio = qApp->screens().at(qApp->desktop()->screenNumber(qApp->activeWindow()))->devicePixelRatio();
ext_attribs_toggler->setVisible(true);
ext_attribs_tog_arrow->setVisible(true);
ext_attribs_toggler->setPen(pen);
ext_attribs_toggler->setBrush(ext_attribs_body->brush());
- ext_attribs_toggler->setRect(QRectF(0, 0, width, 12 * factor));
+ ext_attribs_toggler->setRect(QRectF(0, 0, width, 12 * factor * pixel_ratio));
if(!tab->isExtAttribsHidden())
{
@@ -383,14 +384,14 @@ void BaseTableView::__configureObject(float width)
if(!tab->isExtAttribsHidden())
{
pol.append(QPointF(0,0));
- pol.append(QPointF(-5 * factor, 6 * factor));
- pol.append(QPointF(5 * factor, 6 * factor));
+ pol.append(QPointF(-5 * factor * pixel_ratio, 6 * factor * pixel_ratio));
+ pol.append(QPointF(5 * factor * pixel_ratio, 6 * factor * pixel_ratio));
}
else
{
- pol.append(QPointF(0,6 * factor));
- pol.append(QPointF(-5 * factor, 0));
- pol.append(QPointF(5 * factor, 0));
+ pol.append(QPointF(0,6 * factor * pixel_ratio));
+ pol.append(QPointF(-5 * factor * pixel_ratio, 0));
+ pol.append(QPointF(5 * factor * pixel_ratio, 0));
}
QLinearGradient grad(QPointF(0,0),QPointF(0,1));
diff --git a/libparsers/src/parsersattributes.cpp b/libparsers/src/parsersattributes.cpp
index dd0f7709ba..3a3068e96d 100644
--- a/libparsers/src/parsersattributes.cpp
+++ b/libparsers/src/parsersattributes.cpp
@@ -291,7 +291,6 @@ namespace ParsersAttributes {
MATERIALIZED=QString("materialized"),
MAX_CONNECTIONS=QString("max-connections"),
MAX_VALUE=QString("max-value"),
- MAX_RESULT_ROWS=QString("max-result-rows"),
MEMBER_ROLES=QString("member-roles"),
MEMBER=QString("member"),
MERGES=QString("merges"),
@@ -410,6 +409,7 @@ namespace ParsersAttributes {
RENAME=QString("rename"),
REPLICATION=QString("replication"),
RESTRICTION_FUNC=QString("restriction"),
+ RESTART_SEQ=QString("restart-seq"),
RETURN_TABLE=QString("return-table"),
RETURN_TYPE=QString("return-type"),
RETURNS_SETOF=QString("returns-setof"),
diff --git a/libparsers/src/parsersattributes.h b/libparsers/src/parsersattributes.h
index d06ce98284..c58b148a6f 100644
--- a/libparsers/src/parsersattributes.h
+++ b/libparsers/src/parsersattributes.h
@@ -306,7 +306,6 @@ namespace ParsersAttributes {
MATERIALIZED,
MAX_CONNECTIONS,
MAX_VALUE,
- MAX_RESULT_ROWS,
MEMBER_ROLES,
MEMBER,
MERGES,
@@ -424,6 +423,7 @@ namespace ParsersAttributes {
RELATIONSHIP,
RENAME,
REPLICATION,
+ RESTART_SEQ,
RESTRICTION_FUNC,
RETURN_TABLE,
RETURN_TYPE,
diff --git a/libpgmodeler/src/databasemodel.cpp b/libpgmodeler/src/databasemodel.cpp
index 201a197e27..898d38e564 100644
--- a/libpgmodeler/src/databasemodel.cpp
+++ b/libpgmodeler/src/databasemodel.cpp
@@ -8101,7 +8101,10 @@ void DatabaseModel::getObjectReferences(BaseObject *object, vector
{
col=tab->getColumn(i1);
- if(!col->isAddedByRelationship() && col->getType()==ptr_pgsqltype)
+ if(!col->isAddedByRelationship() &&
+ (col->getType()==ptr_pgsqltype ||
+ //Special case for postgis extension
+ (obj_type == OBJ_EXTENSION && object->getName() == QString("postgis") && col->getType().isGiSType())))
{
refer=true;
refs.push_back(col);
@@ -8808,6 +8811,15 @@ void DatabaseModel::__getObjectReferences(BaseObject *object, vector &objects)
+{
+ for(auto &obj : objects)
+ {
+ if(BaseGraphicObject::isGraphicObject(obj->getObjectType()))
+ dynamic_cast(obj)->setModified(true);
+ }
+}
+
void DatabaseModel::setObjectsModified(vector types)
{
ObjectType obj_types[]={OBJ_TABLE, OBJ_VIEW,
diff --git a/libpgmodeler/src/databasemodel.h b/libpgmodeler/src/databasemodel.h
index 11406b0ad2..f0cde903cb 100644
--- a/libpgmodeler/src/databasemodel.h
+++ b/libpgmodeler/src/databasemodel.h
@@ -561,10 +561,13 @@ class DatabaseModel: public QObject, public BaseObject {
meaning that ALL objects directly or inderectly linked to the 'object' are retrieved. */
void __getObjectReferences(BaseObject *object, vector &refs, bool exclude_perms=false);
- /*! \brief Marks the graphical objects as modified forcing their redraw. User can specify only a set of
+ /*! \brief Marks the graphical objects of the provided types as modified forcing their redraw. User can specify only a set of
graphical objects to be marked */
void setObjectsModified(vector types={});
+ //! \brief Marks the graphical objects in the list as modified forcing their redraw.
+ void setObjectsModified(vector &objects);
+
/*! \brief Marks the objects with code invalidated forcing their code regeneration. User can specify only a set of
graphical objects to be marked */
void setCodesInvalidated(vector types={});
diff --git a/libpgmodeler_ui/libpgmodeler_ui.pro b/libpgmodeler_ui/libpgmodeler_ui.pro
index e0eacb7103..48455934a5 100644
--- a/libpgmodeler_ui/libpgmodeler_ui.pro
+++ b/libpgmodeler_ui/libpgmodeler_ui.pro
@@ -112,7 +112,8 @@ SOURCES += src/mainwindow.cpp \
src/sceneinfowidget.cpp \
src/bulkdataeditwidget.cpp \
src/policywidget.cpp \
- src/objectstablewidget.cpp
+ src/objectstablewidget.cpp \
+ src/resultsetmodel.cpp
HEADERS += src/mainwindow.h \
@@ -212,7 +213,8 @@ HEADERS += src/mainwindow.h \
src/sceneinfowidget.h \
src/bulkdataeditwidget.h \
src/policywidget.h \
- src/objectstablewidget.h
+ src/objectstablewidget.h \
+ src/resultsetmodel.h
FORMS += ui/mainwindow.ui \
ui/textboxwidget.ui \
diff --git a/libpgmodeler_ui/src/aboutwidget.cpp b/libpgmodeler_ui/src/aboutwidget.cpp
index 5c36d6391d..7e01b667c3 100644
--- a/libpgmodeler_ui/src/aboutwidget.cpp
+++ b/libpgmodeler_ui/src/aboutwidget.cpp
@@ -31,14 +31,13 @@ AboutWidget::AboutWidget(QWidget *parent) : QWidget(parent)
drop_shadow->setBlurRadius(30);
this->setGraphicsEffect(drop_shadow);
- pgmodeler_ver_lbl->setText(QString("v%1").arg(GlobalAttributes::PGMODELER_VERSION));
- build_num_lbl->setText(GlobalAttributes::PGMODELER_BUILD_NUMBER);
-
- for(int row=0; row < contributors_tab->rowCount(); row++)
- contributors_tab->item(row, 2)->setToolTip(contributors_tab->item(row, 2)->text().replace(QString("; "), QString(";\n")));
+ PgModelerUiNS::configureWidgetFont(title_lbl, PgModelerUiNS::HUGE_FONT_FACTOR);
+ PgModelerUiNS::configureWidgetFont(pgmodeler_ver_lbl, PgModelerUiNS::HUGE_FONT_FACTOR);
+ PgModelerUiNS::configureWidgetFont(build_lbl, PgModelerUiNS::BIG_FONT_FACTOR);
+ PgModelerUiNS::configureWidgetFont(build_num_lbl, PgModelerUiNS::BIG_FONT_FACTOR);
- contributors_tab->sortByColumn(0, Qt::AscendingOrder);
- contributors_tab->resizeColumnsToContents();
+ pgmodeler_ver_lbl->setText(QString("v%1 ").arg(GlobalAttributes::PGMODELER_VERSION));
+ build_num_lbl->setText(QString("%1 Qt %2").arg(GlobalAttributes::PGMODELER_BUILD_NUMBER).arg(QT_VERSION_STR));
connect(hide_tb, &QToolButton::clicked, this,
[&](){
@@ -46,12 +45,6 @@ AboutWidget::AboutWidget(QWidget *parent) : QWidget(parent)
emit s_visibilityChanged(false);
});
- PgModelerUiNS::configureWidgetFont(title_lbl, PgModelerUiNS::HUGE_FONT_FACTOR);
- PgModelerUiNS::configureWidgetFont(slogan_lbl, PgModelerUiNS::BIG_FONT_FACTOR);
- PgModelerUiNS::configureWidgetFont(pgmodeler_ver_lbl, PgModelerUiNS::HUGE_FONT_FACTOR);
- PgModelerUiNS::configureWidgetFont(build_lbl, PgModelerUiNS::MEDIUM_FONT_FACTOR);
- PgModelerUiNS::configureWidgetFont(build_num_lbl, PgModelerUiNS::MEDIUM_FONT_FACTOR);
-
float factor = BaseObjectView::getScreenDpiFactor();
this->adjustSize();
this->resize(this->minimumWidth() * factor, this->minimumHeight() * factor);
diff --git a/libpgmodeler_ui/src/appearanceconfigwidget.cpp b/libpgmodeler_ui/src/appearanceconfigwidget.cpp
index 15104d7136..6bfb5c8178 100644
--- a/libpgmodeler_ui/src/appearanceconfigwidget.cpp
+++ b/libpgmodeler_ui/src/appearanceconfigwidget.cpp
@@ -384,7 +384,7 @@ void AppearanceConfigWidget::restoreDefaults(void)
{
try
{
- BaseConfigWidget::restoreDefaults(GlobalAttributes::OBJECTS_STYLE_CONF);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::OBJECTS_STYLE_CONF, false);
this->loadConfiguration();
setConfigurationChanged(true);
}
diff --git a/libpgmodeler_ui/src/baseconfigwidget.cpp b/libpgmodeler_ui/src/baseconfigwidget.cpp
index 8a94221c0b..e211d74e14 100644
--- a/libpgmodeler_ui/src/baseconfigwidget.cpp
+++ b/libpgmodeler_ui/src/baseconfigwidget.cpp
@@ -99,7 +99,7 @@ void BaseConfigWidget::saveConfiguration(const QString &conf_id, map%1!").arg(bkp_filename), Messagebox::INFO_ICON);
diff --git a/libpgmodeler_ui/src/baseconfigwidget.h b/libpgmodeler_ui/src/baseconfigwidget.h
index 572f584f5f..9225a529ba 100644
--- a/libpgmodeler_ui/src/baseconfigwidget.h
+++ b/libpgmodeler_ui/src/baseconfigwidget.h
@@ -55,8 +55,9 @@ class BaseConfigWidget: public QWidget {
//! \brief Get a configuratoin key from the xml parser
void getConfigurationParams(map &config_params, const vector &key_attribs);
- //! \brief Restore the configuration specified by conf_in loading them from the original file (conf/defaults)
- void restoreDefaults(const QString &conf_id);
+ /*! \brief Restore the configuration specified by conf_in loading them from the original file (conf/defaults)
+ * The silent parameter indicates that the restoration should not emit a message box informing the restoration sucess */
+ void restoreDefaults(const QString &conf_id, bool silent);
//! \brief Adds a parameter to the specified configuration parameters set
static void addConfigurationParam(map &config_params, const QString ¶m, const attribs_map &attribs);
diff --git a/libpgmodeler_ui/src/baseform.cpp b/libpgmodeler_ui/src/baseform.cpp
index 309c2b35b7..6899100882 100644
--- a/libpgmodeler_ui/src/baseform.cpp
+++ b/libpgmodeler_ui/src/baseform.cpp
@@ -46,10 +46,12 @@ void BaseForm::resizeForm(QWidget *widget)
screen_id = qApp->desktop()->screenNumber(qApp->activeWindow());
QScreen *screen=qApp->screens().at(screen_id);
float dpi_factor = 0;
+ float pixel_ratio = 0;
max_w = screen->size().width() * 0.70;
max_h = screen->size().height() * 0.70;
dpi_factor = screen->logicalDotsPerInch() / 96.0f;
+ pixel_ratio = screen->devicePixelRatio();
if(dpi_factor <= 1.01f)
dpi_factor = 1.0f;
@@ -102,8 +104,8 @@ void BaseForm::resizeForm(QWidget *widget)
((buttons_lt->contentsMargins().top() +
buttons_lt->contentsMargins().bottom()) * 6);
- curr_w *= dpi_factor;
- curr_h *= dpi_factor;
+ curr_w *= dpi_factor * pixel_ratio;
+ curr_h *= dpi_factor * pixel_ratio;
if(curr_w > screen->size().width())
curr_w = screen->size().width() * 0.80;
diff --git a/libpgmodeler_ui/src/codecompletionwidget.cpp b/libpgmodeler_ui/src/codecompletionwidget.cpp
index 5324a4f59e..737dd633a0 100644
--- a/libpgmodeler_ui/src/codecompletionwidget.cpp
+++ b/libpgmodeler_ui/src/codecompletionwidget.cpp
@@ -35,7 +35,7 @@ CodeCompletionWidget::CodeCompletionWidget(QPlainTextEdit *code_field_txt, bool
name_list=new QListWidget(completion_wgt);
name_list->setSpacing(2);
name_list->setIconSize(QSize(16,16));
- name_list->setSortingEnabled(true);
+ name_list->setSortingEnabled(false);
persistent_chk=new QCheckBox(completion_wgt);
persistent_chk->setText(trUtf8("Make &persistent"));
@@ -258,6 +258,12 @@ void CodeCompletionWidget::insertCustomItems(const QStringList &names, const QSt
}
}
+void CodeCompletionWidget::insertCustomItems(const QStringList &names, const QString &tooltip, ObjectType obj_type)
+{
+ for(auto &name : names)
+ insertCustomItem(name, tooltip, QPixmap(PgModelerUiNS::getIconPath(obj_type)));
+}
+
void CodeCompletionWidget::clearCustomItems(void)
{
custom_items.clear();
diff --git a/libpgmodeler_ui/src/codecompletionwidget.h b/libpgmodeler_ui/src/codecompletionwidget.h
index 347104e912..d8faf7a3d5 100644
--- a/libpgmodeler_ui/src/codecompletionwidget.h
+++ b/libpgmodeler_ui/src/codecompletionwidget.h
@@ -112,11 +112,14 @@ class CodeCompletionWidget: public QWidget
highlighter uses an different configuration */
void configureCompletion(DatabaseModel *db_model, SyntaxHighlighter *syntax_hl=nullptr, const QString &keywords_grp=QString("keywords"));
- //! \brief Inserts a custom named item on the list with a custom icon. Custom item will be always appear at the beggining of the list
+ //! \brief Inserts a custom named item on the list with a custom icon. Custom item will always appear at the beggining of the list
void insertCustomItem(const QString &name, const QString &tooltip, const QPixmap &icon);
- //! \brief Inserts several custom named item on the list with a custom icon. Custom item will be always appear at the beggining of the list
+ //! \brief Inserts several custom named item on the list with a custom icon. Custom item will always appear at the beggining of the list
void insertCustomItems(const QStringList &names, const QStringList &tooltips, const QPixmap &icon);
+
+//! \brief Inserts several custom named items on the list with an icon related to the obj_type. Custom item will always appear at the beggining of the list
+ void insertCustomItems(const QStringList &names, const QString &tooltip, ObjectType obj_type);
//! \brief Clear the custom added items
void clearCustomItems(void);
diff --git a/libpgmodeler_ui/src/connectionsconfigwidget.cpp b/libpgmodeler_ui/src/connectionsconfigwidget.cpp
index 6af970c210..6a764e5dda 100644
--- a/libpgmodeler_ui/src/connectionsconfigwidget.cpp
+++ b/libpgmodeler_ui/src/connectionsconfigwidget.cpp
@@ -451,7 +451,7 @@ void ConnectionsConfigWidget::restoreDefaults(void)
try
{
//Restore the default connection config file
- BaseConfigWidget::restoreDefaults(GlobalAttributes::CONNECTIONS_CONF);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::CONNECTIONS_CONF, false);
//Remove all connections
while(connections_cmb->count() > 0)
diff --git a/libpgmodeler_ui/src/databaseexplorerwidget.cpp b/libpgmodeler_ui/src/databaseexplorerwidget.cpp
index 1f47174fe2..d93cc10784 100644
--- a/libpgmodeler_ui/src/databaseexplorerwidget.cpp
+++ b/libpgmodeler_ui/src/databaseexplorerwidget.cpp
@@ -93,7 +93,8 @@ const attribs_map DatabaseExplorerWidget::attribs_i18n {
{SERVER_VERSION, QT_TR_NOOP("Server version")}, {IDENT_FILE, QT_TR_NOOP("Ident file")}, {PASSWORD_ENCRYPTION, QT_TR_NOOP("Password encryption")},
{CONNECTION, QT_TR_NOOP("Connection ID")}, {SERVER_PID, QT_TR_NOOP("Server PID")}, {SERVER_PROTOCOL, QT_TR_NOOP("Server protocol")},
{REFERRERS, QT_TR_NOOP("Referrers")}, {IDENTITY_TYPE, QT_TR_NOOP("Identity")}, {COMMAND, QT_TR_NOOP("Command")},
- {USING_EXP, QT_TR_NOOP("USING expr.")}, {CHECK_EXP, QT_TR_NOOP("CHECK expr.")}, {ROLES, QT_TR_NOOP("Roles")}
+ {USING_EXP, QT_TR_NOOP("USING expr.")}, {CHECK_EXP, QT_TR_NOOP("CHECK expr.")}, {ROLES, QT_TR_NOOP("Roles")},
+ {RLS_ENABLED, QT_TR_NOOP("RLS enabled")}, {RLS_FORCED, QT_TR_NOOP("RLS forced")}
};
DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent)
@@ -509,7 +510,9 @@ void DatabaseExplorerWidget::formatOperatorAttribs(attribs_map &attribs)
void DatabaseExplorerWidget::formatTableAttribs(attribs_map &attribs)
{
formatBooleanAttribs(attribs, { ParsersAttributes::OIDS,
- ParsersAttributes::UNLOGGED });
+ ParsersAttributes::UNLOGGED,
+ ParsersAttributes::RLS_ENABLED,
+ ParsersAttributes::RLS_FORCED});
formatOidAttribs(attribs, { ParsersAttributes::PARENTS }, OBJ_TABLE, true);
}
@@ -1265,6 +1268,7 @@ void DatabaseExplorerWidget::truncateTable(QTreeWidgetItem *item, bool cascade)
else
msg=trUtf8("Do you really want to cascade truncate the table %1? This action will truncate all the tables that depends on it?").arg(obj_name);
+ msg_box.setCustomOptionText(trUtf8("Also restart sequences"));
msg_box.show(msg, Messagebox::CONFIRM_ICON, Messagebox::YES_NO_BUTTONS);
if(msg_box.result()==QDialog::Accepted)
@@ -1276,7 +1280,7 @@ void DatabaseExplorerWidget::truncateTable(QTreeWidgetItem *item, bool cascade)
attribs[ParsersAttributes::SQL_OBJECT]=BaseObject::getSQLName(OBJ_TABLE);
attribs[ParsersAttributes::SIGNATURE]=sch_name + QString(".\"%1\"").arg(obj_name);
attribs[ParsersAttributes::CASCADE]=(cascade ? ParsersAttributes::_TRUE_ : "");
-
+ attribs[ParsersAttributes::RESTART_SEQ]=(msg_box.isCustomOptionChecked() ? ParsersAttributes::_TRUE_ : "");
//Generate the truncate command
schparser.ignoreEmptyAttributes(true);
diff --git a/libpgmodeler_ui/src/databaseimporthelper.cpp b/libpgmodeler_ui/src/databaseimporthelper.cpp
index 8743cae066..3030f94852 100644
--- a/libpgmodeler_ui/src/databaseimporthelper.cpp
+++ b/libpgmodeler_ui/src/databaseimporthelper.cpp
@@ -1670,8 +1670,8 @@ void DatabaseImportHelper::createTable(attribs_map &attribs)
{
/* Building the type name prepending the schema name in order to search it on
the user defined types list at PgSQLType class */
- type_name=getObjectName(types[type_oid][ParsersAttributes::SCHEMA], true);
- type_name+=QString(".") + types[type_oid][ParsersAttributes::NAME];
+ type_name=BaseObject::formatName(getObjectName(types[type_oid][ParsersAttributes::SCHEMA], true), false);
+ type_name+=QString(".") + BaseObject::formatName(types[type_oid][ParsersAttributes::NAME], false);
is_type_registered=PgSQLType::isRegistered(type_name, dbmodel);
}
else
@@ -1695,6 +1695,7 @@ void DatabaseImportHelper::createTable(attribs_map &attribs)
type_def=getDependencyObject(itr->second[ParsersAttributes::TYPE_OID], OBJ_DOMAIN);
}
+ col.setIdentityType(BaseType::null);
col.setType(PgSQLType::parseString(type_name));
col.setNotNull(!itr->second[ParsersAttributes::NOT_NULL].isEmpty());
col.setComment(itr->second[ParsersAttributes::COMMENT]);
diff --git a/libpgmodeler_ui/src/datamanipulationform.cpp b/libpgmodeler_ui/src/datamanipulationform.cpp
index 64ab8b381e..0e7394af5e 100644
--- a/libpgmodeler_ui/src/datamanipulationform.cpp
+++ b/libpgmodeler_ui/src/datamanipulationform.cpp
@@ -374,6 +374,9 @@ void DataManipulationForm::retrieveData(void)
paste_tb->setEnabled(!qApp->clipboard()->text().isEmpty() &&
table_cmb->currentData().toUInt() == OBJ_TABLE &&
!col_names.isEmpty());
+
+ code_compl_wgt->clearCustomItems();
+ code_compl_wgt->insertCustomItems(col_names, trUtf8("Column"), OBJ_COLUMN);
}
catch(Exception &e)
{
diff --git a/libpgmodeler_ui/src/generalconfigwidget.cpp b/libpgmodeler_ui/src/generalconfigwidget.cpp
index 80bd4c378a..b9dada0f9d 100644
--- a/libpgmodeler_ui/src/generalconfigwidget.cpp
+++ b/libpgmodeler_ui/src/generalconfigwidget.cpp
@@ -86,8 +86,6 @@ GeneralConfigWidget::GeneralConfigWidget(QWidget * parent) : BaseConfigWidget(pa
connect(tab_width_chk, SIGNAL(toggled(bool)), tab_width_spb, SLOT(setEnabled(bool)));
connect(tab_width_chk, SIGNAL(toggled(bool)), this, SLOT(updateFontPreview()));
- connect(max_result_rows_chk, SIGNAL(toggled(bool)), max_result_rows_spb, SLOT(setEnabled(bool)));
-
connect(font_preview_txt, SIGNAL(cursorPositionChanged()), this, SLOT(updateFontPreview()));
connect(select_editor_btn, SIGNAL(clicked(bool)), this, SLOT(selectSourceEditor()));
@@ -129,7 +127,6 @@ GeneralConfigWidget::GeneralConfigWidget(QWidget * parent) : BaseConfigWidget(pa
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::SOURCE_EDITOR_APP]=QString();
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::UI_LANGUAGE]=QString();
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::USE_CURVED_LINES]=QString();
- config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::MAX_RESULT_ROWS]=QString();
simp_obj_creation_ht=new HintTextWidget(simp_obj_creation_hint, this);
simp_obj_creation_ht->setText(simple_obj_creation_chk->statusTip());
@@ -182,9 +179,6 @@ GeneralConfigWidget::GeneralConfigWidget(QWidget * parent) : BaseConfigWidget(pa
use_curved_lines_ht=new HintTextWidget(use_curved_lines_hint, this);
use_curved_lines_ht->setText(use_curved_lines_chk->statusTip());
- max_result_rows_ht=new HintTextWidget(max_result_rows_hint, this);
- max_result_rows_ht->setText(max_result_rows_spb->statusTip());
-
selectPaperSize();
QList chk_boxes=this->findChildren();
@@ -308,11 +302,6 @@ void GeneralConfigWidget::loadConfiguration(void)
min_obj_opacity_spb->setValue(config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::MIN_OBJECT_OPACITY].toUInt());
- int value = config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::MAX_RESULT_ROWS].toInt();
- max_result_rows_chk->setChecked(value > 0);
- max_result_rows_spb->setEnabled(value > 0);
- max_result_rows_spb->setValue(value);
-
margin=config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::PAPER_MARGIN].split(',');
custom_size=config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::PAPER_CUSTOM_SIZE].split(',');
@@ -433,7 +422,6 @@ void GeneralConfigWidget::saveConfiguration(void)
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::MIN_OBJECT_OPACITY]=QString::number(min_obj_opacity_spb->value());
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::USE_PLACEHOLDERS]=(use_placeholders_chk->isChecked() ? ParsersAttributes::_TRUE_ : QString());
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::HISTORY_MAX_LENGTH]=QString::number(history_max_length_spb->value());
- config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::MAX_RESULT_ROWS]=QString::number(max_result_rows_chk->isChecked() ? max_result_rows_spb->value() : 0);
config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::USE_CURVED_LINES]=(use_curved_lines_chk->isChecked() ? ParsersAttributes::_TRUE_ : QString());
ObjectsScene::getGridOptions(show_grid, align_grid, show_delim);
@@ -552,7 +540,6 @@ void GeneralConfigWidget::applyConfiguration(void)
MainWindow::setConfirmValidation(confirm_validation_chk->isChecked());
BaseObjectView::setPlaceholderEnabled(use_placeholders_chk->isChecked());
SQLExecutionWidget::setSQLHistoryMaxLength(history_max_length_spb->value());
- SQLExecutionWidget::setMaxResultRows(max_result_rows_chk->isChecked()? max_result_rows_spb->value() : 0);
fnt.setFamily(config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::CODE_FONT]);
fnt.setPointSize(fnt_size);
@@ -570,9 +557,10 @@ void GeneralConfigWidget::restoreDefaults(void)
{
try
{
- BaseConfigWidget::restoreDefaults(GlobalAttributes::GENERAL_CONF);
- BaseConfigWidget::restoreDefaults(GlobalAttributes::XML_HIGHLIGHT_CONF);
- BaseConfigWidget::restoreDefaults(GlobalAttributes::SQL_HIGHLIGHT_CONF);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::GENERAL_CONF, false);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::XML_HIGHLIGHT_CONF, true);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::SQL_HIGHLIGHT_CONF, true);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::UI_STYLE_CONF, true);
this->loadConfiguration();
this->applyConfiguration();
setConfigurationChanged(true);
diff --git a/libpgmodeler_ui/src/linenumberswidget.cpp b/libpgmodeler_ui/src/linenumberswidget.cpp
index 11db826fd8..eb8ffb76b6 100644
--- a/libpgmodeler_ui/src/linenumberswidget.cpp
+++ b/libpgmodeler_ui/src/linenumberswidget.cpp
@@ -19,14 +19,23 @@
#include "linenumberswidget.h"
#include
#include
+#include "exception.h"
QColor LineNumbersWidget::font_color=Qt::lightGray;
QColor LineNumbersWidget::bg_color=Qt::black;
LineNumbersWidget::LineNumbersWidget(QPlainTextEdit * parent) : QWidget(parent)
{
- first_line=line_count=0;
+ if(!parent)
+ throw Exception(ERR_ASG_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__);
+
+ parent_edt = qobject_cast(parent);
+ first_line=line_count=start_sel_pos=0;
dy=0;
+ has_selection = false;
+ start_sel_line = -1;
+
+ connect(parent_edt, SIGNAL(selectionChanged()), this, SLOT(update()));
}
void LineNumbersWidget::drawLineNumbers(unsigned first_line, unsigned line_count, int dy)
@@ -51,8 +60,20 @@ void LineNumbersWidget::setColors(const QColor &font_color, const QColor &bg_col
void LineNumbersWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
- int y=dy, height=fontMetrics().height();
+ int y = dy, height = 0;
unsigned last_line=first_line + line_count;
+ QFont font = painter.font();
+ unsigned fs_line = 0, ls_line = 0;
+ QTextCursor cursor = parent_edt->textCursor();
+
+ if(cursor.hasSelection())
+ {
+ QTextCursor start = cursor, end = cursor;
+ start.setPosition(cursor.selectionStart(), QTextCursor::MoveAnchor);
+ fs_line = start.blockNumber();
+ end.setPosition(cursor.selectionEnd(), QTextCursor::KeepAnchor);
+ ls_line = end.blockNumber();
+ }
//Repaint the widget to clear previous drawn numbers
painter.fillRect(event->rect(), bg_color);
@@ -61,15 +82,77 @@ void LineNumbersWidget::paintEvent(QPaintEvent *event)
//Draw line numbers
for(unsigned lin=first_line; lin < last_line; lin++)
{
- painter.drawText(0, y, this->width(), fontMetrics().height(),
- Qt::AlignHCenter, QString::number(lin));
+ font.setBold(cursor.hasSelection() && lin-1 >= fs_line && lin-1 <= ls_line);
+ height = QFontMetrics(font).height();
+ painter.setFont(font);
+
+ if(font.bold())
+ {
+ painter.setBrush(bg_color.dark(150));
+ painter.setPen(Qt::transparent);
+ painter.drawRect(QRect(-1, y, this->width() + 1, height));
+ painter.setPen(font_color.light(180));
+ }
+ else
+ painter.setPen(font_color);
+
+ painter.drawText(0, y, this->width(), height, Qt::AlignHCenter, QString::number(lin));
y+=height;
}
}
-QColor LineNumbersWidget::getBackgroundColor(void)
+void LineNumbersWidget::mousePressEvent(QMouseEvent *event)
{
- return(LineNumbersWidget::bg_color);
+ if(event->buttons() == Qt::LeftButton && !has_selection)
+ {
+ QTextCursor cursor = parent_edt->cursorForPosition(QPoint(0, event->pos().y()));
+
+ has_selection = true;
+ cursor.select(QTextCursor::LineUnderCursor);
+ parent_edt->setTextCursor(cursor);
+ start_sel_line = cursor.blockNumber();
+ start_sel_pos = cursor.position();
+ }
+}
+
+void LineNumbersWidget::mouseMoveEvent(QMouseEvent *event)
+{
+ if(event->buttons() == Qt::LeftButton && has_selection)
+ {
+ QTextCursor cursor = parent_edt->cursorForPosition(QPoint(0, event->pos().y())),
+ curr_cursor = parent_edt->textCursor();
+
+ //If the user wants selects lines below the first
+ if(start_sel_line < cursor.blockNumber())
+ {
+ cursor.movePosition(QTextCursor::EndOfLine);
+ curr_cursor.setPosition(cursor.position(), QTextCursor::KeepAnchor);
+ parent_edt->setTextCursor(curr_cursor);
+ }
+ //If the user wants selects lines above the first
+ else if(start_sel_line > cursor.blockNumber())
+ {
+ curr_cursor.setPosition(start_sel_pos);
+ curr_cursor.movePosition(QTextCursor::EndOfLine);
+ curr_cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, curr_cursor.position() - cursor.position());
+ parent_edt->setTextCursor(curr_cursor);
+ }
+ else
+ {
+ cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
+ parent_edt->setTextCursor(cursor);
+ }
+
+ this->update();
+ }
}
+void LineNumbersWidget::mouseReleaseEvent(QMouseEvent *)
+{
+ has_selection = false;
+}
+QColor LineNumbersWidget::getBackgroundColor(void)
+{
+ return(LineNumbersWidget::bg_color);
+}
diff --git a/libpgmodeler_ui/src/linenumberswidget.h b/libpgmodeler_ui/src/linenumberswidget.h
index ac83e76c25..420f63b2c6 100644
--- a/libpgmodeler_ui/src/linenumberswidget.h
+++ b/libpgmodeler_ui/src/linenumberswidget.h
@@ -32,6 +32,10 @@ class LineNumbersWidget : public QWidget {
private:
Q_OBJECT
+ QPlainTextEdit *parent_edt;
+
+ bool has_selection;
+
//! \brief The first line number that must be drawn
unsigned first_line,
@@ -41,6 +45,8 @@ class LineNumbersWidget : public QWidget {
//! \brief The y axis increment to start drawn the line number
int dy;
+ int start_sel_line, start_sel_pos;
+
//! \brief Font color for drawn line numbers
static QColor font_color,
@@ -49,9 +55,12 @@ class LineNumbersWidget : public QWidget {
protected:
void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *);
public:
- explicit LineNumbersWidget(QPlainTextEdit *parent = 0);
+ explicit LineNumbersWidget(QPlainTextEdit *parent);
/*! \brief Draw the lines starting from 'first_line' and stoping at fisrt_line + line_count -1.
The dy param. defines an initial Y translation before drawn lines */
diff --git a/libpgmodeler_ui/src/messagebox.cpp b/libpgmodeler_ui/src/messagebox.cpp
index efa66df897..4120492e6a 100644
--- a/libpgmodeler_ui/src/messagebox.cpp
+++ b/libpgmodeler_ui/src/messagebox.cpp
@@ -31,8 +31,10 @@ Messagebox::Messagebox(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f)
connect(show_errors_tb,SIGNAL(clicked()),this,SLOT(showExceptionList()));
connect(show_errors_tb,SIGNAL(toggled(bool)),show_raw_info_tb,SLOT(setVisible(bool)));
connect(show_raw_info_tb,SIGNAL(toggled(bool)),this,SLOT(showExceptionList(void)));
- show_errors_tb->setVisible(false);
+
show_raw_info_tb->setVisible(false);
+ error_show_btns_wgt->setVisible(false);
+ custom_option_chk->setVisible(false);
}
void Messagebox::handleYesOkClick(void)
@@ -62,6 +64,17 @@ bool Messagebox::isCancelled(void)
return(cancelled);
}
+void Messagebox::setCustomOptionText(const QString &text)
+{
+ custom_option_chk->setVisible(!text.isEmpty());
+ custom_option_chk->setText(text);
+}
+
+bool Messagebox::isCustomOptionChecked(void)
+{
+ return(custom_option_chk->isChecked());
+}
+
void Messagebox::showExceptionList(void)
{
if(show_errors_tb->isChecked())
@@ -188,7 +201,7 @@ void Messagebox::show(const QString &title, const QString &msg, unsigned icon_ty
this->setWindowTitle(aux_title);
this->objs_group_wgt->setCurrentIndex(0);
this->show_errors_tb->setChecked(false);
- this->show_errors_tb->setVisible((exceptions_trw->topLevelItemCount() > 0));
+ error_show_btns_wgt->setVisible((exceptions_trw->topLevelItemCount() > 0));
showExceptionList();
this->resize(this->minimumWidth(), this->minimumHeight());
diff --git a/libpgmodeler_ui/src/messagebox.h b/libpgmodeler_ui/src/messagebox.h
index d549e1fb15..69228e1c36 100644
--- a/libpgmodeler_ui/src/messagebox.h
+++ b/libpgmodeler_ui/src/messagebox.h
@@ -67,6 +67,9 @@ class Messagebox: public QDialog, public Ui::Messagebox {
bool isCancelled(void);
+ void setCustomOptionText(const QString &text);
+ bool isCustomOptionChecked(void);
+
private slots:
void handleYesOkClick(void);
void handleNoCancelClick(void);
diff --git a/libpgmodeler_ui/src/modelvalidationhelper.cpp b/libpgmodeler_ui/src/modelvalidationhelper.cpp
index f53c0ff65a..cd0d404ee9 100644
--- a/libpgmodeler_ui/src/modelvalidationhelper.cpp
+++ b/libpgmodeler_ui/src/modelvalidationhelper.cpp
@@ -46,7 +46,8 @@ ModelValidationHelper::~ModelValidationHelper(void)
void ModelValidationHelper::generateValidationInfo(unsigned val_type, BaseObject *object, vector refs)
{
if(!refs.empty() ||
- (val_type==ValidationInfo::BROKEN_REL_CONFIG &&
+ val_type==ValidationInfo::MISSING_EXTENSION ||
+ (val_type==ValidationInfo::BROKEN_REL_CONFIG &&
std::find(inv_rels.begin(), inv_rels.end(), object)==inv_rels.end()))
{
//Configures a validation info
@@ -71,7 +72,7 @@ void ModelValidationHelper::resolveConflict(ValidationInfo &info)
//Resolving broken references by swaping the object ids
if(info.getValidationType()==ValidationInfo::BROKEN_REFERENCE ||
- info.getValidationType()==ValidationInfo::SP_OBJ_BROKEN_REFERENCE)
+ info.getValidationType()==ValidationInfo::SP_OBJ_BROKEN_REFERENCE)
{
BaseObject *info_obj=info.getObject(), *aux_obj=nullptr;
unsigned obj_id=info_obj->getObjectId();
@@ -190,6 +191,13 @@ void ModelValidationHelper::resolveConflict(ValidationInfo &info)
refs.pop_back();
}
}
+ //Resolving the absence of postgis extension
+ else if(info.getValidationType()==ValidationInfo::MISSING_EXTENSION && !db_model->getExtension(QString("postgis")))
+ {
+ Extension *extension = new Extension();
+ extension->setName(QString("postgis"));
+ db_model->addExtension(extension);
+ }
}
catch(Exception &e)
{
@@ -274,13 +282,14 @@ void ModelValidationHelper::validateModel(void)
map > dup_objects;
map >::iterator mitr;
QString name, signal_msg=QString("`%1' (%2)");
+ bool postgis_exists = db_model->getObjectIndex(QString("postgis"), OBJ_EXTENSION) >= 0;
warn_count=error_count=progress=0;
val_infos.clear();
valid_canceled=false;
/* Step 1: Validating broken references. This situation happens when a object references another
- whose id is smaller than the id of the first one. */
+ which id is smaller than the id of the first one. */
for(i=0; i < count && !valid_canceled; i++)
{
obj_list=db_model->getObjectList(types[i]);
@@ -508,8 +517,31 @@ void ModelValidationHelper::validateModel(void)
i++; mitr++;
}
+ // Step 3: Checking if columns of any table is using GiS data types and the postgis extension is not created.
+ if(!postgis_exists)
+ {
+ obj_list=db_model->getObjectList(OBJ_TABLE);
+ itr=obj_list->begin();
+ i=0;
+
+ while(itr!=obj_list->end() && !valid_canceled)
+ {
+ table = dynamic_cast(*itr);
+ itr++;
+
+ for(auto &obj : *table->getObjectList(OBJ_COLUMN))
+ {
+ col = dynamic_cast(obj);
+
+ if(col->getType().isGiSType())
+ generateValidationInfo(ValidationInfo::MISSING_EXTENSION, col, {});
+ }
- /* Step 3: Checking if there are some invalidated relationship. In some cases, specially with identifier and generalization relationships,
+ progress=30 + ((i/static_cast(obj_list->size()))*20);
+ }
+ }
+
+ /* Step 4: Checking if there are some invalidated relationship. In some cases, specially with identifier and generalization relationships,
the columns aren't correctly propagated due to creation order and special behavior of those objects. Thus, in order to
keep all columns synchonized it is need to make this step and change the relationship creation order if needed. This step is executed
only when there is no validation infos generated because for each broken relationship there is the need to do a revalidation of all relationships */
@@ -520,7 +552,7 @@ void ModelValidationHelper::validateModel(void)
while(itr!=obj_list->end() && !valid_canceled)
{
- progress=30 + ((i/static_cast(obj_list->size()))*20);
+ progress=40 + ((i/static_cast(obj_list->size()))*20);
if(dynamic_cast(*itr)->isInvalidated())
generateValidationInfo(ValidationInfo::BROKEN_REL_CONFIG, *itr, {});
@@ -529,7 +561,6 @@ void ModelValidationHelper::validateModel(void)
}
}
-
if(!valid_canceled && !fix_mode)
{
//Step 3 (optional): Validating the SQL code onto a local DBMS.
@@ -575,8 +606,9 @@ void ModelValidationHelper::applyFixes(void)
{
if(!validate_rels)
validate_rels=(val_infos[i].getValidationType()==ValidationInfo::BROKEN_REFERENCE ||
- val_infos[i].getValidationType()==ValidationInfo::SP_OBJ_BROKEN_REFERENCE ||
- val_infos[i].getValidationType()==ValidationInfo::NO_UNIQUE_NAME);
+ val_infos[i].getValidationType()==ValidationInfo::SP_OBJ_BROKEN_REFERENCE ||
+ val_infos[i].getValidationType()==ValidationInfo::NO_UNIQUE_NAME ||
+ val_infos[i].getValidationType()==ValidationInfo::MISSING_EXTENSION);
/* Checking if a broken relatinship is found, when this is the case all the pending validation info
will not be analyzed until no broken relationship is found */
diff --git a/libpgmodeler_ui/src/modelvalidationwidget.cpp b/libpgmodeler_ui/src/modelvalidationwidget.cpp
index 9319a73cff..9017267c01 100644
--- a/libpgmodeler_ui/src/modelvalidationwidget.cpp
+++ b/libpgmodeler_ui/src/modelvalidationwidget.cpp
@@ -266,6 +266,16 @@ void ModelValidationWidget::updateValidation(ValidationInfo val_info)
.arg(val_info.getObject()->getObjectId()));
else if(val_info.getValidationType()==ValidationInfo::SQL_VALIDATION_ERR)
label->setText(trUtf8("SQL validation failed due to error(s) below. NOTE: These errors does not invalidates the model but may affect operations like export and diff."));
+ else if(val_info.getValidationType() == ValidationInfo::MISSING_EXTENSION)
+ {
+ Column *col = dynamic_cast(val_info.getObject());
+
+ label->setText(trUtf8("The column %1 on %2 (%3) is referencing the geospatial data type %4 but the postgis extension is not present in the model!")
+ .arg(col->getName())
+ .arg(col->getParentTable()->getSignature(true))
+ .arg(BaseObject::getTypeName(OBJ_TABLE))
+ .arg(~col->getType()));
+ }
else
label->setText(val_info.getErrors().at(0));
@@ -306,6 +316,11 @@ void ModelValidationWidget::updateValidation(ValidationInfo val_info)
PgModelerUiNS::createOutputTreeItem(output_trw, trUtf8("HINT: try to swap the relationship by another ones that somehow are linked to it through generated columns or constraints to solve this issue. Note that other objects may be lost in the swap process."),
QPixmap(PgModelerUiNS::getIconPath("msgbox_alerta")), item);
}
+ else if(val_info.getValidationType()==ValidationInfo::MISSING_EXTENSION)
+ {
+ PgModelerUiNS::createOutputTreeItem(output_trw, trUtf8("HINT: Create the extension in the model or let it be created by applying the needed fixes."),
+ QPixmap(PgModelerUiNS::getIconPath("msgbox_alerta")), item);
+ }
else
{
//Listing the referrer object on output pane
diff --git a/libpgmodeler_ui/src/modelwidget.cpp b/libpgmodeler_ui/src/modelwidget.cpp
index 000c455c1d..128f436c64 100644
--- a/libpgmodeler_ui/src/modelwidget.cpp
+++ b/libpgmodeler_ui/src/modelwidget.cpp
@@ -2006,11 +2006,13 @@ void ModelWidget::setTag(void)
{
op_id=op_list->registerObject(obj, Operation::OBJECT_MODIFIED, -1);
tab->setTag(dynamic_cast(tag));
- tab->setModified(true);
}
}
op_list->finishOperationChain();
+ db_model->setObjectsModified(selected_objects);
+ scene->clearSelection();
+
emit s_objectModified();
}
catch(Exception &e)
@@ -2210,9 +2212,9 @@ void ModelWidget::copyObjects(bool duplicate_mode)
vector deps;
BaseObject *object=nullptr;
TableObject *tab_obj=nullptr;
- Table *table=nullptr;
+ BaseTable *table=nullptr;
Constraint *constr=nullptr;
- ObjectType types[]={ OBJ_TRIGGER, OBJ_INDEX, OBJ_CONSTRAINT };
+ ObjectType types[]={ OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX, OBJ_CONSTRAINT, OBJ_POLICY };
unsigned i, type_id, count;
Messagebox msg_box;
@@ -2254,11 +2256,11 @@ void ModelWidget::copyObjects(bool duplicate_mode)
/* Copying the special objects (which references columns added by relationship) in order
to be correclty created when pasted */
- if(object->getObjectType()==OBJ_TABLE)
+ if(object->getObjectType()==OBJ_TABLE || object->getObjectType() == OBJ_VIEW)
{
- table=dynamic_cast(object);
+ table=dynamic_cast(object);
- for(type_id=0; type_id < 3; type_id++)
+ for(type_id=0; type_id < 4; type_id++)
{
count=table->getObjectCount(types[type_id]);
@@ -2271,14 +2273,16 @@ void ModelWidget::copyObjects(bool duplicate_mode)
columns added by relationship. Case the object is a constraint, it cannot be a primary key because
this type of constraint is treated separetely by relationships */
if(!tab_obj->isAddedByRelationship() &&
- ((constr &&
+ (!constr ||
+ (((constr &&
(constr->getConstraintType()==ConstraintType::foreign_key ||
(constr->getConstraintType()==ConstraintType::unique &&
- constr->isReferRelationshipAddedColumn()))) ||
- (types[type_id]==OBJ_TRIGGER && dynamic_cast(tab_obj)->isReferRelationshipAddedColumn()) ||
- (types[type_id]==OBJ_INDEX && dynamic_cast(tab_obj)->isReferRelationshipAddedColumn())))
+ constr->isReferRelationshipAddedColumn())))))))
deps.push_back(tab_obj);
}
+
+ if(object->getObjectType() == OBJ_VIEW && type_id >= 2)
+ break;
}
}
}
@@ -2374,7 +2378,7 @@ void ModelWidget::pasteObjects(void)
aux_object=db_model->getObject(aux_name, obj_type);
else
{
- if(sel_view && (obj_type==OBJ_TRIGGER || obj_type==OBJ_RULE))
+ if(sel_view && (obj_type==OBJ_TRIGGER || obj_type==OBJ_RULE || obj_type==OBJ_INDEX))
aux_object=sel_view->getObject(aux_name, obj_type);
else if(sel_table)
aux_object=sel_table->getObject(aux_name, obj_type);
@@ -2420,7 +2424,12 @@ void ModelWidget::pasteObjects(void)
else
{
if(tab_obj)
- tab_obj->setName(PgModelerNS::generateUniqueName(tab_obj, (*sel_table->getObjectList(tab_obj->getObjectType())), false, QString("_cp"), true));
+ {
+ if(sel_table)
+ tab_obj->setName(PgModelerNS::generateUniqueName(tab_obj, (*sel_table->getObjectList(tab_obj->getObjectType())), false, QString("_cp"), true));
+ else
+ tab_obj->setName(PgModelerNS::generateUniqueName(tab_obj, (*sel_view->getObjectList(tab_obj->getObjectType())), false, QString("_cp"), true));
+ }
else
object->setName(PgModelerNS::generateUniqueName(object, (*db_model->getObjectList(object->getObjectType())), false, QString("_cp"), true));
@@ -2467,11 +2476,12 @@ void ModelWidget::pasteObjects(void)
parent=sel_view;
/* Only generates the XML for a table object when the selected receiver object
- is a table or is a view and the current object is a trigger or rule (because
+ is a table or is a view and the current object is a trigger, index, or rule (because
view's only accepts this two types) */
if(sel_table ||
(sel_view && (tab_obj->getObjectType()==OBJ_TRIGGER ||
- tab_obj->getObjectType()==OBJ_RULE)))
+ tab_obj->getObjectType()==OBJ_RULE ||
+ tab_obj->getObjectType()==OBJ_INDEX)))
{
//Backups the original parent table
orig_parent_tab=tab_obj->getParentTable();
@@ -2549,17 +2559,11 @@ void ModelWidget::pasteObjects(void)
//Special case for table objects
if(tab_obj)
{
- if(sel_table &&
- (tab_obj->getObjectType()==OBJ_COLUMN || tab_obj->getObjectType()==OBJ_RULE))
+ if(sel_table && tab_obj->getObjectType()==OBJ_COLUMN)
{
sel_table->addObject(tab_obj);
sel_table->setModified(true);
}
- else if(sel_view && tab_obj->getObjectType()==OBJ_RULE)
- {
- sel_view->addObject(tab_obj);
- sel_view->setModified(true);
- }
//Updates the fk relationships if the constraint is a foreign-key
if(constr && constr->getConstraintType()==ConstraintType::foreign_key)
@@ -2639,7 +2643,11 @@ void ModelWidget::duplicateObject(void)
table = dynamic_cast(object)->getParentTable();
PgModelerNS::copyObject(&dup_object, object, obj_type);
- dup_object->setName(PgModelerNS::generateUniqueName(dup_object, *dynamic_cast(table)->getObjectList(obj_type), false, QString("_cp")));
+
+ if(table->getObjectType() == OBJ_TABLE)
+ dup_object->setName(PgModelerNS::generateUniqueName(dup_object, *dynamic_cast(table)->getObjectList(obj_type), false, QString("_cp")));
+ else
+ dup_object->setName(PgModelerNS::generateUniqueName(dup_object, *dynamic_cast(table)->getObjectList(obj_type), false, QString("_cp")));
op_id=op_list->registerObject(dup_object, Operation::OBJECT_CREATED, -1, table);
table->addObject(dup_object);
@@ -3134,9 +3142,9 @@ void ModelWidget::configureSubmenu(BaseObject *object)
menus[i]->clear();
//Configuring actions "Move to schema", "Change Owner" and "Set tag"
- if((i==0 && accepts_schema) ||
- (i==1 && accepts_owner) ||
- (i==2 && tab_or_view))
+ if((types[i] == OBJ_SCHEMA && accepts_schema) ||
+ (types[i] == OBJ_ROLE && accepts_owner) ||
+ (types[i]==OBJ_TAG && tab_or_view))
{
obj_list=db_model->getObjects(types[i]);
@@ -3147,6 +3155,12 @@ void ModelWidget::configureSubmenu(BaseObject *object)
}
else
{
+ if(types[i] == OBJ_TAG)
+ {
+ menus[i]->addAction(trUtf8("None"), this, SLOT(setTag()));
+ menus[i]->addSeparator();
+ }
+
while(!obj_list.empty())
{
act=new QAction(obj_list.back()->getName(), menus[i]);
diff --git a/libpgmodeler_ui/src/objectdepsrefswidget.cpp b/libpgmodeler_ui/src/objectdepsrefswidget.cpp
index dd9e022078..01e834b5a0 100644
--- a/libpgmodeler_ui/src/objectdepsrefswidget.cpp
+++ b/libpgmodeler_ui/src/objectdepsrefswidget.cpp
@@ -84,12 +84,12 @@ void ObjectDepsRefsWidget::updateObjectTables(void)
objs.erase(std::find(objs.begin(), objs.end(), this->object));
ObjectFinderWidget::updateObjectTable(dependences_tbw, objs);
+ objs.clear();
if(!inc_ind_refs_chk->isChecked())
model->getObjectReferences(object, objs);
else
model->__getObjectReferences(object, objs);
- objs.clear();
ObjectFinderWidget::updateObjectTable(references_tbw, objs);
references_tbw->resizeColumnsToContents();
diff --git a/libpgmodeler_ui/src/pgmodeleruins.cpp b/libpgmodeler_ui/src/pgmodeleruins.cpp
index e5447f1f06..b03c296c79 100644
--- a/libpgmodeler_ui/src/pgmodeleruins.cpp
+++ b/libpgmodeler_ui/src/pgmodeleruins.cpp
@@ -279,8 +279,10 @@ namespace PgModelerUiNS {
screen_id = qApp->desktop()->screenNumber(qApp->activeWindow());
QScreen *screen=qApp->screens().at(screen_id);
float dpi_factor = 0;
+ float pixel_ratio = 0;
dpi_factor = screen->logicalDotsPerInch() / 96.0f;
+ pixel_ratio = screen->devicePixelRatio();
//If the dpi_factor is unchanged (1) we keep the dialog original dimension
if(dpi_factor <= 1.01f)
@@ -307,8 +309,8 @@ namespace PgModelerUiNS {
else if(min_size.height() >= max_h)
curr_h = max_h;
- curr_w *= dpi_factor;
- curr_h *= dpi_factor;
+ curr_w *= dpi_factor * pixel_ratio;
+ curr_h *= dpi_factor * pixel_ratio;
if(curr_w > screen->size().width())
curr_w = screen->size().width() * 0.80;
diff --git a/libpgmodeler_ui/src/relationshipconfigwidget.cpp b/libpgmodeler_ui/src/relationshipconfigwidget.cpp
index 8703e73d1e..e869133b14 100644
--- a/libpgmodeler_ui/src/relationshipconfigwidget.cpp
+++ b/libpgmodeler_ui/src/relationshipconfigwidget.cpp
@@ -191,7 +191,7 @@ void RelationshipConfigWidget::restoreDefaults(void)
{
try
{
- BaseConfigWidget::restoreDefaults(GlobalAttributes::RELATIONSHIPS_CONF);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::RELATIONSHIPS_CONF, false);
this->loadConfiguration();
setConfigurationChanged(true);
}
diff --git a/libpgmodeler_ui/src/relationshipwidget.cpp b/libpgmodeler_ui/src/relationshipwidget.cpp
index f96962eb41..478dd38fa2 100644
--- a/libpgmodeler_ui/src/relationshipwidget.cpp
+++ b/libpgmodeler_ui/src/relationshipwidget.cpp
@@ -157,8 +157,12 @@ RelationshipWidget::RelationshipWidget(QWidget *parent): BaseObjectWidget(parent
connect(deferrable_chk, SIGNAL(toggled(bool)), deferral_cmb, SLOT(setEnabled(bool)));
connect(deferrable_chk, SIGNAL(toggled(bool)), deferral_lbl, SLOT(setEnabled(bool)));
- connect(identifier_chk, SIGNAL(toggled(bool)), table1_mand_chk, SLOT(setDisabled(bool)));
- connect(identifier_chk, SIGNAL(toggled(bool)), table2_mand_chk, SLOT(setDisabled(bool)));
+ connect(identifier_chk, &QCheckBox::toggled, [&](){
+ table1_mand_chk->setDisabled(identifier_chk->isChecked());
+ table2_mand_chk->setEnabled(!identifier_chk->isChecked() &&
+ this->object &&
+ dynamic_cast(this->object)->getRelationshipType() != BaseRelationship::RELATIONSHIP_1N);
+ });
connect(attributes_tab, SIGNAL(s_rowsRemoved(void)), this, SLOT(removeObjects(void)));
connect(attributes_tab, SIGNAL(s_rowAdded(int)), this, SLOT(addObject(void)));
diff --git a/libpgmodeler_ui/src/resultsetmodel.cpp b/libpgmodeler_ui/src/resultsetmodel.cpp
new file mode 100644
index 0000000000..548ff7c3da
--- /dev/null
+++ b/libpgmodeler_ui/src/resultsetmodel.cpp
@@ -0,0 +1,137 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2018 - Raphael Araújo e Silva
+#
+# 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 version 3.
+#
+# 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.
+#
+# The complete text of GPLv3 is at LICENSE file on source code root directory.
+# Also, you can get the complete GNU General Public License at
+*/
+
+#include "resultsetmodel.h"
+
+ResultSetModel::ResultSetModel(ResultSet &res, Catalog &catalog, QObject *parent) : QAbstractTableModel(parent)
+{
+ try
+ {
+ Catalog aux_cat = catalog;
+ vector type_ids;
+ vector::iterator end;
+ vector types;
+ map type_names;
+ int col = 0;
+
+ col_count = res.getColumnCount();
+ row_count = res.getTupleCount();
+ insertColumns(0, col_count);
+ insertRows(0, row_count);
+
+ for(col=0; col < col_count; col++)
+ {
+ header_data.push_back(res.getColumnName(col));
+ type_ids.push_back(res.getColumnTypeId(col));
+ }
+
+ if(res.accessTuple(ResultSet::FIRST_TUPLE))
+ {
+ do
+ {
+ //Fills the current row with the values of current tuple
+ for(int col=0; col < col_count; col++)
+ {
+ if(res.isColumnBinaryFormat(col))
+ item_data.push_back(trUtf8("[binary data]"));
+ else
+ item_data.push_back(res.getColumnValue(col));
+ }
+ }
+ while(res.accessTuple(ResultSet::NEXT_TUPLE));
+ }
+
+ aux_cat.setFilter(Catalog::LIST_ALL_OBJS);
+ std::sort(type_ids.begin(), type_ids.end());
+ end=std::unique(type_ids.begin(), type_ids.end());
+ type_ids.erase(end, type_ids.end());
+
+ types = aux_cat.getObjectsAttributes(OBJ_TYPE, QString(), QString(), type_ids);
+ col = 0;
+
+ for(auto &tp : types)
+ type_names[tp[ParsersAttributes::OID].toInt()]=tp[ParsersAttributes::NAME];
+
+ for(col=0; col < col_count; col++)
+ tooltip_data.push_back(type_names[res.getColumnTypeId(col)]);
+ }
+ catch(Exception &e)
+ {
+ throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e);
+ }
+}
+
+int ResultSetModel::rowCount(const QModelIndex &) const
+{
+ return(row_count);
+}
+
+int ResultSetModel::columnCount(const QModelIndex &) const
+{
+ return(col_count);
+}
+
+QModelIndex ResultSetModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return(QAbstractTableModel::index(row, column, parent));
+}
+
+QModelIndex ResultSetModel::parent(const QModelIndex &) const
+{
+ return(QModelIndex());
+}
+
+QVariant ResultSetModel::data(const QModelIndex &index, int role) const
+{
+ if(index.row() < row_count && index.column() < col_count)
+ {
+ if(role == Qt::DisplayRole)
+ return(item_data.at(index.row() * col_count + index.column()));
+
+ if(role == Qt::TextAlignmentRole)
+ return(QVariant(Qt::AlignLeft | Qt::AlignVCenter));
+ }
+
+ return(QVariant(QVariant::Invalid));
+}
+
+QVariant ResultSetModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if(orientation == Qt::Horizontal)
+ {
+ if(section >= col_count)
+ return(QVariant(QVariant::Invalid));
+
+ if(role == Qt::DisplayRole)
+ return(header_data.at(section));
+
+ if(role == Qt::ToolTipRole)
+ return(tooltip_data.at(section));
+
+ if(role == Qt::TextAlignmentRole)
+ return(QVariant(Qt::AlignLeft | Qt::AlignVCenter));
+ }
+
+ return(QAbstractTableModel::headerData(section, orientation, role));
+}
+
+Qt::ItemFlags ResultSetModel::flags(const QModelIndex &) const
+{
+ return(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
+}
+
diff --git a/libpgmodeler_ui/src/resultsetmodel.h b/libpgmodeler_ui/src/resultsetmodel.h
new file mode 100644
index 0000000000..ec1a6a5a34
--- /dev/null
+++ b/libpgmodeler_ui/src/resultsetmodel.h
@@ -0,0 +1,53 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2018 - Raphael Araújo e Silva
+#
+# 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 version 3.
+#
+# 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.
+#
+# The complete text of GPLv3 is at LICENSE file on source code root directory.
+# Also, you can get the complete GNU General Public License at
+*/
+
+/**
+\ingroup libpgmodeler_ui
+\class ResultSetModel
+\brief Implements a model representation of ResultSet class which can be used to show large amount of data in instances of QTableView.
+*/
+
+#ifndef RESULT_SET_MODEL_H
+#define RESULT_SET_MODEL_H
+
+#include
+#include "resultset.h"
+#include "catalog.h"
+
+class ResultSetModel: public QAbstractTableModel {
+ private:
+ Q_OBJECT
+
+ int col_count, row_count;
+ QStringList item_data, header_data, tooltip_data;
+
+ void insertColumn(int, const QModelIndex &){}
+ void insertRow(int, const QModelIndex &){}
+
+ public:
+ ResultSetModel(ResultSet &res, Catalog &catalog, QObject *parent = 0);
+ virtual int rowCount(const QModelIndex &) const;
+ virtual int columnCount(const QModelIndex &) const;
+ virtual QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ virtual QModelIndex parent(const QModelIndex &) const;
+ virtual QVariant data(const QModelIndex &index, int role) const;
+ virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ virtual Qt::ItemFlags flags(const QModelIndex &) const;
+};
+
+#endif
diff --git a/libpgmodeler_ui/src/snippetsconfigwidget.cpp b/libpgmodeler_ui/src/snippetsconfigwidget.cpp
index c270999116..67d02a78f7 100644
--- a/libpgmodeler_ui/src/snippetsconfigwidget.cpp
+++ b/libpgmodeler_ui/src/snippetsconfigwidget.cpp
@@ -484,7 +484,7 @@ void SnippetsConfigWidget::restoreDefaults(void)
{
try
{
- BaseConfigWidget::restoreDefaults(GlobalAttributes::SNIPPETS_CONF);
+ BaseConfigWidget::restoreDefaults(GlobalAttributes::SNIPPETS_CONF, false);
this->loadConfiguration();
setConfigurationChanged(true);
}
diff --git a/libpgmodeler_ui/src/sqlexecutionwidget.cpp b/libpgmodeler_ui/src/sqlexecutionwidget.cpp
index 18d8acf839..19b004a8a6 100644
--- a/libpgmodeler_ui/src/sqlexecutionwidget.cpp
+++ b/libpgmodeler_ui/src/sqlexecutionwidget.cpp
@@ -27,13 +27,14 @@
map SQLExecutionWidget::cmd_history;
int SQLExecutionWidget::cmd_history_max_len = 1000;
-int SQLExecutionWidget::max_result_rows = 20000;
const QString SQLExecutionWidget::COLUMN_NULL_VALUE = QString("␀");
SQLExecutionWidget::SQLExecutionWidget(QWidget * parent) : QWidget(parent)
{
setupUi(this);
+ result_model = nullptr;
+
sql_cmd_txt=PgModelerUiNS::createNumberedTextEditor(sql_cmd_wgt);
cmd_history_txt=PgModelerUiNS::createNumberedTextEditor(cmd_history_parent);
cmd_history_txt->setCustomContextMenuEnabled(false);
@@ -51,6 +52,7 @@ SQLExecutionWidget::SQLExecutionWidget(QWidget * parent) : QWidget(parent)
layout->addWidget(find_history_wgt);
find_history_parent->setLayout(layout);
find_history_parent->setVisible(false);
+ connect(find_history_wgt->hide_tb, SIGNAL(clicked(bool)), find_history_parent, SLOT(hide()));
sql_cmd_hl=new SyntaxHighlighter(sql_cmd_txt, false);
sql_cmd_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH);
@@ -74,6 +76,7 @@ SQLExecutionWidget::SQLExecutionWidget(QWidget * parent) : QWidget(parent)
hbox->setContentsMargins(0,0,0,0);
hbox->addWidget(find_replace_wgt);
find_wgt_parent->setVisible(false);
+ connect(find_replace_wgt->hide_tb, SIGNAL(clicked(bool)), find_tb, SLOT(toggle()));
run_sql_tb->setToolTip(run_sql_tb->toolTip() + QString(" (%1)").arg(run_sql_tb->shortcut().toString()));
export_tb->setToolTip(export_tb->toolTip() + QString(" (%1)").arg(export_tb->shortcut().toString()));
@@ -103,7 +106,7 @@ SQLExecutionWidget::SQLExecutionWidget(QWidget * parent) : QWidget(parent)
connect(output_tb, SIGNAL(toggled(bool)), this, SLOT(toggleOutputPane(bool)));
//Signal handling with C++11 lambdas Slots
- connect(results_tbw, &QTableWidget::itemPressed,
+ connect(results_tbw, &QTableView::pressed,
[&](){ SQLExecutionWidget::copySelection(results_tbw); });
connect(export_tb, &QToolButton::clicked,
@@ -127,6 +130,16 @@ SQLExecutionWidget::SQLExecutionWidget(QWidget * parent) : QWidget(parent)
v_splitter->handle(1)->installEventFilter(this);
}
+SQLExecutionWidget::~SQLExecutionWidget(void)
+{
+ if(result_model)
+ {
+ results_tbw->blockSignals(true);
+ results_tbw->setModel(nullptr);
+ delete(result_model);
+ }
+}
+
bool SQLExecutionWidget::eventFilter(QObject *object, QEvent *event)
{
if(event->type() == QEvent::MouseButtonDblClick && object == v_splitter->handle(1))
@@ -185,7 +198,21 @@ void SQLExecutionWidget::fillResultsTable(ResultSet &res)
aux_conn.setConnectionParams(sql_cmd_conn.getConnectionParams());
export_tb->setEnabled(res.getTupleCount() > 0);
catalog.setConnection(aux_conn);
- fillResultsTable(catalog, res, results_tbw);
+
+ results_tbw->setSortingEnabled(false);
+ results_tbw->blockSignals(true);
+ results_tbw->setUpdatesEnabled(false);
+ results_tbw->setModel(nullptr);
+
+ if(result_model)
+ delete(result_model);
+
+ result_model = new ResultSetModel(res, catalog);
+
+ results_tbw->setModel(result_model);
+ results_tbw->resizeColumnsToContents();
+ results_tbw->setUpdatesEnabled(true);
+ results_tbw->blockSignals(false);
}
catch(Exception &e)
{
@@ -266,16 +293,13 @@ void SQLExecutionWidget::fillResultsTable(Catalog &catalog, ResultSet &res, QTab
for(col=0; col < col_cnt; col++)
{
item=results_tbw->horizontalHeaderItem(col);
- item->setToolTip(res.getColumnName(col) + QString(" [%1]").arg(type_names[res.getColumnTypeId(col)]));
+ item->setToolTip(type_names[res.getColumnTypeId(col)]);
item->setData(Qt::UserRole, type_names[res.getColumnTypeId(col)]);
}
if(res.accessTuple(ResultSet::FIRST_TUPLE))
{
- if(max_result_rows != 0 && res.getTupleCount() > max_result_rows)
- results_tbw->setRowCount(max_result_rows);
- else
- results_tbw->setRowCount(res.getTupleCount());
+ results_tbw->setRowCount(res.getTupleCount());
do
{
@@ -414,6 +438,7 @@ void SQLExecutionWidget::runSQLCommand(void)
{
ResultSet res;
QStringList conn_notices;
+ qint64 start_exec=0, end_exec=0, total_exec = 0;
output_tb->setChecked(true);
@@ -434,9 +459,11 @@ void SQLExecutionWidget::runSQLCommand(void)
}
QApplication::setOverrideCursor(Qt::WaitCursor);
+
+ start_exec=QDateTime::currentDateTime().toMSecsSinceEpoch();
sql_cmd_conn.executeDMLCommand(cmd, res);
- conn_notices=sql_cmd_conn.getNotices();
+ conn_notices=sql_cmd_conn.getNotices();
addToSQLHistory(cmd, res.getTupleCount());
output_tbw->setTabEnabled(0, !res.isEmpty());
@@ -446,16 +473,8 @@ void SQLExecutionWidget::runSQLCommand(void)
if(!res.isEmpty())
{
fillResultsTable(res);
- output_tbw->setTabText(0, trUtf8("Results (%1)").arg(results_tbw->rowCount()));
-
- if(res.getTupleCount() > max_result_rows)
- {
- conn_notices.append(trUtf8("The number of retrieved rows exceeds the maximum allowed in the results grid! The data was trucated."));
- conn_notices.append(trUtf8("Try to limit the result set by adjusting the query."));
- output_tbw->setCurrentIndex(1);
- }
- else
- output_tbw->setCurrentIndex(0);
+ output_tbw->setTabText(0, trUtf8("Results (%1)").arg(results_tbw->model()->rowCount()));
+ output_tbw->setCurrentIndex(0);
}
else
{
@@ -472,9 +491,13 @@ void SQLExecutionWidget::runSQLCommand(void)
QPixmap(PgModelerUiNS::getIconPath("msgbox_alerta")));
}
+ end_exec=QDateTime::currentDateTime().toMSecsSinceEpoch();
+ total_exec = end_exec - start_exec;
+
PgModelerUiNS::createOutputListItem(msgoutput_lst,
- PgModelerUiNS::formatMessage(trUtf8("[%1]: SQL command successfully executed. %2 %3")
+ PgModelerUiNS::formatMessage(trUtf8("[%1]: SQL command successfully executed in %2. %3 %4")
.arg(QTime::currentTime().toString(QString("hh:mm:ss.zzz")))
+ .arg(total_exec >= 1000 ? QString("%1 s").arg(total_exec/1000) : QString("%1 ms").arg(total_exec))
.arg(res.isEmpty() ? trUtf8("Rows affected") : trUtf8("Rows retrieved"))
.arg(res.getTupleCount())),
QPixmap(PgModelerUiNS::getIconPath("msgbox_info")));
@@ -551,7 +574,7 @@ void SQLExecutionWidget::loadCommands(void)
}
}
-void SQLExecutionWidget::exportResults(QTableWidget *results_tbw)
+void SQLExecutionWidget::exportResults(QTableView *results_tbw)
{
if(!results_tbw)
throw Exception(ERR_OPR_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__);
@@ -577,126 +600,117 @@ void SQLExecutionWidget::exportResults(QTableWidget *results_tbw)
.arg(csv_file_dlg.selectedFiles().at(0))
, ERR_FILE_DIR_NOT_ACCESSED ,__PRETTY_FUNCTION__,__FILE__,__LINE__);
- file.write(generateCSVBuffer(results_tbw, 0, 0, results_tbw->rowCount(), results_tbw->columnCount()));
+ QApplication::setOverrideCursor(Qt::WaitCursor);
+ results_tbw->setUpdatesEnabled(false);
+ results_tbw->blockSignals(true);
+ results_tbw->selectAll();
+
+ file.write(generateCSVBuffer(results_tbw));
file.close();
+
+ results_tbw->clearSelection();
+ results_tbw->blockSignals(false);
+ results_tbw->setUpdatesEnabled(true);
+ QApplication::restoreOverrideCursor();
+ }
+}
+
+int SQLExecutionWidget::clearAll(void)
+{
+ Messagebox msg_box;
+ int res = 0;
+
+ msg_box.show(trUtf8("The SQL input field and the results grid will be cleared! Want to proceed?"),
+ Messagebox::CONFIRM_ICON, Messagebox::YES_NO_BUTTONS);
+
+ res = msg_box.result();
+
+ if(res==QDialog::Accepted)
+ {
+ sql_cmd_txt->setPlainText(QString());
+ msgoutput_lst->clear();
+ msgoutput_lst->setVisible(true);
+ results_parent->setVisible(false);
+ export_tb->setEnabled(false);
}
+
+ return(res);
}
-void SQLExecutionWidget::setMaxResultRows(int max_val)
+QByteArray SQLExecutionWidget::generateCSVBuffer(QTableView *results_tbw)
{
- max_result_rows = (max_val < 0 ? 0 : max_val);
+ return(generateBuffer(results_tbw, QChar(';'), true, true));
}
-int SQLExecutionWidget::getMaxResultRows(void)
+QByteArray SQLExecutionWidget::generateTextBuffer(QTableView *results_tbw)
{
- return(max_result_rows);
+ return(generateBuffer(results_tbw, QChar('\t'), false, false));
}
-QByteArray SQLExecutionWidget::generateCSVBuffer(QTableWidget *results_tbw, int start_row, int start_col, int row_cnt, int col_cnt)
+QByteArray SQLExecutionWidget::generateBuffer(QTableView *results_tbw, QChar separator, bool incl_col_names, bool use_quotes)
{
if(!results_tbw)
throw Exception(ERR_OPR_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__);
+ if(!results_tbw->selectionModel())
+ return (QByteArray());
+
+ QAbstractItemModel *model = results_tbw->model();
+ QModelIndexList sel_indexes = results_tbw->selectionModel()->selectedIndexes();
QByteArray buf;
QStringList line;
+ QModelIndex index;
+ QString str_pattern = use_quotes ? QString("\"%1\"") : QString("%1");
+ int start_row = -1, start_col = -1,
+ row_cnt = 0, col_cnt = 0;
- //If the selection interval is valid
- if(start_row >=0 && start_col >=0 &&
- start_row + row_cnt <= results_tbw->rowCount() &&
- start_col + col_cnt <= results_tbw->columnCount())
- {
- int col=0, row=0,
- max_col=start_col + col_cnt,
- max_row=start_row + row_cnt;
+ start_row = sel_indexes.at(0).row();
+ start_col = sel_indexes.at(0).column();
+ row_cnt = (sel_indexes.last().row() - start_row) + 1;
+ col_cnt = (sel_indexes.last().column() - start_col) + 1;
+
+ int col=0, row=0,
+ max_col=start_col + col_cnt,
+ max_row=start_row + row_cnt;
- //Creating the header of csv
+ if(incl_col_names)
+ {
+ //Creating the header
for(col=start_col; col < max_col; col++)
- line.append(QString("\"%1\"").arg(results_tbw->horizontalHeaderItem(col)->text()));
+ line.append(str_pattern.arg(model->headerData(col, Qt::Horizontal).toString()));
- buf.append(line.join(';'));
+ buf.append(line.join(separator));
buf.append('\n');
line.clear();
-
- //Creating the content
- for(row=start_row; row < max_row; row++)
- {
- for(col=start_col; col < max_col; col++)
- line.append(QString("\"%1\"").arg(results_tbw->item(row, col)->text()));
-
- buf.append(line.join(';'));
- line.clear();
- buf.append('\n');
- }
}
- return(buf);
-}
-
-QByteArray SQLExecutionWidget::generateTextBuffer(QTableWidget *results_tbw, int start_row, int start_col, int row_cnt, int col_cnt)
-{
- if(!results_tbw)
- throw Exception(ERR_OPR_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__);
-
- QByteArray buf;
- QStringList line;
-
- //If the selection interval is valid
- if(start_row >=0 && start_col >=0 &&
- start_row + row_cnt <= results_tbw->rowCount() &&
- start_col + col_cnt <= results_tbw->columnCount())
+ //Creating the content
+ for(row=start_row; row < max_row; row++)
{
- int col=0, row=0,
- max_col=start_col + col_cnt,
- max_row=start_row + row_cnt;
-
- //Creating the content
- for(row=start_row; row < max_row; row++)
+ for(col=start_col; col < max_col; col++)
{
- for(col=start_col; col < max_col; col++)
- {
- line.push_back(results_tbw->item(row, col)->text());
- }
-
- buf.append(line.join('\t'));
- line.clear();
- buf.append('\n');
+ index = model->index(row, col);
+ line.append(str_pattern.arg(index.data().toString()));
}
- }
-
- return(buf);
-}
-int SQLExecutionWidget::clearAll(void)
-{
- Messagebox msg_box;
- int res = 0;
-
- msg_box.show(trUtf8("The SQL input field and the results grid will be cleared! Want to proceed?"),
- Messagebox::CONFIRM_ICON, Messagebox::YES_NO_BUTTONS);
-
- res = msg_box.result();
-
- if(res==QDialog::Accepted)
- {
- sql_cmd_txt->setPlainText(QString());
- msgoutput_lst->clear();
- msgoutput_lst->setVisible(true);
- results_parent->setVisible(false);
- export_tb->setEnabled(false);
+ buf.append(line.join(separator));
+ line.clear();
+ buf.append('\n');
}
- return(res);
+ return(buf);
}
-void SQLExecutionWidget::copySelection(QTableWidget *results_tbw, bool use_popup, bool csv_is_default)
+void SQLExecutionWidget::copySelection(QTableView *results_tbw, bool use_popup, bool csv_is_default)
{
if(!results_tbw)
throw Exception(ERR_OPR_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__);
- QList sel_ranges=results_tbw->selectedRanges();
+ QItemSelectionModel *selection = results_tbw->selectionModel();
- if(sel_ranges.count()==1 && (!use_popup || (use_popup && QApplication::mouseButtons()==Qt::RightButton)))
+ if(selection && (!use_popup || (use_popup && QApplication::mouseButtons()==Qt::RightButton)))
{
+ QModelIndexList sel_indexes = selection->selectedIndexes();
QMenu copy_menu, copy_mode_menu;
QAction *act = nullptr, *act_csv = nullptr, *act_txt = nullptr;
@@ -711,15 +725,13 @@ void SQLExecutionWidget::copySelection(QTableWidget *results_tbw, bool use_popup
if(!use_popup || act)
{
- QTableWidgetSelectionRange selection=sel_ranges.at(0);
+ //QTableWidgetSelectionRange selection=sel_ranges.at(0);
QByteArray buf;
if((use_popup && act == act_csv) || (!use_popup && csv_is_default))
{
//Generates the csv buffer and assigns it to application's clipboard
- buf=generateCSVBuffer(results_tbw,
- selection.topRow(), selection.leftColumn(),
- selection.rowCount(), selection.columnCount());
+ buf=generateCSVBuffer(results_tbw);
/* Making DataManipulationForm instances know that the clipboard has csv buffer
* in order to paste the contents properly */
@@ -727,9 +739,7 @@ void SQLExecutionWidget::copySelection(QTableWidget *results_tbw, bool use_popup
}
else if((use_popup && act == act_txt) || (!use_popup && !csv_is_default))
{
- buf=generateTextBuffer(results_tbw,
- selection.topRow(), selection.leftColumn(),
- selection.rowCount(), selection.columnCount());
+ buf=generateTextBuffer(results_tbw);
}
qApp->clipboard()->setText(buf);
diff --git a/libpgmodeler_ui/src/sqlexecutionwidget.h b/libpgmodeler_ui/src/sqlexecutionwidget.h
index 8257fc1352..9b8ff25be8 100644
--- a/libpgmodeler_ui/src/sqlexecutionwidget.h
+++ b/libpgmodeler_ui/src/sqlexecutionwidget.h
@@ -33,6 +33,7 @@
#include "codecompletionwidget.h"
#include "numberedtexteditor.h"
#include "findreplacewidget.h"
+#include "resultsetmodel.h"
class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget {
private:
@@ -42,12 +43,6 @@ class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget {
static int cmd_history_max_len;
- /*! \brief The maximum amount of rows allowed to the results grid.
- * This attribute is used to limit the amount of rows inserted in any QTableWidget instance
- * by fillResultsTable() in order to avoid memory exhaustion leading to crash depending on
- * the amount of rows stored in a result set */
- static int max_result_rows;
-
SchemaParser schparser;
//! \brief Syntax highlighter for sql input field
@@ -74,6 +69,8 @@ class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget {
FindReplaceWidget *find_history_wgt;
+ ResultSetModel *result_model;
+
/*! \brief Enables/Disables the fields for sql input and execution.
When enabling a new connection to server will be opened. */
void enableSQLExecution(bool enable);
@@ -103,6 +100,7 @@ class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget {
static const QString COLUMN_NULL_VALUE;
SQLExecutionWidget(QWidget * parent = 0);
+ ~SQLExecutionWidget(void);
//! \brief Configures the connection to query the server
void setConnection(Connection conn);
@@ -112,20 +110,19 @@ class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget {
static void fillResultsTable(Catalog &catalog, ResultSet &res, QTableWidget *results_tbw, bool store_data=false);
//! \brief Copy to clipboard (in csv format) the current selected items on results grid
- static void copySelection(QTableWidget *results_tbw, bool use_popup=true, bool csv_is_default = false);
+ static void copySelection(QTableView *results_tbw, bool use_popup=true, bool csv_is_default = false);
//! \brief Generates a CSV buffer based upon the selection on the results grid
- static QByteArray generateCSVBuffer(QTableWidget *results_tbw, int start_row, int start_col, int row_cnt, int col_cnt);
+ static QByteArray generateCSVBuffer(QTableView *results_tbw);
//! \brief Generates a Plain text buffer based upon the selection on the results grid (this method does not include the column names)
- static QByteArray generateTextBuffer(QTableWidget *results_tbw, int start_row, int start_col, int row_cnt, int col_cnt);
+ static QByteArray generateTextBuffer(QTableView *results_tbw);
- //! \brief Exports the results to csv file
- static void exportResults(QTableWidget *results_tbw);
+ //! \brief Generates a custom text buffer. User can specify a separator for columns, include column names and quote values
+ static QByteArray generateBuffer(QTableView *results_tbw, QChar separator, bool incl_col_names, bool use_quotes);
- static void setMaxResultRows(int max_val);
-
- static int getMaxResultRows(void);
+ //! \brief Exports the results to csv file
+ static void exportResults(QTableView *results_tbw);
public slots:
void configureSnippets(void);
diff --git a/libpgmodeler_ui/src/validationinfo.h b/libpgmodeler_ui/src/validationinfo.h
index 81773c2289..4ff4872670 100644
--- a/libpgmodeler_ui/src/validationinfo.h
+++ b/libpgmodeler_ui/src/validationinfo.h
@@ -50,8 +50,9 @@ class ValidationInfo {
BROKEN_REFERENCE=1,
SP_OBJ_BROKEN_REFERENCE=2,
BROKEN_REL_CONFIG=3,
- SQL_VALIDATION_ERR=4,
- VALIDATION_ABORTED=5;
+ MISSING_EXTENSION=4,
+ SQL_VALIDATION_ERR=5,
+ VALIDATION_ABORTED=6;
ValidationInfo(void);
ValidationInfo(unsigned val_type, BaseObject *object, vector references);
diff --git a/libpgmodeler_ui/ui/aboutwidget.ui b/libpgmodeler_ui/ui/aboutwidget.ui
index 2fdb9dcc26..5df306c8fd 100644
--- a/libpgmodeler_ui/ui/aboutwidget.ui
+++ b/libpgmodeler_ui/ui/aboutwidget.ui
@@ -9,8 +9,8 @@
0
0
- 575
- 550
+ 550
+ 530
@@ -21,14 +21,14 @@
- 575
- 550
+ 550
+ 530
16777215
- 600
+ 550
@@ -68,7 +68,7 @@
QFrame::Raised
-
+
6
@@ -81,32 +81,7 @@
6
-
- 6
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- PostgreSQL Database Modeler
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
+
-
@@ -116,14 +91,14 @@
- 100
- 100
+ 50
+ 50
- 100
- 100
+ 50
+ 50
@@ -137,190 +112,32 @@
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- false
-
-
-
- QFrame::NoFrame
-
-
- Open source data modeling tool designed for PostgreSQL. No more DDL commands written by hand, let pgModeler do the job for you! This software reunites the concepts of entity-relationship diagrams and the features that PostgreSQL implements as extensions of SQL standards.
-
-
- Qt::PlainText
-
-
- Qt::AlignJustify|Qt::AlignTop
-
-
- true
-
-
- 0
-
-
- Qt::TextSelectableByMouse
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 230
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
- true
-
-
-
- Design, configure, deploy
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
- <html><head/><body><p><a href="http://pgmodeler.com.br"><span style=" text-decoration: underline; color:#2980b9;">https://pgmodeler.io</span></a></p></body></html>
-
-
- Qt::RichText
-
-
- 5
-
-
- true
-
-
-
- -
-
-
- pgModeler is proudly a brazilian software!
-
-
-
-
-
-
-
-
- :/imagens/imagens/brazil_flag.png
-
-
- Qt::AlignHCenter|Qt::AlignTop
-
-
-
+ -
+
-
-
-
-
- 0
- 0
-
-
-
- <html><head/><body><p>Copyright 2006-2016 - Raphael Araújo e Silva <<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.io</span></a>></p></body></html>
+
+
+ Qt::Horizontal
-
- Qt::AutoText
-
-
- 5
-
-
- true
+
+
+ 40
+ 20
+
-
+
-
-
- -
-
-
-
- 20
- 20
-
-
-
-
- 20
- 20
-
-
-
- Hide this widget
-
-
- ...
-
-
-
- :/icones/icones/fechar1.png:/icones/icones/fechar1.png
-
-
- true
-
-
-
- -
-
-
- 6
-
-
-
+
-
-
+
0
0
- 60
+ 0
0
@@ -337,19 +154,15 @@
true
+
+
+
- 0.0.0.0
+ 0.0.0
-
-
- -
-
-
- 6
-
-
-
+
-
@@ -368,20 +181,17 @@
Qt::LeftToRight
- Build:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+ build:
-1
- -
+
-
-
+
0
0
@@ -436,482 +246,258 @@
-1
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ PostgreSQL Database Modeler
+
+
+ Qt::AlignCenter
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
- -
-
-
-
- 0
- 0
-
-
+
-
+
- 0
- 0
+ 20
+ 20
-
- 0
+
+
+ 20
+ 20
+
+
+
+ Hide this widget
+
+
+ ...
+
+
+
+ :/icones/icones/fechar1.png:/icones/icones/fechar1.png
+
+
+ true
-
-
- License
-
-
-
- 4
-
-
- 4
-
-
- 4
-
-
- 4
-
-
-
-
-
-
- Droid Sans Tamil
-
-
-
- QFrame::Sunken
-
-
- QAbstractScrollArea::AdjustToContents
-
-
- false
-
-
- QTextEdit::WidgetWidth
-
-
- true
-
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Droid Sans Tamil'; font-size:10pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier';">pgModeler - PostgreSQL Database Modeler<br />Copyright 2006-2016 - Raphael Araújo e Silva<br /><br />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 version 3.<br /><br />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.<br /><br />The complete text of GPLv3 is at LICENSE file on pgModeler's source code root directory. Also, you can get the complete GNU General Public License at <</span><a href="http://www.gnu.org/licenses"><span style=" font-family:'Courier'; text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses</span></a><span style=" font-family:'Courier';">></span></p></body></html>
-
-
- false
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
-
-
-
-
-
-
-
- Contributors
-
-
-
- 4
-
-
- 4
-
-
- 4
-
-
- 4
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- false
-
-
-
- QFrame::NoFrame
-
-
- <html><head/><body><p>This page is dedicated to all contributors who gave a bit of their time in make pgModeler a better software somehow. The complete list of people that helped pgModeler can be found at <a href="https://github.com/pgmodeler/pgmodeler/graphs/contributors"><span style=" text-decoration: underline; color:#00a489;">GitHub</span></a>.</p><p>If you have a great idea to improve pgModeler please submit it <a href="http://github.com/pgmodeler/pgmodeler/issues"><span style=" text-decoration: underline; color:#00a489;">here</span></a>. No ideas for now but want to help? Why not donate a few bucks <a href="http://pgmodeler.com.br/#donate"><span style=" text-decoration: underline; color:#00a489;">here</span></a>!?</p></body></html>
-
-
- Qt::RichText
-
-
- Qt::AlignJustify|Qt::AlignTop
-
-
- true
-
-
- 0
-
-
- true
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Qt::ScrollBarAsNeeded
-
-
- Qt::ScrollBarAsNeeded
-
-
- QAbstractItemView::NoEditTriggers
-
-
- false
-
-
- true
-
-
- QAbstractItemView::SingleSelection
-
-
- QAbstractItemView::SelectItems
-
-
- QAbstractItemView::ScrollPerItem
-
-
- true
-
-
- false
-
-
- true
-
-
- true
-
-
- false
-
-
- true
-
-
- false
-
-
- false
-
-
- false
-
-
-
- 1
-
-
-
-
- 2
-
-
-
-
- 3
-
-
-
-
- 4
-
-
-
-
- 5
-
-
-
-
- 6
-
-
-
-
- 7
-
-
-
-
- 8
-
-
-
-
- 9
-
-
-
-
- 10
-
-
-
-
- Name
-
-
-
-
- Country
-
-
-
-
- Contribution
-
-
- -
-
- Damien Degois
-
-
- -
-
- France
-
-
-
- :/icones/icones/flag_france.png:/icones/icones/flag_france.png
-
-
- -
-
- French UI translation and several improvements in auxiliary scripts.
-
-
- -
-
- Ji Bin
-
-
- -
-
- China
-
-
-
- :/icones/icones/flag_china.png:/icones/icones/flag_china.png
-
-
- -
-
- Chinese UI translation and small fixes.
-
-
- -
-
- Pierre-Samuel LE STANG
-
-
- -
-
- France
-
-
-
- :/icones/icones/flag_france.png:/icones/icones/flag_france.png
-
-
- -
-
- French UI translation.
-
-
- -
-
- Lisandro Damián Nicanor
-
-
- -
-
- Argentina
-
-
-
- :/icones/icones/flag_argentina.png:/icones/icones/flag_argentina.png
-
-
- -
-
- Improvements on build scripts enabling the custom packaging in Linux distros; Per-user settings; pgModeler's package maintainer in Debian Linux.
-
-
- -
-
- Pavel Alexeev
-
-
- -
-
- Russia
-
-
-
- :/icones/icones/flag_russia.png:/icones/icones/flag_russia.png
-
-
- -
-
- Additional work for packaging in Linux distros; pgModeler's package maintainer in Fedora Linux.
-
-
- -
-
- Mariusz Fik
-
-
- -
-
- Poland
-
-
-
- :/icones/icones/flag_poland.png:/icones/icones/flag_poland.png
-
-
- -
-
- Custom packaging first ideas. Tester of first version of custom packaging patch.
-
-
- -
-
- Jonathan DUPRE
-
-
- -
-
- France
-
-
-
- :/icones/icones/flag_france.png:/icones/icones/flag_france.png
-
-
- -
-
- French UI translation.
-
-
- -
-
- Gilberto Castillo
-
-
- -
-
- Cuba
-
-
-
- :/icones/icones/flag_cuba.png:/icones/icones/flag_cuba.png
-
-
- -
-
- Spanish UI translation.
-
-
- -
-
-
-Danúbio Viana Nogueira
-
-
- -
-
- Brazil
-
-
-
- :/imagens/imagens/brazil_flag.png:/imagens/imagens/brazil_flag.png
-
-
- -
-
- Brazilian Portuguese UI translation.
-
-
- -
-
- Alfredo Marcillo
-
-
- -
-
- Ecuador
-
-
-
- :/icones/icones/flag_ecuador.png:/icones/icones/flag_ecuador.png
-
-
- -
-
- Spanish UI translation review.
-
-
-
-
-
-
- -
+
-
Qt::Vertical
- QSizePolicy::Expanding
+ QSizePolicy::Fixed
20
- 10
+ 20
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ false
+
+
+
+ QFrame::NoFrame
+
+
+ Open source data modeling tool designed for PostgreSQL. No more DDL commands written by hand, let pgModeler do the job for you! This software reunites the concepts of entity-relationship diagrams and the features that PostgreSQL implements as extensions of SQL standards.
+
+
+ Qt::PlainText
+
+
+ Qt::AlignJustify|Qt::AlignTop
+
+
+ true
+
+
+ 0
+
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+ License
+
+
+
+ 4
+
+
+ 4
+
+
+ 4
+
+
+ 4
+
+
-
+
+
+ QFrame::Sunken
+
+
+ QAbstractScrollArea::AdjustToContents
+
+
+ false
+
+
+ QTextEdit::WidgetWidth
+
+
+ true
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Courier';">pgModeler - PostgreSQL Database Modeler<br />Copyright 2006-2018 - Raphael Araújo e Silva<br /><br />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 version 3.<br /><br />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.<br /><br />The complete text of GPLv3 is at LICENSE file on pgModeler's source code root directory. Also, you can get the complete GNU General Public License at <</span><a href="http://www.gnu.org/licenses"><span style=" font-family:'Courier'; text-decoration: underline; color:#0000ff;">http://www.gnu.org/licenses</span></a><span style=" font-family:'Courier';">></span></p></body></html>
+
+
+ false
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ <html><head/><body><p><a href="http://pgmodeler.com.br"><span style=" text-decoration: underline; color:#2980b9;">https://pgmodeler.io</span></a></p></body></html>
+
+
+ Qt::RichText
+
+
+ 5
+
+
+ true
+
+
+
+ -
+
+
+ pgModeler is proudly a brazilian software!
+
+
+
+
+
+
+
+
+ :/imagens/imagens/brazil_flag.png
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ <html><head/><body><p>Copyright 2006-2018 - Raphael Araújo e Silva <<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.io</span></a>></p></body></html>
+
+
+ Qt::AutoText
+
+
+ 5
+
+
+ true
+
+
+
+
+
diff --git a/libpgmodeler_ui/ui/baseobjectwidget.ui b/libpgmodeler_ui/ui/baseobjectwidget.ui
index c3db5ea209..6d8136f248 100644
--- a/libpgmodeler_ui/ui/baseobjectwidget.ui
+++ b/libpgmodeler_ui/ui/baseobjectwidget.ui
@@ -507,6 +507,9 @@ This will disable the code of all child and referrer objects.
80
+
+ true
+
diff --git a/libpgmodeler_ui/ui/configurationform.ui b/libpgmodeler_ui/ui/configurationform.ui
index c33ee5bf83..e2e72b0462 100644
--- a/libpgmodeler_ui/ui/configurationform.ui
+++ b/libpgmodeler_ui/ui/configurationform.ui
@@ -117,7 +117,7 @@
false
- QAbstractItemView::DragOnly
+ QAbstractItemView::NoDragDrop
Qt::IgnoreAction
@@ -205,6 +205,9 @@
:/icones/icones/relationshiptv.png:/icones/icones/relationshiptv.png
+
+ ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled
+
-
@@ -244,6 +247,9 @@
:/icones/icones/codesnippet.png:/icones/icones/codesnippet.png
+
+ ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled
+
-
diff --git a/libpgmodeler_ui/ui/datamanipulationform.ui b/libpgmodeler_ui/ui/datamanipulationform.ui
index 97d2c9f515..995d5ea701 100644
--- a/libpgmodeler_ui/ui/datamanipulationform.ui
+++ b/libpgmodeler_ui/ui/datamanipulationform.ui
@@ -1456,10 +1456,13 @@
0
- 999999
+ 1000000
+
+
+ 50
- 500
+ 1000
diff --git a/libpgmodeler_ui/ui/donatewidget.ui b/libpgmodeler_ui/ui/donatewidget.ui
index d150e9660d..82b6988a59 100644
--- a/libpgmodeler_ui/ui/donatewidget.ui
+++ b/libpgmodeler_ui/ui/donatewidget.ui
@@ -166,6 +166,12 @@
-
+
+
+ 0
+ 0
+
+
0
@@ -203,7 +209,7 @@
- 40
+ 118
20
diff --git a/libpgmodeler_ui/ui/findreplacewidget.ui b/libpgmodeler_ui/ui/findreplacewidget.ui
index 9bdea1a4c4..d5972e866d 100644
--- a/libpgmodeler_ui/ui/findreplacewidget.ui
+++ b/libpgmodeler_ui/ui/findreplacewidget.ui
@@ -7,7 +7,7 @@
0
0
704
- 62
+ 64
@@ -170,6 +170,35 @@
+ -
+
+
+
+ 20
+ 20
+
+
+
+
+ 20
+ 20
+
+
+
+ Hide this widget
+
+
+ ...
+
+
+
+ :/icones/icones/fechar1.png:/icones/icones/fechar1.png
+
+
+ true
+
+
+
-
diff --git a/libpgmodeler_ui/ui/generalconfigwidget.ui b/libpgmodeler_ui/ui/generalconfigwidget.ui
index e68bad1f52..19c46a92cd 100644
--- a/libpgmodeler_ui/ui/generalconfigwidget.ui
+++ b/libpgmodeler_ui/ui/generalconfigwidget.ui
@@ -1011,25 +1011,10 @@
4
-
-
-
-
-
- 0
- 0
-
-
-
-
- 22
- 22
-
-
-
-
- 22
- 22
-
+
-
+
+
+ Souce code editor args:
@@ -1163,156 +1148,30 @@
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 60
- 0
-
-
-
- Maximum number of rows to be displayed in the results grid. This is used as a security measure to avoid application crash due to memory exhaustion when retrieving a huge set of data from the database without using filtering keywords like <strong>LIMIT</strong> or <strong>WHERE</strong>.
-
-
- 5000
-
-
- 500000
-
-
- 5000
-
-
- 20000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- rows
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 22
- 22
-
-
-
-
- 22
- 22
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Expanding
-
-
-
- 25
- 20
-
-
-
-
-
-
- -
-
-
-
-
-
- false
-
-
-
- -
-
+
-
+
-
+
0
0
- 0
- 0
+ 22
+ 22
-
- SQL history max. length:
-
-
-
- -
-
-
- true
-
-
-
- -
-
-
- Souce code editor:
-
-
-
- -
-
-
- Configurations directory:
+
+
+ 22
+ 22
+
- -
-
+
-
+
0
@@ -1332,7 +1191,7 @@
- Browse the source code editor application
+ Open in file manager
@@ -1349,10 +1208,17 @@
- -
-
+
-
+
+
+ Overrides the default user interface language defined by the system. Requires restarting the program. <strong>NOTE:</strong> UI translations are third party collaborations thus any typo or mistake should be reported directly to their respective maintainers.
+
+
+
+ -
+
-
+
0
0
@@ -1363,31 +1229,22 @@
0
-
-
- 16777215
- 16777215
-
+
+ SQL history max. length:
+
+
+ -
+
- Open in file manager
-
-
-
-
- :/icones/icones/abrir.png:/icones/icones/abrir.png
-
-
-
- 22
- 22
-
+
+ false
- -
+
-
Check if there is a new version on server
@@ -1400,10 +1257,20 @@
- -
-
-
- Souce code editor args:
+
-
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+ false
@@ -1414,30 +1281,55 @@
- -
-
-
- Overrides the default user interface language defined by the system. Requires restarting the program. <strong>NOTE:</strong> UI translations are third party collaborations thus any typo or mistake should be reported directly to their respective maintainers.
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
-
-
- -
-
+ Browse the source code editor application
+
+
-
- false
+
+
+ :/icones/icones/abrir.png:/icones/icones/abrir.png
+
+
+
+ 22
+ 22
+
- -
-
+
-
+
- Limit SQL results in:
+ Souce code editor:
-
- true
+
+
+ -
+
+
+ Configurations directory:
diff --git a/libpgmodeler_ui/ui/messagebox.ui b/libpgmodeler_ui/ui/messagebox.ui
index 9f1a235117..38e5e05b28 100644
--- a/libpgmodeler_ui/ui/messagebox.ui
+++ b/libpgmodeler_ui/ui/messagebox.ui
@@ -10,7 +10,7 @@
0
0
500
- 175
+ 244
@@ -105,7 +105,7 @@
0
-
+
0
@@ -118,91 +118,121 @@
0
-
- 0
-
-
-
-
- 2
+
+
+
+ 40
+ 40
+
-
-
-
-
-
- 40
- 40
-
-
-
-
- 40
- 40
-
-
-
-
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- true
-
-
-
- 0
- 0
-
+
+
+ 40
+ 40
+
+
+
+
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 90
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+ msg
+
+
+ Qt::RichText
+
+
+ true
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+ 4
+
+
+ true
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 84
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
-
-
- 0
- 90
-
+
+ QSizePolicy::Fixed
-
+
- 16777215
- 16777215
+ 5
+ 20
-
- false
-
-
- false
-
-
-
-
+
+
+ -
+
- msg
-
-
- Qt::RichText
-
-
- true
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
- true
-
-
- 4
-
-
- true
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
@@ -316,86 +346,100 @@
- -
-
-
- Qt::Horizontal
-
-
+
-
+
+
- 414
- 27
+ 0
+ 0
-
-
- -
-
-
- 4
-
-
- 4
-
-
-
-
-
-
- 0
- 0
-
-
-
- Show raw text errors or information.
-
-
-
-
-
-
- :/icones/icones/codigofonte.png:/icones/icones/codigofonte.png
-
-
-
- 22
- 22
-
-
-
- true
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Show/hide exceptions stack.
-
-
- ...
-
-
-
- :/icones/icones/refazer.png:/icones/icones/refazer.png
-
-
-
- 22
- 22
-
-
-
- true
-
-
-
-
+
+
+ 0
+
+
+ 0
+
+
+ 4
+
+
+ 4
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 415
+ 24
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Show raw text errors or information.
+
+
+
+
+
+
+ :/icones/icones/codigofonte.png:/icones/icones/codigofonte.png
+
+
+
+ 22
+ 22
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Show/hide exceptions stack.
+
+
+ ...
+
+
+
+ :/icones/icones/refazer.png:/icones/icones/refazer.png
+
+
+
+ 22
+ 22
+
+
+
+ true
+
+
+
+
+
diff --git a/libpgmodeler_ui/ui/modelvalidationwidget.ui b/libpgmodeler_ui/ui/modelvalidationwidget.ui
index 6530560647..fdc016a937 100644
--- a/libpgmodeler_ui/ui/modelvalidationwidget.ui
+++ b/libpgmodeler_ui/ui/modelvalidationwidget.ui
@@ -718,7 +718,7 @@
Try to resolve the reported issues.
- Apply Fix
+ Apply fixes
@@ -753,7 +753,7 @@
Change the creation order for two objects by swapping their ids
- Swap Ids
+ Swap ids
diff --git a/libpgmodeler_ui/ui/sqlexecutionwidget.ui b/libpgmodeler_ui/ui/sqlexecutionwidget.ui
index 60d3821d04..16305c6758 100644
--- a/libpgmodeler_ui/ui/sqlexecutionwidget.ui
+++ b/libpgmodeler_ui/ui/sqlexecutionwidget.ui
@@ -581,7 +581,7 @@
4
- -
+
-
@@ -605,14 +605,8 @@
0
-
-
-
-
- true
-
-
- true
-
+
-
+
QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed
@@ -622,34 +616,24 @@
QAbstractItemView::ContiguousSelection
-
- QAbstractItemView::ScrollPerItem
-
-
- QAbstractItemView::ScrollPerPixel
-
-
+
+ true
+
+
false
-
+
true
+
+ true
+
25
25
-
-
- ...
-
-
-
-
- ...
-
-
diff --git a/linuxdeploy.sh b/linuxdeploy.sh
index 045c9c975c..be88cd8b5e 100755
--- a/linuxdeploy.sh
+++ b/linuxdeploy.sh
@@ -23,20 +23,25 @@ QMAKE_CMD=qmake
LOG="$PWD/linuxdeploy.log"
QT_IFW_ROOT=/opt/qt-ifw-1.5.0
+
+# Prepare setup variables
STARTUP_SCRIPT="start-pgmodeler.sh"
MIME_UPDATE_SCRIPT="dbm-mime-type.sh"
ENV_VARS_SCRIPT="pgmodeler.vars"
BUILD_DIR="$PWD/build"
DIST_DIR="$PWD/dist"
-INSTALL_ROOT="/opt/pgmodeler"
+# Detecting current pgModeler version
+DEPLOY_VER=`cat libutils/src/globalattributes.cpp | grep PGMODELER_VERSION | sed 's/PGMODELER_VERSION=QString("//g' | sed 's/"),//g' | sed 's/^ *//g' | cut -s -f2`
+PREFIX="/opt/pgmodeler"
+# Uncomment this line if you want to keep several versions of pgmodeler
+#PREFIX="/opt/pgmodeler/$DEPLOY_VER"
+INSTALL_ROOT="$PREFIX"
INSTALLER_CONF_DIR="$PWD/installer/linux/config"
INSTALLER_PKG_DIR="$PWD/installer/linux/packages"
INSTALLER_DATA_DIR="$INSTALLER_PKG_DIR/br.com.pgmodeler/data"
QT_CONF="$BUILD_DIR/$INSTALL_ROOT/qt.conf"
DEP_PLUGINS_DIR="$BUILD_DIR/$INSTALL_ROOT/lib/qtplugins"
-# Detecting current pgModeler version
-DEPLOY_VER=`cat libutils/src/globalattributes.cpp | grep PGMODELER_VERSION | sed 's/PGMODELER_VERSION=QString("//g' | sed 's/"),//g' | sed 's/^ *//g' | cut -s -f2`
GEN_INSTALLER_OPT='-gen-installer'
DEMO_VERSION_OPT='-demo-version'
NO_QT_LIBS_OPT='-no-qt-libs'
@@ -49,7 +54,6 @@ BUNDLE_QT_LIBS=1
BUILD_ALL=0
# pgModeler output paths settings
-PREFIX="/opt/pgmodeler"
BINDIR=$PREFIX
PRIVATEBINDIR=$PREFIX
PRIVATELIBDIR="$PREFIX/lib"
diff --git a/main-cli/src/pgmodelercli.cpp b/main-cli/src/pgmodelercli.cpp
index c21c60a513..a618817666 100644
--- a/main-cli/src/pgmodelercli.cpp
+++ b/main-cli/src/pgmodelercli.cpp
@@ -366,50 +366,50 @@ bool PgModelerCLI::isOptionRecognized(QString &op, bool &accepts_val)
void PgModelerCLI::showMenu(void)
{
out << endl;
- out << trUtf8("Usage: pgmodeler-cli [OPTIONS]") << endl;
out << QString("pgModeler ") << GlobalAttributes::PGMODELER_VERSION << trUtf8(" command line interface.") << endl;
out << trUtf8("PostgreSQL Database Modeler Project - pgmodeler.io") << endl;
out << trUtf8("Copyright 2006-2018 Raphael A. Silva ") << endl;
out << endl;
- out << trUtf8("This CLI tool provides several operations over models and databases without the need to perform them\non pgModeler's graphical interface. All available options are described below.") << endl;
+ out << trUtf8("Usage: pgmodeler-cli [OPTIONS]") << endl << endl;
+ out << trUtf8("This CLI tool provides several operations over models and databases without the need to perform them\nin pgModeler's graphical interface. All available options are described below.") << endl;
out << endl;
out << trUtf8("General options: ") << endl;
- out << trUtf8(" %1, %2 [FILE]\t\t Input model file (.dbm). This is mandatory in fix, export operations.").arg(short_opts[INPUT]).arg(INPUT) << endl;
- out << trUtf8(" %1, %2 [DBNAME]\t Input database name. This is mandatory import operation.").arg(short_opts[INPUT_DB]).arg(INPUT_DB) << endl;
- out << trUtf8(" %1, %2 [FILE]\t\t Output file. Mandatory use in fixing model or exporting to file, png or svg.").arg(short_opts[OUTPUT]).arg(OUTPUT) << endl;
+ out << trUtf8(" %1, %2 [FILE]\t\t Input model file (.dbm). This is mandatory for fix, export operations.").arg(short_opts[INPUT]).arg(INPUT) << endl;
+ out << trUtf8(" %1, %2 [DBNAME]\t Input database name. This is mandatory for import operation.").arg(short_opts[INPUT_DB]).arg(INPUT_DB) << endl;
+ out << trUtf8(" %1, %2 [FILE]\t\t Output file. This is mandatory for fixing model or exporting to file, png or svg.").arg(short_opts[OUTPUT]).arg(OUTPUT) << endl;
out << trUtf8(" %1, %2\t\t Try to fix the structure of the input model file in order to make it loadable again.").arg(short_opts[FIX_MODEL]).arg(FIX_MODEL) << endl;
- out << trUtf8(" %1, %2 [NUMBER]\t Model fix tries. When reaching the maximum count the invalid objects will be discard.").arg(short_opts[FIX_TRIES]).arg(FIX_TRIES) << endl;
+ out << trUtf8(" %1, %2 [NUMBER]\t Model fix tries. When reaching the maximum count the invalid objects will be discarded.").arg(short_opts[FIX_TRIES]).arg(FIX_TRIES) << endl;
out << trUtf8(" %1, %2\t\t Export the input model to a sql script file.").arg(short_opts[EXPORT_TO_FILE]).arg(EXPORT_TO_FILE)<< endl;
out << trUtf8(" %1, %2\t\t Export the input model to a png image.").arg(short_opts[EXPORT_TO_PNG]).arg(EXPORT_TO_PNG) << endl;
out << trUtf8(" %1, %2\t\t Export the input model to a svg file.").arg(short_opts[EXPORT_TO_SVG]).arg(EXPORT_TO_SVG) << endl;
out << trUtf8(" %1, %2\t\t Export the input model directly to a PostgreSQL server.").arg(short_opts[EXPORT_TO_DBMS]).arg(EXPORT_TO_DBMS) << endl;
out << trUtf8(" %1, %2\t\t Import a database to an output file.").arg(short_opts[IMPORT_DB]).arg(IMPORT_DB) << endl;
- out << trUtf8(" %1, %2\t\t\t Compares a model and database or two databases generating a SQL script to synch the latter in relation to the first.").arg(short_opts[DIFF]).arg(DIFF) << endl;
+ out << trUtf8(" %1, %2\t\t\t Compares a model and a database or two databases generating the SQL script to synch the latter in relation to the first.").arg(short_opts[DIFF]).arg(DIFF) << endl;
out << trUtf8(" %1, %2\t\t Force the PostgreSQL version of generated SQL code.").arg(short_opts[PGSQL_VER]).arg(PGSQL_VER) << endl;
- out << trUtf8(" %1, %2\t\t\t Silent execution. Only critical errors are shown during process.").arg(short_opts[SILENT]).arg(SILENT) << endl;
+ out << trUtf8(" %1, %2\t\t\t Silent execution. Only critical messages and errors are shown during process.").arg(short_opts[SILENT]).arg(SILENT) << endl;
out << trUtf8(" %1, %2\t\t\t Show this help menu.").arg(short_opts[HELP]).arg(HELP) << endl;
out << endl;
out << trUtf8("Connection options: ") << endl;
out << trUtf8(" %1, %2\t\t List available connections in file %3.").arg(short_opts[LIST_CONNS]).arg(LIST_CONNS).arg(GlobalAttributes::CONNECTIONS_CONF + GlobalAttributes::CONFIGURATION_EXT) << endl;
out << trUtf8(" %1, %2 [ALIAS]\t Connection configuration alias to be used.").arg(short_opts[CONN_ALIAS]).arg(CONN_ALIAS) << endl;
- out << trUtf8(" %1, %2 [HOST]\t\t PostgreSQL host which a task will operate.").arg(short_opts[HOST]).arg(HOST) << endl;
+ out << trUtf8(" %1, %2 [HOST]\t\t PostgreSQL host in which a task will operate.").arg(short_opts[HOST]).arg(HOST) << endl;
out << trUtf8(" %1, %2 [PORT]\t\t PostgreSQL host listening port.").arg(short_opts[PORT]).arg(PORT) << endl;
out << trUtf8(" %1, %2 [USER]\t\t PostgreSQL username.").arg(short_opts[USER]).arg(USER) << endl;
out << trUtf8(" %1, %2 [PASSWORD]\t PostgreSQL user password.").arg(short_opts[PASSWD]).arg(PASSWD) << endl;
out << trUtf8(" %1, %2 [DBNAME]\t Connection's initial database.").arg(short_opts[INITIAL_DB]).arg(INITIAL_DB) << endl;
out << endl;
out << trUtf8("PNG and SVG export options: ") << endl;
- out << trUtf8(" %1, %2\t\t Draws the grid on the exported png image.").arg(short_opts[SHOW_GRID]).arg(SHOW_GRID) << endl;
- out << trUtf8(" %1, %2\t Draws the page delimiters on the exported png image.").arg(short_opts[SHOW_DELIMITERS]).arg(SHOW_DELIMITERS) << endl;
- out << trUtf8(" %1, %2\t\t Each page will be exported on a separated png image. (Only for PNG)").arg(short_opts[PAGE_BY_PAGE]).arg(PAGE_BY_PAGE) << endl;
- out << trUtf8(" %1, %2 [FACTOR]\t\t Applies a zoom (in percent) before export to png image. Accepted zoom interval: %3-%4 (Only for PNG)").arg(short_opts[ZOOM_FACTOR]).arg(ZOOM_FACTOR).arg(ModelWidget::MINIMUM_ZOOM*100).arg(ModelWidget::MAXIMUM_ZOOM*100) << endl;
+ out << trUtf8(" %1, %2\t\t Draws the grid in the exported image.").arg(short_opts[SHOW_GRID]).arg(SHOW_GRID) << endl;
+ out << trUtf8(" %1, %2\t Draws the page delimiters in the exported image.").arg(short_opts[SHOW_DELIMITERS]).arg(SHOW_DELIMITERS) << endl;
+ out << trUtf8(" %1, %2\t\t Each page will be exported in a separated png image. (Only for PNG images)").arg(short_opts[PAGE_BY_PAGE]).arg(PAGE_BY_PAGE) << endl;
+ out << trUtf8(" %1, %2 [FACTOR]\t\t Applies a zoom (in percent) before export to png image. Accepted zoom interval: %3-%4 (Only for PNG images)").arg(short_opts[ZOOM_FACTOR]).arg(ZOOM_FACTOR).arg(ModelWidget::MINIMUM_ZOOM*100).arg(ModelWidget::MAXIMUM_ZOOM*100) << endl;
out << endl;
out << trUtf8("DBMS export options: ") << endl;
- out << trUtf8(" %1, %2\t Ignores errors related to duplicated objects that eventually exists on server side.").arg(short_opts[IGNORE_DUPLICATES]).arg(IGNORE_DUPLICATES) << endl;
+ out << trUtf8(" %1, %2\t Ignores errors related to duplicated objects that eventually exist in the server.").arg(short_opts[IGNORE_DUPLICATES]).arg(IGNORE_DUPLICATES) << endl;
out << trUtf8(" %1, %2 [CODES] Ignores additional errors by their codes. A comma-separated list of alphanumeric codes should be provided.").arg(short_opts[IGNORE_ERROR_CODES]).arg(IGNORE_ERROR_CODES) << endl;
out << trUtf8(" %1, %2\t\t Drop the database before execute a export process.").arg(short_opts[DROP_DATABASE]).arg(DROP_DATABASE) << endl;
out << trUtf8(" %1, %2\t\t Runs the DROP commands attached to SQL-enabled objects.").arg(short_opts[DROP_OBJECTS]).arg(DROP_OBJECTS) << endl;
- out << trUtf8(" %1, %2\t\t Simulates a export process. Actually executes all steps but undoing any modification.").arg(short_opts[SIMULATE]).arg(SIMULATE) << endl;
+ out << trUtf8(" %1, %2\t\t Simulates an export process by executing all steps but undoing any modification in the end.").arg(short_opts[SIMULATE]).arg(SIMULATE) << endl;
out << trUtf8(" %1, %2\t\t Generates temporary names for database, roles and tablespaces when in simulation mode.").arg(short_opts[USE_TMP_NAMES]).arg(USE_TMP_NAMES) << endl;
out << endl;
out << trUtf8("Database import options: ") << endl;
@@ -421,13 +421,13 @@ void PgModelerCLI::showMenu(void)
out << trUtf8("Diff options: ") << endl;
out << trUtf8(" %1, %2 [DBNAME]\t The database used in the comparison. All the SQL code generated is applied to it.").arg(short_opts[COMPARE_TO]).arg(COMPARE_TO) << endl;
out << trUtf8(" %1, %2\t\t Save the generated diff code to output file.").arg(short_opts[SAVE_DIFF]).arg(SAVE_DIFF) << endl;
- out << trUtf8(" %1, %2\t\t Apply the generated diff code to the database.").arg(short_opts[APPLY_DIFF]).arg(APPLY_DIFF) << endl;
- out << trUtf8(" %1, %2\t Don't preview the generated diff code.").arg(short_opts[NO_DIFF_PREVIEW]).arg(NO_DIFF_PREVIEW) << endl;
+ out << trUtf8(" %1, %2\t\t Apply the generated diff code on the database server.").arg(short_opts[APPLY_DIFF]).arg(APPLY_DIFF) << endl;
+ out << trUtf8(" %1, %2\t Don't preview the generated diff code when applying it to the server.").arg(short_opts[NO_DIFF_PREVIEW]).arg(NO_DIFF_PREVIEW) << endl;
out << trUtf8(" %1, %2\t Drop cluster level objects like roles and tablespaces.").arg(short_opts[DROP_CLUSTER_OBJS]).arg(DROP_CLUSTER_OBJS) << endl;
out << trUtf8(" %1, %2\t\t Revoke permissions already set on the database. New permissions configured in the input model are still applied.").arg(short_opts[REVOKE_PERMISSIONS]).arg(REVOKE_PERMISSIONS) << endl;
out << trUtf8(" %1, %2\t\t Drop missing objects. Generates DROP commands for objects that are present in the input model but not in the compared database.").arg(short_opts[DROP_MISSING_OBJS]).arg(DROP_MISSING_OBJS) << endl;
out << trUtf8(" %1, %2\t Force the drop of missing columns and constraints. Causes only columns and constraints to be dropped, other missing objects aren't removed.").arg(short_opts[FORCE_DROP_COLS_CONSTRS]).arg(FORCE_DROP_COLS_CONSTRS) << endl;
- out << trUtf8(" %1, %2\t\t Rename the destination database. When the databases have different names the destination one has its name changed.").arg(short_opts[RENAME_DB]).arg(RENAME_DB) << endl;
+ out << trUtf8(" %1, %2\t\t Rename the destination database when the names of the involved databases are different.").arg(short_opts[RENAME_DB]).arg(RENAME_DB) << endl;
out << trUtf8(" %1, %2\t\t Don't drop or truncate objects in cascade mode.").arg(short_opts[NO_CASCADE_DROP_TRUNC]).arg(NO_CASCADE_DROP_TRUNC) << endl;
out << trUtf8(" %1, %2\t Truncate tables prior to alter columns. Avoids errors related to type casting when the new type of a column isn't compatible to the old one.").arg(short_opts[TRUNC_ON_COLS_TYPE_CHANGE]).arg(TRUNC_ON_COLS_TYPE_CHANGE) << endl;
out << trUtf8(" %1, %2\t Don't reuse sequences on serial columns. Drop the old sequence assigned to a serial column and creates a new one.").arg(short_opts[NO_SEQUENCE_REUSE]).arg(NO_SEQUENCE_REUSE) << endl;
@@ -1344,6 +1344,15 @@ void PgModelerCLI::diffModelDatabase(void)
diff_hlp.setDiffOption(ModelsDiffHelper::OPT_DONT_DROP_MISSING_OBJS, !parsed_opts.count(DROP_MISSING_OBJS));
diff_hlp.setDiffOption(ModelsDiffHelper::OPT_DROP_MISSING_COLS_CONSTR, !parsed_opts.count(FORCE_DROP_COLS_CONSTRS));
+ if(!parsed_opts[PGSQL_VER].isEmpty())
+ diff_hlp.setPgSQLVersion(parsed_opts[PGSQL_VER]);
+ else
+ {
+ extra_connection.connect();
+ diff_hlp.setPgSQLVersion(extra_connection.getPgSQLVersion(true));
+ extra_connection.close();
+ }
+
printMessage(trUtf8("Comparing the generated models..."));
diff_hlp.diffModels();
@@ -1374,9 +1383,10 @@ void PgModelerCLI::diffModelDatabase(void)
QString res, buff, line;
QTextStream in(stdin), preview;
+ buff += "\n** Press ENTER to scroll the preview **\n";
buff += "\n### DIFF PREVIEW ###\n\n";
buff += diff_hlp.getDiffDefinition();
- buff += "\n### END PREVIEW ###\n\n";
+ buff += "\n### END OF PREVIEW ###\n\n";
preview.setString(&buff, QIODevice::ReadOnly);
@@ -1397,7 +1407,7 @@ void PgModelerCLI::diffModelDatabase(void)
}
out << endl;
- out << trUtf8("** WARNING: you are about to apply the generated SQL code to the server! Data can be lost in the process.") << endl;
+ out << trUtf8("** WARNING: You are about to apply the generated diff code to the server. Data can be lost in the process!") << endl;
do
{
diff --git a/schemas/alter/truncate.sch b/schemas/alter/truncate.sch
index f7b26cbb44..39a822b513 100644
--- a/schemas/alter/truncate.sch
+++ b/schemas/alter/truncate.sch
@@ -5,9 +5,14 @@
[TRUNCATE ] {sql-object} $sp {signature}
+%if {restart-seq} %then
+ [ RESTART IDENTITY ]
+%end
+
%if {cascade} %then
- [ CASCADE]
- %end
- ;
+ [ CASCADE]
+%end
+
+;
$br [-- ddl-end --] $br
diff --git a/schemas/catalog/usertype.sch b/schemas/catalog/usertype.sch
index 155838171a..f0c8175641 100644
--- a/schemas/catalog/usertype.sch
+++ b/schemas/catalog/usertype.sch
@@ -3,7 +3,7 @@
# Code generation can be broken if incorrect changes are made.
%if {list} %then
- [SELECT tp.oid, replace(tp.oid::regtype::text, ns.nspname || '.', '') AS name FROM pg_type AS tp ]
+ [SELECT tp.oid, replace(replace(tp.oid::regtype::text,'"', ''), ns.nspname || '.', '') AS name FROM pg_type AS tp ]
[ LEFT JOIN pg_namespace AS ns ON tp.typnamespace = ns.oid ]
%if {schema} %then
@@ -34,7 +34,7 @@
%else
%if {attribs} %then
- [SELECT tp.oid, replace(tp.oid::regtype::text, ns.nspname || '.', '') AS name, tp.typnamespace AS schema, tp.typowner AS owner, ]
+ [SELECT tp.oid, replace(replace(tp.oid::regtype::text,'"', ''), ns.nspname || '.', '') AS name, tp.typnamespace AS schema, tp.typowner AS owner, ]
#Retrieve the OID for table/view/sequence that generates the composite type
[ (SELECT
diff --git a/schemas/sql/dbmodel.sch b/schemas/sql/dbmodel.sch
index 722d21f128..4642eecdb9 100644
--- a/schemas/sql/dbmodel.sch
+++ b/schemas/sql/dbmodel.sch
@@ -25,14 +25,14 @@ $br $br
%if {role} %then {role} %end
%if {tablespace} %then
- [-- Tablespaces creation must be done outside an multicommand file.] $br
- [-- These commands were put in this file only for convenience.] $br
+ [-- Tablespaces creation must be done outside a multicommand file.] $br
+ [-- These commands were put in this file only as a convenience.] $br
{tablespace} $br
%end
$br
- [-- Database creation must be done outside an multicommand file.] $br
- [-- These commands were put in this file only for convenience.] $br
+ [-- Database creation must be done outside a multicommand file.] $br
+ [-- These commands were put in this file only as a convenience.] $br
{database} $br
%end
diff --git a/schemas/sql/table.sch b/schemas/sql/table.sch
index dcbdfd89c4..fe953bf77f 100644
--- a/schemas/sql/table.sch
+++ b/schemas/sql/table.sch
@@ -33,12 +33,15 @@
%if %not {constr-sql-disabled} %and {constraints} %then [,] $br %end
%end
+
+ %if {inh-columns} %then
+ $br {inh-columns}
+ %end
- %if {inh-columns} %then {inh-columns} %end
-
- %if {constraints} %then
+ %if {constraints} %then
{constraints}
%end
+
%end
$br )
diff --git a/tests/src/linenumberstest/linenumberstest.cpp b/tests/src/linenumberstest/linenumberstest.cpp
new file mode 100644
index 0000000000..8fe9823259
--- /dev/null
+++ b/tests/src/linenumberstest/linenumberstest.cpp
@@ -0,0 +1,90 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2018 - Raphael Araújo e Silva
+#
+# 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 version 3.
+#
+# 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.
+#
+# The complete text of GPLv3 is at LICENSE file on source code root directory.
+# Also, you can get the complete GNU General Public License at
+*/
+
+#include
+#include "numberedtexteditor.h"
+#include
+#include
+
+class LineNumbersTest: public QObject {
+ private:
+ Q_OBJECT
+
+ private slots:
+ void handleLineSelectionUsingMouse(void);
+};
+
+void LineNumbersTest::handleLineSelectionUsingMouse(void)
+{
+ QDialog *dlg=new QDialog;
+ NumberedTextEditor *edt=new NumberedTextEditor(dlg);
+ QHBoxLayout *layout=new QHBoxLayout(dlg);
+
+ LineNumbersWidget::setColors(Qt::darkGray, QColor(230,230,230));
+ layout->addWidget(edt);
+ dlg->setMinimumSize(640,220);
+
+ edt->setPlainText("--\n\
+-- PostgreSQL database dump\n\
+--\n\
+-- Dumped from database version 9.4.4\n\
+-- Dumped by pg_dump version 9.4.4\n\
+-- Started on 2015-07-20 19:24:52 WEST\n\
+\n\
+SET statement_timeout = 0;\n\
+SET lock_timeout = 0;\n\
+SET client_encoding = 'UTF8';\n\
+SET standard_conforming_strings = on;\n\
+SET check_function_bodies = false;\n\
+SET client_min_messages = warning;\n\
+--\n\
+-- PostgreSQL database dump\n\
+--\n\
+-- Dumped from database version 9.4.4\n\
+-- Dumped by pg_dump version 9.4.4\n\
+-- Started on 2015-07-20 19:24:52 WEST\n\
+SET statement_timeout = 0;\n\
+SET lock_timeout = 0;\n\
+SET client_encoding = 'UTF8';\n\
+SET standard_conforming_strings = on;\n\
+SET check_function_bodies = false;\n\
+SET client_min_messages = warning;\n\
+-- Dumped from database version 9.4.4\n\
+-- Dumped by pg_dump version 9.4.4\n\
+-- Started on 2015-07-20 19:24:52 WEST\n\
+SET statement_timeout = 0;\n\
+SET lock_timeout = 0;\n\
+SET client_encoding = 'UTF8';\n\
+SET standard_conforming_strings = on;\n\
+SET check_function_bodies = false;\n\
+SET client_min_messages = warning;\n\
+-- Dumped from database version 9.4.4\n\
+-- Dumped by pg_dump version 9.4.4\n\
+-- Started on 2015-07-20 19:24:52 WEST\n\
+SET statement_timeout = 0;\n\
+SET lock_timeout = 0;\n\
+SET client_encoding = 'UTF8';\n\
+SET standard_conforming_strings = on;\n\
+SET check_function_bodies = false;\n\
+SET client_min_messages = warning;");
+
+ dlg->exec();
+}
+
+QTEST_MAIN(LineNumbersTest)
+#include "linenumberstest.moc"
diff --git a/tests/src/linenumberstest/linenumberstest.pro b/tests/src/linenumberstest/linenumberstest.pro
new file mode 100644
index 0000000000..728f7a5aa1
--- /dev/null
+++ b/tests/src/linenumberstest/linenumberstest.pro
@@ -0,0 +1,3 @@
+include(../../tests.pri)
+SOURCES += linenumberstest.cpp
+
diff --git a/tests/tests.pro b/tests/tests.pro
index 6e60d5c27b..b8020f0218 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -8,9 +8,10 @@
# refactored code, containing almost all changes done by the refactoring author.
TEMPLATE = subdirs
SUBDIRS = src/main \
- src/baseobjecttest \
- src/roletest \
- src/syntaxhighlightertest \
- src/databasemodeltest \
- src/schemaparsertest
+src/baseobjecttest \
+src/roletest \
+src/syntaxhighlightertest \
+src/databasemodeltest \
+src/schemaparsertest \
+src/linenumberstest \