diff --git a/CHANGELOG.md b/CHANGELOG.md index 29cbe3281..005b7d7ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,185 @@ 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
+ +* [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 missing SQL keywords into sql-highlight.conf +* [New] Added support to multi line comments in UI. +* [New] Added code snippets for CREATE and ALTER policy. +* [New] Added full support to row level security (RLS), including export, import and diff of this kind of object. +* [New] Added the method DatabaseExplorerWidget::formatPolicyAttribs in order to display some attributes values correctly. +* [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 the ability to generate diff code to Enable/Force RLS attribute of tables. +* [New] Added support to RLS on tables. +* [New] Added the support to detect identity columns in diff. +* [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] The filter widget is now toggled in DatabaseExplorerWidget via filter menu. +* [Change] Minor adjustments on forms sizes. +* [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] Minor improvements on catalog queries for index, trigger, rule, policy, constraint in order to use the comment catalog query. +* [Change] Removed an uneeded form adjustment code in Table::openEditingForm. +* [Change] Minor improvements on DatabaseModel::getCreationOrder. +* [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. +* [Change] Improved the model loading on macOs in such way to avoid showing the visual objects creation while they are being loaded from file. +* [Change] Improved the reverse engineering and diff process to accept the new attributes of database object. +* [Fix] Fixed the query catalog for built-in types to include the types related to domains. +* [Fix] Fixed the Extension::setSchema method to accept null schemas. +* [Fix] Fixed the generation of XML code for casts. +* [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] Minor fix in ObjectDepsRefsWidget to correctly list the indirect references. +* [Fix] Fixed a bug when dropping Functions in DatabaseExplorerWidget. +* [Fix] Improved the import of sequences in such way to avoid unsolvable reference breaking. +* [Fix] Fixed a bug that cause 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 the import of sequences which now assigns owner columns correctly. If the owner column is an identity one the SQL code of the sequence is disabled by default which will not cause confusion in the diff process trying to drop it in some cases. +* [Fix] Fixed an issue in diff process that was generating a malformed DROP command for extensions. +* [Fix] Minor fixed in the "Filter by OID" feature in DatabaseExplorerWidget and DatabaseImportForm. +* [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. + +v0.9.1-beta +------ +Release date: January 26, 2018
+ +* [New] Added support to GROUP BY/HAVING clauses in Views by adding a new kind of reference. Proper changes done in ViewWidget to allow configuring those clauses. +* [New] Added the method Catalog::isSystemObject(oid) which indicates if the provided OID is related to a system object. +* [Change] Minor adjustment in the copy/paste operation to generate suffix in the pasted objects only when there're conflics. +* [Change] Removed the port range limitation in connection configuration dialog. +* [Change] Updated the default version of Qt and PostgreSQL to, respectively, 5.9.3 and 10.1 in deployment scripts. +* [Change] Changed the method PgSQLType::getTypeName by adding a bool parameter so the name can be returned with dimension descriptor (when dimension is > 0). Useful for configuring operator's signatures. +* [Fix] Fixed the drop action for materialized views in database explorer. +* [Fix] Fixed a crash when importing extension objects. +* [Fix] Fixed the generation of operator's signature that must consider dimensions of the arguments' types. +* [Fix] Fixed the bounding rect calculation for relationship instances when one or more labels are hidden. +* [Fix] Fixed the SVG & PNG export to properly determine the area to be drawn in the destination graphics file. +* [Fix] Fixed a crash when adding attributes into many-to-many relationships. + +v0.9.1-alpha1 +------ +Release date: November 30, 2017
+ +* [New] Added the ability to compare two databases, and not only a model and a database, in diff tool. +* [New] Added the relationship creation buttons on the object overlay when a single table is selected. +* [New] Added the "Relationship" action in "New" submenu on table's popup menu so the user can create relationships using the selected table as source. This avoids the need to use blank areas of the canvas to start creating relationships. +* [New] Improved the data manipulation dialog in such way that when dealing with deletes in tables without PK, tuples with NULL values can be correctly considered. +* [New] Improved the validations on ResultSet class. +* [New] Added a method to indicate if a column value is null in ResultSet. +* [New] Added support to fade in/out objects in object finder in order to highlight the graphical objects retrieved from the search. +* [New] Added an attribute in pgmodeler.conf to store the current status of the "Fade in" button in object finder widget. +* [Change] Minor improvement in the diff generated metadata. +* [Change] Increased the maximum allowed amount of lines in command history. +* [Change] Minor adjustment on diff tool so the connections combo can be correctly updated when the user edit connections from within that form. +* [Change] Improved the progress info of diff process so it can be more accurate. +* [Fix] Fixed the way PostgreSQL 10+ version is returned from Connection::getPgSQLVersion. +* [Fix] Fixed the sequence importing on PostgreSQL 10. + +v0.9.1-alpha +------ +Release date: October 20, 2017
+ +* [New] Added support to crow's foot notation. +* [New] Added the crow's foot notation switch in RelationshipConfigWidget. +* [New] Added the grid arrangement in the arrangment menu at MainWindow. +* [New] Added the schema arrangement (scattered). +* [New] Added an action to toggle schemas rectangle on ModelWidget. +* [New] CLI now loads the relationship and general settings to reflect relationship styles in export modes. +* [New] Added support to connect relatinship on tables' edges when using classical notation. +* [New] Added support to apostrophes in the middle of object's name. +* [Change] Removed the controls related to arragement in DatabaseImportForm. +* [Change] Minor adjustments in tables' spacing in auto arrangement process. +* [Change] Minor improvement on SQLExecutionWidget and DataManipulationForm in order to make possible to paste csv buffer from SQLExecutionWidget to DataManipulationForm. +* [Change] Improvements done in the Spanish UI translation. +* [Change] Changed the position of the zoom info icon in SceneInfoWidget. +* [Change] Minor adjustments in the pen width of relationship lines and objects borders. +* [Change] Minor improvement when aligning objects to grid forcing the relationships updating. +* [Change] Minor arrangement of the connection modes in RelationshipConfigWidget. +* [Change] Improved the performance of (de)selection of several objects at once in ModelWidget and ObjectsScene. +* [Change] Removed unused attributes from BezierCurveItem. +* [Change] Improved the BezierCurveItem class to enable the drawing of inverted curve by inverting its bounding rect. +* [Change] Improved the import of index objects. +* [Change] Minor tweak to enable clipboard usage in macOS when copying data in DataManipulationForm. +* [Fix] Fixed a bug in ObjectsScene that was not emitting signals of deselection correctly. +* [Fix] Fixed a bug in SQLToolWidget that was not cleaning up the source code pane when all databases were disconnected. +* [Fix] Fixed a bug that was causing the diff process to try to remove the not null constraint of a primary key. +* [Fix] Fixed a bug that was causing relationship line to be wrongly constructed in case the tables bounding rects don't intercepted. +* [Fix] Fixed a bug that was recognizing the creation of a constraint but wasn't generating the SQL in diff process. +* [Fix] Minor fix in order to avoid the inheritance/dependency descriptor to be rotated to the wrong size when curved lines are being used. +* [Fix] Fixed the generation of sql comments for database and tablespace. +* [Fix] Minor fix in example.dbm +* [Fix] Fixed the configuration of bidirectional fk relationships when crow's foot is enabled. +* [Fix] Fix a bug in GeneralConfigWidget that was reverting the grid optins everytime the user applyed settings. +* [Fix] Fixed the genaration of index elements containing expressions. +* [Fix] Fixed the import of operators and operator classes. +* [Fix] Fixed the generation of operator signature by removing the length/precision of the types. +* [Fix] Minor fix in CSVLoadWidget::loadCsvFromBuffer in order to preserve the line breaks avoiding the creation of unecessary lines. +* [Fix] Fixed the import of exclude constraint. +* [Fix] Fixed the import of timestamp(0) type. + v0.9.0 ------ Release date: September 1st, 2017
diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b69365c02..f77074d8b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,31 +1,49 @@ -v0.9.0 +v0.9.1 ------ -Release date: September 1st, 2017
-Changes since: v0.9.0-beta2
- -Summary: after one year and three months of hard work we finally have the stable release 0.9.0. This version does not bring extraordinary changes or improvements compared to the alphas and betas but it closes one more development cycle delivering an even more refined product to our users. In order to give an idea on how pgModeler have changed since last year if we place togheter all change logs from the beggining of 0.9.0 development we would have: 175 log entries being 51 new features, 58 changes/improvements, 68 bug fixes. These numbers only indicates how the project is being constantly enhanced through the years.
- -About some of the new features, pgModeler now supports curved relationship lines in order to improve the model's visualization. By default, for new installations, this option comes activated but it can be toggled in the general settings. Another feature requested long ago and now is available is the ability to choose the UI language instead of rely only in the OS default language. One more enhacement is the possibility of copying and pasting text from one data manipulation dialog to another. This comes to be handy mainly when the user needs to copy data between tables when they reside in different databases.
- -Finally, small fixes and changes have been implemented as you can see below. The complete change history is in the file CHANGELOG.md.
- -* [New] Added the ability to paste text from clipboard to data grid in DataManipulationForm. -* [New] Added a new sample model donated by the maintainers of 3D City DB project. -* [New] Added the language "internal" to the set of system languages available when creating a new model. -* [New] Added support to override the default language settings via GeneralConfigWidget. -* [New] Added support to toggle curved relationship lines in GeneralConfigWidget. -* [Change] Improved the MetadataHandlingForm enabling user to only extract metada to a backup file. -* [Change] Minor adjustments in the graphical points when relationships are selected. -* [Change] Changed the default action to reset label's position from middle button click to Alt + Ctrl + left click. -* [Change] Minor enhancement in auto arrange feature to avoid breaking lines when curved relationship lines are enabled. -* [Change] Minor adjustment in the methods which automatically resize dialogs depending on the resolution. -* [Change] Changed the default font for objects and source code. -* [Fix] Fixed the catalog query for event triggers. -* [Fix] Fixed the icons and labels of the "Select all" submenu in ModelWidget. -* [Fix] Fixed a rare crash when configuring self relationships. -* [Fix] Minor fix when rendering self n:n relationships. -* [Fix] Minor fix in the HintTextWidget to resize more properly according to the held text. -* [Fix] Minor fix in default confs for source code font style. -* [Fix] Fixed the generation of objects style configuration file that was missing constraints settings. -* [Fix] Fixed a bug in the index / exclude constraint import which was not creating expressions of these objects correctly and sometimes trucating them. +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/example.dbm b/conf/defaults/example.dbm index b6a7c933f..38f936f7c 100644 --- a/conf/defaults/example.dbm +++ b/conf/defaults/example.dbm @@ -3,7 +3,7 @@ CAUTION: Do not modify this file unless you know what you are doing. Unexpected results may occur if the code is changed deliberately. --> - + @@ -36,7 +36,7 @@ CAUTION: Do not modify this file unless you know what you are doing. - +
@@ -65,9 +65,9 @@ CAUTION: Do not modify this file unless you know what you are doing. -
+
- + @@ -159,7 +159,7 @@ CAUTION: Do not modify this file unless you know what you are doing. -
+
diff --git a/conf/defaults/pgmodeler.conf b/conf/defaults/pgmodeler.conf index 24dc553cf..38405c783 100644 --- a/conf/defaults/pgmodeler.conf +++ b/conf/defaults/pgmodeler.conf @@ -39,7 +39,7 @@ history-max-length="1000" use-curved-lines="true"/> - + diff --git a/conf/defaults/snippets.conf b/conf/defaults/snippets.conf index bf3e252fd..b53b039f9 100644 --- a/conf/defaults/snippets.conf +++ b/conf/defaults/snippets.conf @@ -298,6 +298,22 @@ $br + + + + + + + + @@ -857,5 +873,5 @@ $br [FROM ] $ob $sp {role} [ | PUBLIC ] $cb $sp $br $ob [ CASCADE | RESTRICT ] $cb $br]]> - + diff --git a/conf/defaults/sql-highlight.conf b/conf/defaults/sql-highlight.conf index 5b321ed82..b02abf031 100644 --- a/conf/defaults/sql-highlight.conf +++ b/conf/defaults/sql-highlight.conf @@ -20,7 +20,8 @@ - + + @@ -54,10 +55,17 @@ - - + + + + + + + @@ -112,6 +121,7 @@ + @@ -186,10 +196,12 @@ + + @@ -219,7 +231,9 @@ + + @@ -229,6 +243,7 @@ + @@ -274,6 +289,8 @@ + + diff --git a/conf/dtd/pgmodeler.dtd b/conf/dtd/pgmodeler.dtd index 4e6a070b7..51768e16d 100644 --- a/conf/dtd/pgmodeler.dtd +++ b/conf/dtd/pgmodeler.dtd @@ -61,7 +61,8 @@ - + + diff --git a/conf/dtd/relationships.dtd b/conf/dtd/relationships.dtd index 0fed4fb17..08590b5eb 100644 --- a/conf/dtd/relationships.dtd +++ b/conf/dtd/relationships.dtd @@ -5,7 +5,7 @@ - + diff --git a/conf/dtd/snippets.dtd b/conf/dtd/snippets.dtd index d4af0195d..56ec1c01a 100644 --- a/conf/dtd/snippets.dtd +++ b/conf/dtd/snippets.dtd @@ -13,5 +13,5 @@ + extension|eventtrigger|general|policy) "general"> diff --git a/conf/example.dbm b/conf/example.dbm index b6a7c933f..38f936f7c 100644 --- a/conf/example.dbm +++ b/conf/example.dbm @@ -3,7 +3,7 @@ CAUTION: Do not modify this file unless you know what you are doing. Unexpected results may occur if the code is changed deliberately. --> - + @@ -36,7 +36,7 @@ CAUTION: Do not modify this file unless you know what you are doing. -
+
@@ -65,9 +65,9 @@ CAUTION: Do not modify this file unless you know what you are doing. -
+
- + @@ -159,7 +159,7 @@ CAUTION: Do not modify this file unless you know what you are doing. -
+
diff --git a/conf/pgmodeler.conf b/conf/pgmodeler.conf index 24dc553cf..38405c783 100644 --- a/conf/pgmodeler.conf +++ b/conf/pgmodeler.conf @@ -39,7 +39,7 @@ history-max-length="1000" use-curved-lines="true"/> - + diff --git a/conf/schemas/widget.sch b/conf/schemas/widget.sch index 05c20f90a..95626c56f 100644 --- a/conf/schemas/widget.sch +++ b/conf/schemas/widget.sch @@ -13,7 +13,8 @@ $tb [ + + + + + + + + @@ -857,5 +873,5 @@ $br [FROM ] $ob $sp {role} [ | PUBLIC ] $cb $sp $br $ob [ CASCADE | RESTRICT ] $cb $br]]> - + diff --git a/conf/sql-highlight.conf b/conf/sql-highlight.conf index 5b321ed82..b02abf031 100644 --- a/conf/sql-highlight.conf +++ b/conf/sql-highlight.conf @@ -20,7 +20,8 @@ - + + @@ -54,10 +55,17 @@ - - + + + + + + + @@ -112,6 +121,7 @@ + @@ -186,10 +196,12 @@ + + @@ -219,7 +231,9 @@ + + @@ -229,6 +243,7 @@ + @@ -274,6 +289,8 @@ + + diff --git a/conf/ui-style.conf b/conf/ui-style.conf index 0320e1a21..cc481818e 100644 --- a/conf/ui-style.conf +++ b/conf/ui-style.conf @@ -34,12 +34,14 @@ UpdateNotifierWidget > 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/crashhandler/src/crashhandlerform.cpp b/crashhandler/src/crashhandlerform.cpp index aaec14623..64452c5fa 100644 --- a/crashhandler/src/crashhandlerform.cpp +++ b/crashhandler/src/crashhandlerform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/crashhandler/src/crashhandlerform.h b/crashhandler/src/crashhandlerform.h index 5d823a9b0..c30f91379 100644 --- a/crashhandler/src/crashhandlerform.h +++ b/crashhandler/src/crashhandlerform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/crashhandler/src/main.cpp b/crashhandler/src/main.cpp index fd27b7aa5..902b7ca63 100644 --- a/crashhandler/src/main.cpp +++ b/crashhandler/src/main.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/lang/es_ES.qm b/lang/es_ES.qm index e7f34c9a5..15fab2a28 100644 Binary files a/lang/es_ES.qm and b/lang/es_ES.qm differ diff --git a/lang/es_ES.ts b/lang/es_ES.ts index 862eacfb2..2ea09f6e3 100644 --- a/lang/es_ES.ts +++ b/lang/es_ES.ts @@ -6,7 +6,7 @@ About pgModeler - Acerca del pgModeler + Acerca de pgModeler @@ -16,26 +16,18 @@ 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. - Abrir herramienta de modelado de datos de origen diseñado para PostgreSQL. No más comandos DDL escritas a mano, permiten pgModeler hacer el trabajo para usted! Este software reúne los conceptos de diagramas entidad-relación y las características que PostgreSQL implementa como una extensión de los estándares SQL. + Herramienta de modelado de datos de código abierto diseñada para PostgreSQL. ¡No más comandos de DDL escritos a mano, deje a pgModeler hacer el trabajo para usted! Este software reúne los conceptos de diagramas entidad-relación y las características que PostgreSQL implementa como extensiones de estándares SQL. Design, configure, deploy Diseño, configurar, implementar - - <html><head/><body><p><a href="http://pgmodeler.com.br"><span style=" font-size:11pt; font-style:italic; text-decoration: underline; color:#0057ae;">http://pgmodeler.com.br</span></a></p></body></html> - <html><head/><body><p><a href="http://pgmodeler.com.br"><span style=" font-size:11pt; font-style:italic; text-decoration: underline; color:#0057ae;">http://pgmodeler.com.br</span></a></p></body></html> - pgModeler is proudly a brazilian software! pgModeler es orgullosamente un programa brasileño! - - <html><head/><body><p>Copyright 2006-2015 - Raphael Araújo e Silva &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.com.br</span></a>&gt;</p></body></html> - <html><head/><body><p>Copyright 2006-2015 - Raphael Araújo e Silva &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.com.br</span></a>&gt;</p></body></html> - <a href="http://pgmodeler.com.br">http://pgmodeler.com.br</a> @@ -44,7 +36,7 @@ <html><head/><body><p>Copyright 2006-2016 - Raphael Araújo e Silva &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.com.br</span></a>&gt;</p></body></html> - <html><head/><body><p>Copyright 2006-2015 - Raphael Araújo e Silva &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.com.br</span></a>&gt;</p></body></html> {2006-2016 ?} {0057a?} + <html><head/><body><p>Copyright 2006-2015 - Raphael Araújo e Silva &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.com.br</span></a>&gt;</p></body></html> @@ -62,205 +54,217 @@ 0.0.0.0 - - (CODE_NAME) - (NOMBRE_CÓDIGO) - - - + Build: Contruido: - + (BUILD_NUM) (NUM_CONSTRUIDO) - + License Licencia - + Contributors Colaboradores - + <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> - <html><head/><body><p>Esta página está dedicada a todos los colaboradores que dieron un poco de su tiempo en hacer pgModeler un mejor software de alguna manera. La lista completa de las personas que ayudó pgModeler se puede encontrar en <a href="https://github.com/pgmodeler/pgmodeler/graphs/contributors"><span style=" text-decoration: underline; color:#00a489;">GitHub</span></a>.</p><p>Si usted tiene una gran idea para mejorar pgModeler favor enviarlo <a href="http://github.com/pgmodeler/pgmodeler/issues"><span style=" text-decoration: underline; color:#00a489;">here</span></a>. ¿No hay ideas por ahora, pero quiere ayudar? Por qué no donar un poco de dinero <a href="http://pgmodeler.com.br/#donate"><span style=" text-decoration: underline; color:#00a489;">here</span></a>!?</p></body></html> + <html><head/><body><p>Esta página está dedicada a todos los colaboradores que dieron un poco de su tiempo en hacer pgModeler un mejor software de alguna manera. La lista completa de las personas que ayudó pgModeler se puede encontrar en <a href="https://github.com/pgmodeler/pgmodeler/graphs/contributors"><span style=" text-decoration: underline; color:#00a489;">GitHub</span></a>.</p><p>Si usted tiene una gran idea para mejorar pgModeler favor enviarlo <a href="http://github.com/pgmodeler/pgmodeler/issues"><span style=" text-decoration: underline; color:#00a489;">aquí</span></a>. ¿Sin ideas por ahora, pero quiere ayudar? Por qué no donar un poco de dinero <a href="http://pgmodeler.com.br/#donate"><span style=" text-decoration: underline; color:#00a489;">aquí</span></a>!?</p></body></html> - + 1 1 - + 2 2 - + 3 3 - + 4 4 - + 5 5 - + 6 6 - + 7 7 - + 8 8 - + + 9 + 9 + + + Name - Nombe + Nombre - + Country País - + Contribution Contribución - + Damien Degois Damien Degois - - - + + + France Francia - + French UI translation and several improvements in auxiliary scripts. Traducción de IU francés y varias mejoras en scripts auxiliares. - + Ji Bin Ji Bin - + China China - + Chinese UI translation and small fixes. Traducción de IU chino y pequeñas correcciones. - + Pierre-Samuel LE STANG Pierre-Samuel LE STANG - - + + French UI translation. Traducción de IU al francés. - + Lisandro Damián Nicanor Lisandro Damián Nicanor - + Argentina Argentina - + Improvements on build scripts enabling the custom packaging in Linux distros; Per-user settings; pgModeler's package maintainer in Debian Linux. Mejoras en scripts de construcción que permitan el embalaje personalizado en distribuciones de Linux; Por usuario ajustes; pgModeler y apos; s mantenedor de paquetes en Debian Linux. - + Pavel Alexeev Pavel Alexeev - + Russia Rusia - + Additional work for packaging in Linux distros; pgModeler's package maintainer in Fedora Linux. El trabajo adicional para el empaquetado en la distribuciones de Linux; pgModeler's empaquetador de paquetes en Fedora Linux. - + Mariusz Fik Mariusz Fik - + Poland Polonia - + Custom packaging first ideas. Tester of first version of custom packaging patch. Empaquetados hechos a medida primeras ideas. Probador de primera versión del parche de empaquetados personalizados. - + Jonathan DUPRE - + Gilberto Castillo - + Cuba - + Spanish UI translation. + + + +Danúbio Viana Nogueira + + + + + Brazil + + + + + Brazilian Portuguese UI translation. + + AggregateWidget - - Form - Formulario - Final Function: @@ -294,7 +298,7 @@ Input Data Type - Tipo de Dados de Entrada + Tipo de Datos de Entrada @@ -302,7 +306,7 @@ Tipo de Dato de Estado - + An aggregate function that accepts the types <em><strong>typeA</strong></em> and <em><strong>typeB</strong></em> as input types and which type of state is <em><strong>state_type</strong></em>, must obey the following rules: <br/><br/> <strong> &nbsp;&nbsp;&nbsp;• Final Function:</strong> <em>void final_function(<strong>state_type</strong>)</em><br/> <strong> &nbsp;&nbsp;&nbsp;• Transition Function:</strong> <em><strong>state_type</strong> transition_function(<strong>state_type</strong>, <strong>typeA</strong>, <strong>typeB</strong>)</em> Una función de agregación que acepta los tipos <em><strong>tipoA</strong></em> y <em><strong>tipoB</strong></em> como entrada y cuyo tipo de estado sea <em><strong>tipo_estado</strong></em>, debe obedecer a la seguintes reglas:<br/><br/> <strong> &nbsp;&nbsp;&nbsp;• Función Final:</strong> <em>void funcao_final(<strong>tipo_estado</strong>)</em><br/> <strong> &nbsp;&nbsp;&nbsp;• Función Transición:</strong> <em><strong>tipo_estado</strong> funcao_transicao(<strong>tipo_estado</strong>, <strong>tipoA</strong>, <strong>tipoB</strong>)</em> @@ -416,181 +420,191 @@ + Constraint: Name + + + + + Constraint: Descriptor + + + + View: Schema name Vista: Nombre de esquema - + View: View name Vista: Nombre de vista - + View: References box Vista: Cuadro de referéncias - + View: Extended attributes box Vista: Cuadro de atributos extendidos - + View: Title box Vista: Cuadro de título - + View: Table / columns alias Vista: Tabla / columna alias - + View: Referenced column Vista: Columna referenciada - + View: Referenced table Vista: Tabla referenciada - + View: Reference descriptor Vista: Descritor de Referencia - + Textbox: Body Cuadro de Texto: Cuerpo - + Column: Column name Columna: Nombre de columna - + Column: Descriptor Columna: Descritor - + Column: Included / Inherited by relationship Columna: Incluída / Herendado por relación - + Column: Protected Columna: Protegida - + Column (pk): Column name Columna (pk): Nombre de columna - + Column (pk): Descriptor Columna (fk): Descritor - + Column (fk): Column name Columna (fk): Nombre de columna - + Column (fk): Descriptor Columna (fk): Descritor - + Column (uq): Column name Columna (uq): Nombre de columna - + Column (uq): Descriptor Columna (uq): Descritor - + Column (nn): Column name Columna (nn): Nombre de columna - + Column (nn): Descriptor Columna (nn): Descritor - + Relationship: Descriptor Relación: Descritor - + Relationship: Label text Relación: Texto etiqueta - + Relationship: Label box Relación: Cuadro etiqueta - + Relationship: Attribute text Relación: Texto del atributo - + Relationship: Attribute descriptor Relación: Descritor del atributo - + Tag: Name Tag: Nombre - + Tag: Body Tag: Cuerpo - + Placeholder: Body - + Font: Fuente: - + Colors: Colores: - + pt pt - + Underline Subrayar - + Italic Itálico - + Bold Negrito @@ -598,16 +612,24 @@ Application - + Unknown exception caught! - Excepción desconocido capturada! + Excepción desconocida capturada! - + Failed to create initial configuration in `%1'! Check if the current user has write permission over that path and at least read permission over `%2'. No se pudo crear la configuración inicial en `%1'! Compruebe si el usuario actual tiene permiso de escritura sobre ese camino y al menos permiso de lectura sobre `%2'. + + BaseConfigWidget + + + A backup of the previous settings was saved into <strong>%1</strong>! + Se guardó una copia de seguridad de la configuración anterior en <strong>%1</strong>! + + BaseForm @@ -632,9 +654,9 @@ &Ok - + %1 properties - + %1 propiedades @@ -799,6 +821,11 @@ Basic Relationship Relación básica + + + Generic SQL + + new_object @@ -811,17 +838,13 @@ BaseObjectView - + SQL off SQL off BaseObjectWidget - - Form - Formulario - Name: @@ -845,7 +868,7 @@ Edit object's permissions - Editar permisos de Objeto's + Editar permisos del objeto @@ -855,7 +878,7 @@ This object is protected thus no change in form will be applied to it. - Este objeto está protegido por lo tanto no hay cambio en la forma se aplicará a la misma. + @@ -887,7 +910,7 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. Owner: - Dueño: + Propietario: @@ -900,32 +923,25 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.icone - Create / Edit: - Crear / Editar: - - - + Required field. Leaving this empty will raise errors! Campo requerido. Dejando este vacío elevará errores! - + Value(s) Valor(es) - + Version Versión - + The <em style='color: %1'><strong>highlighted</strong></em> fields in the form or one of their values are available only on specific PostgreSQL versions. Generating SQL code for versions other than those specified in the fields' tooltips may create incompatible code. - - - - The <em style='color: %1'><strong>highlighted</strong></em> fields on the form are available only on specific PostgreSQL versions. When generating SQL code for versions other than those specified on fields' tooltips pgModeler will ignore their values. - El <em style='color: %1'><strong>highlighted</strong></em> campos del formulario están disponibles sólo en las versiones específicas de PostgreSQL. Al generar código SQL para versiones distintas de las especificadas en los campos y apos; información sobre herramientas pgModeler ignorará sus valores. + Los campos <em style ='color: %1'><strong>resaltados</strong></em> en el formulario o uno de sus valores sólo están disponibles en versiones específicas de PostgreSQL. + Generar código SQL para versiones distintas a las especificadas en las sugerencias de los campos puede crear código incompatible. @@ -936,6 +952,19 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.rel_%1_%2 + + BaseTableView + + + Toggles the extended attributes display + + + + + Connected rels: %1 + Rels conectados: %1 + + BugReportForm @@ -999,10 +1028,6 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.Database Model Base de datos del modelo - - In none occasion the models sent within the report will be published. They are kept safe and are used only for debug purpose. - En ninguna ocasión se publicarán los modelos enviados dentro del informe. Ellos están a salvo y sólo se utilizan para fines de depuración. - Attach the below database model file to be debugged. @@ -1036,23 +1061,15 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. CastWidget - - Form - Formulario - - - Implicit - Implícita - I&mplicit - + I&mplícito Assignment - Atribuición + Asignación @@ -1072,11 +1089,7 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. E&xplicit - - - - Explicit - Explícito + E&xplícito @@ -1094,62 +1107,32 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.La función que se asignará a una conversión de <em><strong>typeA</strong></em> a <em><strong>typeB</strong></em> debe tener la siguiente firma: <em><strong>typeB</strong> function(<strong>typeA</strong>, integer, boolean)</em>. - - CentralWidget - - Form - Formulario - - - New model - Nuevo modelo - - - Open model - Abrir modelo - - - Sample models - Ejemplo de modoles - - - Recent models - Modelos Recientes - - - Last session - Última sesión - - CodeCompletionWidget - - Make persistent - Hacer persistente + + Make &persistent + - + Makes the widget closable only by ESC key or mouse click on other controls. - Hace el widget que se puede cerrar solamente por tecla ESC o clic del ratón sobre otros controles. + Hace que el widget se puede cerrar solamente por tecla ESC o clic del ratón sobre otros controles. - + SQL Keyword Palabra clave SQL - + (no items found.) + (No se encontraron items.) (No se encontró ninguna.) CollationWidget - - Form - Formulario - Locale: @@ -1207,10 +1190,6 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. ColumnWidget - - Form - Formulario - Default Value: @@ -1219,7 +1198,7 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. E&xpression: - + E&xpresión: @@ -1231,18 +1210,6 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.Se&quence: - - Expression: - Expresión: - - - NOT NULL - NOT NULL - - - Sequence: - Secuencia: - ConfigurationForm @@ -1284,7 +1251,7 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. Defaults - Valor por Defecto + Valores por Defecto @@ -1298,6 +1265,16 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. + In some cases restore the default settings related to it may solve the problem. Would like to do that? + En algunos casos, restaurar la configuración predeterminada relacionada con él puede resolver el problema. ¿Le gustaría hacer eso? + + + + Restore + Restaurar + + + Any modification made until now in the current section will be lost! Do you really want to restore default settings? Cualquier modificación realizada hasta ahora en la sección actual se perderá! ¿Realmente desea restaurar la configuración predeterminada? @@ -1305,129 +1282,117 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. ConnectionsConfigWidget - Form - Formulario - - - + Password: Contraseña: - + Connection Alias: - Alias Conexión: + Alias de Conexión: - + Connection DB: BD Conexión: - + Host/Port: - Host/Puerta: + Host/Puerto: - + User: - Usuário: + Usuario: - + Timeout: Timeout: - + SSL Mode: Modo SSL: - + Disable Desactivado - + Diff Diff - + Export - Exportar + Exportar - + Import - Importar + Importar - + Validation - + Validación - + Security - + Seguridad - + Allow Permitir - + Require Requerido - + AC verification Verificación de AC - + Full verification Verificación Completa - + Kerberos Server: - + Servidor Kerberos: - + Client Certificate: Certificado Cliente: - + Revoked Certs.: Cert. Revocados: - + Client Key: Clave Cliente: - + Root Certificate: Certificado Root: - Options: - Opciones: - - - Kerberus Server: - Servidor Kerberus: - - - + ~/.postgresql/root.crt ~/.postgresql/root.crt @@ -1437,42 +1402,42 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.Conexiones: - + second(s) segundo(s) - + Force GSSAPI Forzar a GSSAPI - + ~/.postgresql/postgresql.crt ~/.postgresql/postgresql.crt - + Add Añadir - + Update Actualizar - + Test Testear - + ~/.postgresql/root.crl ~/.postgresql/root.crl - + ~/.postgresql/postgresql.key ~/.postgresql/postgresql.key @@ -1483,9 +1448,9 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. - + Edit database connections - + Editar conexiones de base de datos @@ -1513,29 +1478,29 @@ Esto desactivará el código de todos los objetos secundarios y referenciales.General - + Other params: - + Otros parámetros: - + Specify additional connection parameters in the form [param]=[value]. These parameters are described in the <strong>libpq</strong> chapter at PostgreSQL docs. - + Especifique los parámetros de conexión adicionales en la forma [param]=[valor]. Estos parámetros se describen en el capítulo <strong> libpq </strong> en la documentación de PostgreSQL. - + Default for: - + Automatically browses the named database when using this connection to manage databases on <strong>Manage</strong> view. Busca automáticamente la base de datos llamada cuando se utiliza esta conexión para administrar bases de datos en la vista <strong>Manage</strong>. - + Auto browse - Auto explorar + Auto explorar @@ -1543,58 +1508,44 @@ Esto desactivará el código de todos los objetos secundarios y referenciales. - + Success Éxito - - Connection successfuly stablished! + + Connection successfully established! Server details: PID: `%1' Protocol: `%2' Version: `%3' - Conexión establecida exitosamente! - -Detalle del Servidor: - -PID: `%1' -Protocol: `%2' -Versión: `%3' + - + There is a connection being created or edited! Do you want to save it? - + ¡Hay una conexión que se está creando o editando! ¿Desea guardarla? - + Found %1 connection(s) - + Se encontró %1 conexión(es) - + No connections found - + No se encontraron conexiones - + Edit connections - - - - There is an unsaved connection! Want to save it? - Existe una conexión no guardado! ¿Quiere guardarla? + Editar conexiones ConstraintWidget - - Form - Formulario - Match: @@ -1677,29 +1628,25 @@ Versión: `%3' Factor Rellen.: - - + + Column Column - - + + Type Tipo - + Columns which were included by relationship can not be added / removed manually from the primary key. If done such changes they can raise errors. To create primary key using columns included by relationship use the following options: identifier field, attributes & constraints tab or primary key tab on the relationship form. Las columnas que se incluyeron por la relación no se pueden añadir / retirado manualmente de la clave principal. Si se hace este tipo de cambios que pueden elevar los errores. Para crear la clave primaria utilizando columnas incluidas por relación utilizar las siguientes opciones: campo de identificador, atributos & limitaciones ficha o pestaña clave principal en el formulario de la relación. ConversionWidget - - Form - Formulario - Source Encoding: @@ -1729,121 +1676,215 @@ Versión: `%3' CrashHandlerForm - + Crash Handler Accidente del Handler - + Stack trace Pila de traza - + Input: Entrada: - + Load report file for analysis Cargando archivos de reporte para el análisis - + Save the attached model file on the filesystem Guarde el archivo de modelo que se adjunta en el sistema de archivos - + pgModeler bug report (*.bug);;All files (*.*) Reporte de Bog del pgModeler (*.bug);;Todos los archivos (*.*) - + Load report Cargando reporte - + Save model Salvar modelo - + Database model (*.dbm);;All files (*.*) Modelo de Bases de Datos (*.dbm);;Todos los archivo (*.*) - + Crash handler Accidente del Handler - + Bug report analysis mode activated. Modo de análisis para informar de fallos activada. - + Oops! pgModeler just crashed! ¡Huy! pgModeler simplemente cayó! - + We apologize for what happened! It is clear that a nasty bug caused that. Please fill out the form below describing your actions before pgModeler quit unexpectedly. This will help on bug extermination and improve the software. - Pedimos disculpas por lo que pasó! Es claro que un error desagradable causada eso. Rellene el siguiente formulario describiendo sus acciones antes pgModeler cierre inesperadamente. Esto ayudará en la exterminación de insectos y mejorar el software. + ¡Pedimos disculpas por lo ocurrido! Es evidente que un error desagradable ha causado eso. Rellene el siguiente formulario para describir sus acciones antes de que pgModeler se cierre inesperadamente. Esto ayudará en la exterminación de errores y mejorará el software. - CustomSQLWidget + CsvLoadWidget + Form - Formulario + Formulario - - Add custom SQL code - + + Load CSV + Cargar CSV - - SQL code - Código SQL + + CSV File: + Archivo CSV: - - Puts an SELECT command template at current cursor position. - Pone un comando SELECT en una plantilla en la posición actual de cursor. + + Select output file + Seleccionar archivo de salida - - &SELECT - &SELECT + + ... + ... - - Puts an INSERT command template at current cursor position. - Pone un comando INSERT en una plantilla en la posición actual de cursor. + + Separator: + Separador: - - &INSERT - &INSERT + + Use the first row as column names in the CSV file. By unchecking this option the first row is used as data. + - - Puts an UPDATE command template at current cursor position. - Pone un comando UPDATE en una plantilla en la posición actual de cursor. + + Columns in the first row + - - &UPDATE - &UPDATE + + Load + Cargar - - Puts an DELETE command template at current cursor position. - Pone un comando DELETE en una plantilla en la posición actual de cursor. + + Semicolon (;) + + + + + Comma (,) + + + + + Space + Espacio + + + + Tabulation + + + + + Other + + + + + ; + + + + + Text delimiter: + + + + + " + + + + + Load CSV file + + + + + Comma-separted values (*.csv);;All files (*.*) + + + + + CustomSQLWidget + + + Add custom SQL code + + + + + SQL code + Código SQL + + + + Puts an SELECT command template at current cursor position. + Pone un comando SELECT en una plantilla en la posición actual de cursor. + + + + &SELECT + &SELECT + + + + Puts an INSERT command template at current cursor position. + Pone un comando INSERT en una plantilla en la posición actual de cursor. + + + + &INSERT + &INSERT + + + + Puts an UPDATE command template at current cursor position. + Pone un comando UPDATE en una plantilla en la posición actual de cursor. + + + + &UPDATE + &UPDATE + + + + Puts an DELETE command template at current cursor position. + Pone un comando DELETE en una plantilla en la posición actual de cursor. @@ -1889,56 +1930,52 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT <html><head/><body><p>Utilice comandos personalizados con extrema precaución ya que puede cambiar la semántica de todo el modelo cuando se ejecutan los procesos de validación de SQL o de exportación. Además, dependiendo de la cantidad de comandos, esos procesos pueden tener su rendimiento sensiblemente degrada.</p></body></html> - Append / Prepend SQL code - Adjuntar / Prefijar código SQL - - - + Type: Tipo: - + Generic INSERT INSERT genérico - + Include serial columns Incluir columnas serial - + Exclude serial columns Excluir columnas serial - + Generic SELECT SELECT genérico - + Table SELECT SELECT tabla - + Generic UPDATE - + Table UPDATE UPDATE genérico - + Generic DELETE DELETE genérico - + Table DELETE DELETE tabla @@ -1956,339 +1993,329 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT &Cerrar - Rows returned: - Filas devueltas: - - - 0 - 0 - - - Maximum limit of listed rows - Límite máximo de filas listadas - - - (Limit: 0) - (Límite: 0) - - - Empty values are assumed as <strong>DEFAULT</strong>. To use special values like <strong>NULL</strong>, a function call like <strong>now()</strong> or a specific data escaping, enclose values in <strong>&lt;&gt;</strong>. To use <strong>&lt;</strong> or <strong>&gt;</strong> as part of the value prepend the backslash character, e.g., <strong>\&lt;</strong> or <strong>\&gt;</strong>. - Los Valores vacíos se asumen como <strong>DEFAULT</strong>. Para utilizar los valores especiales como <strong>NULL</strong> una llamada de función como <strong>now()</strong> o un escape de datos específica, encierran valores <strong>&lt;&gt;</strong>. Usar <strong>&lt;</strong> o <strong>&gt;</strong> como parte del valor de anteponer el carácter de barra invertida, por ejemplo, <strong>\&lt;</strong> or <strong>\&gt;</strong>. - - - + Refresh listing Refrescar listado - - Refresh - Refrescar - - - + F5 F5 - + Save changes Salvar cambios - - Save - Salvar - - - + Ctrl+S Ctrl+S - - Copy the selection as CSV buffer - Copiar la selección como buffer CSV - - - - Copy - Copiar - - - - Ctrl+C - Ctrl+C - - - + Export results to CSV file Exportar resultados a archivo CSV - - Export - Exportar - - - + + Ctrl+X Ctrl+X - + Undo modifications Deshacer modificaciones - - Undo - Deshacer - - - + Ctrl+Z Ctrl+Z - Add data - Añadir datos - - - - Add - Añadir - - - - + + Ins Ins - + Mark the selected rows to be deleted Marque las filas seleccionadas para ser borradas - - - Delete - Borrar - - - - - - - + + + + + Del Del - + Duplicate the selected rows - - Duplicate + + Ctrl+D - - Ctrl+D + + Add new rows from a CSV file - + Filter the result set Filtrar el conjunto de resultados - + Table: Tabla: - + Schema: Esquema: - + in in - + Hide views Ocultar vista - + Filter expression Filtrar expresión - + Order && Limit Order && Límite - + results (Use <strong>0</strong> for no limit) - + Column: Columna: - - ASC - ASC + + <html><head/><body><p>Empty values are assumed as <span style=" font-weight:600;">DEFAULT</span>. To use special values like <span style=" font-weight:600;">NULL</span>, a function call like <span style=" font-weight:600;">now()</span> or a specific data escaping, enclose values in two slashes, e.g., <span style=" font-weight:600;">/value/</span>. To use a slash as part of the value prepend the backslash character, e.g., <span style=" font-weight:600;">\/</span>.</p></body></html> + - - <html><head/><body><p>Empty values are assumed as <span style=" font-weight:600;">DEFAULT</span>. To use special values like <span style=" font-weight:600;">NULL</span>, a function call like <span style=" font-weight:600;">now()</span> or a specific data escaping, enclose values in <span style=" font-weight:600;">{}</span>. To use <span style=" font-weight:600;">{</span> or <span style=" font-weight:600;">}</span> as part of the value prepend the backslash character, e.g., <span style=" font-weight:600;">\{</span> or <span style=" font-weight:600;">\}</span>.</p></body></html> + + Copy items on the grid - - Add empty rows + + Paste items on the grid - - DESC - DESC + + Ctrl+V + Ctrl+V - - Limit in: - Límite en: + + Browse referenced tables + - 000000 - 000000 + + ASC + ASC + + + + Add empty rows + - 100 - 100 + + DESC + DESC - results - resultados + + Limit in: + Límite en: - + Add Item Añadir Item - + Remove Item Eliminar Item - + Clear the order by columns list Desactive el orden de lista columnas - + Move selected item up Mover arriba el item seleccionado - + Move selected item down Mover abajo el item seleccionado - + + Copy as CSV + + + + + Copy as text + + + + + Copy items + + + + + Pase items + + + + + Browse tables + + + + + Duplicate row(s) + + + + + Delete row(s) + + + + <strong>WARNING: </strong> There are some changed rows waiting the commit! Do you really want to discard them and retrieve the data now? - + Rows returned: <strong>%1</strong>&nbsp;&nbsp;&nbsp; - + <em>(Limit: <strong>%1</strong>)</em> <em>(Límite: <strong>%1</strong>)</em> - + none - + No objects found Objects no encontrado - + Found %1 object(s) Encontrado %1 objecto(s) - + Views can't have their data handled through this grid, this way, all operations are disabled. Las vistas no pueden tener sus datos manejados a través de esta red, de esta manera, todas las operaciones están desactivadas. - + The selected table doesn't owns a primary key! Updates and deletes will be performed by considering all columns as primary key. <strong>WARNING:</strong> those operations can affect more than one row. La tabla seleccionada no posee una clave primaria! Las actualizaciones y eliminaciones se realizarán teniendo en cuenta todas las columnas como clave primaria. <strong>WARNING:</strong> estas operaciones pueden afectar a más de una fila. - + + Referenced tables + + + + + + (none) + + + + + Referrer tables + + + + This row is marked to be %1 Esta fila se marca para ser %1 - + deleted eliminado - + updated actualizado - + inserted insertado - + [binary data] [datos binarios] - + <strong>WARNING:</strong> Once commited its not possible to undo the changes! Proceed with saving? <strong>WARNING:</strong> Una vez que su cometido no es posible deshacer los cambios! Procedo con salvar? - + delete eliminar - + update actualizar - + insert insertar @@ -2300,23 +2327,11 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT Form Formulario - - Toggles the display of system - Cambia la visualización de objects del sistema - - - Sys. objects - Objectos del Sys - Toggles the display of extension objects Cambia la visualización de extensión de objetos - - Ext. objects - Ext. objectos - Data &Grid @@ -2327,27 +2342,15 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT Alt+G Alt+G - - Open a new SQL execution pane. - Abrir un nuevo panel de ejecución de SQL. - - - + + ... ... - - Ctrl+F5 - Ctrl+F5 - - - Update the objects tree. - Actualizar el árbol de objetos. - Toggles the display of system objects. @@ -2371,7 +2374,7 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT Open a new SQL execution pane - + Abrir un nuevo panel de ejecución de SQL @@ -2381,7 +2384,7 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT Update the objects tree - + Actualizar el árbol de objetos @@ -2391,936 +2394,1059 @@ Desmarcando esto hará que el SQL que se adjunta al final del mandato CREATE DAT Drop this database - + Eliminar esta base de datos - + Expands all items Expande todos los item - + Collapses all items Contrae todos los item - + Filters the currently loaded items in the tree by using a pattern and matching their names. If <strong>By OID</strong> is checked the pattern is interpreted as an integer value that represents the object id (OID). <br><br/><strong>HINT:</strong> if you need to search the entire database use the full refresh (<strong>Ctrl+F5</strong>) prior the filtering. - + Filter: Filtro: - + By OID Por OID - - + + Attribute Atributo - + Value Valor - + Show raw attributes - Show raw attributes names - Mostrar primero nombres de atributos - - - + (not found, OID: %1) - + -- Source code not generated! Hit F7 or middle-click the item to load it. -- - + Admin. roles Admin. roles - + Alignment Alineación - + Analyze func. Analizar func. - + Arg. count Arg. Contar - + Arg. default count Arg. contar por defecto - + Arg. defaults Arg. por defecto - + Arg. modes Arg. modos - + Arg. names Arg. nombres - + Arg. types Arg. tipos - + Behavior type Tipo de comportamiento - + By value Por valor - + Cast type Tipo conversión - + Category Categoria - + Collatable Intercalable - + Collation Intercalación - + Comment Comentario - + Commutator Op. Commutador Op. - + Configuration Configuración - + Conn. limit Conn. límite - - + + Constraint Restricción - + Create DB Crear BD - + Create role Crear rol - + Curr. version Corr. versión - + Default Por defecto - + Default value Valor por defecto - + Definition Definición - + Delimiter Delimitador - + Dest. type Dest. tipo - + Dimension Dimensión - + Directory Directorio - + Dest. encoding Dest. codificación - + Element Elemento - + Encoding Codificación - + Encrypted Encriptado - + Enumerations Enumeraciones - + Exec. cost Costo ejec - + Expression Expresión - + Op. family Op. familia - + Final func. Final func. - + Function Función - + Func. type Func. tipo - + Handler func. Handler func. - + Handles type Handles tipo - + Hashes Hashes - + Index type Indixe tipo - + Inherit Heredar - + Ini. condition Ini. condición - + Inline func. En linea func. - + Input func. Entrada func. - + Internal length Longitud interna - + Interval type Intervalo tipo - + I/O cast I/O cast - + Join func. Join func. - + Language Languaje - + LC COLLATE LC COLLATE - + LC CTYPE LC CTYPE - + Leak proof Prueba de fugas - + Left type Tipo izquierda - + Length Longitud - + Library Biblioteca - + Can login Puede login - + Materialized Materializada - + Member roles Roles miembros - + Merges Unir - + Name Nombre - + Negator op. Op negador. - + Not null No null - + Object type Tipo object - + OID OID - + With OIDs Con OIDs - + Old version Vieja version - + Operator Operador - + Operator func. Operador func. - + Output func. Salida func. - + Owner Dueño - + Owner column Dueño columna - + Parents Padres - + Password Contraseña - + Permissions Permisos - + Precision Precisión - + Preferred Preferido - + Range attributes Rango atributos - + Receive func. Recibe func. - + Ref. roles Ref. roles - + Replication Replicación - + Restriction func. Restricción func. - + Return type Retornar tipo - + Returns SETOF Retornar SETOF - + Right type Tipo a la derecha - + Rows amount Cantidad filas - + Schema Esquema - + Security type Tipo de seguridad - + Send func. Envio func. - + Sort op. Op ordenación. - + Source type Tipo de fuentes - + Src. encoding Fnt. codificación - + State type Tipo estado - + Storage Almacenamiento - + Superuser Superusuario - + Tablespace Tablespace - + Type mod. in func. Tipo mod. entrada func. - + Type mod. out func. Tipo mod. salida func. - + Transition func. Transición func. - + Trusted Verdadero - + Type Tipo - + Type attribute Tipo atributos - + Types Tipos - + Unlogged Invitados - + Validator func. Validador func. - + Validity Validez - + Windows func. Func. ventana. - + false falso - + true verdadero - + Cache value Valor en cache - + Cycle Ciclo - + Increment Incremneto - + Max. value Max. valor - + Min. value Min valor - + Start value Valor inicial - + Last value Próximo valor - + Subtype Subtipo - + Op. class Op. clases - + Canonical func. func. canonica. - + Subtype diff func. Subtipo diff func. - + Deferrable Diferible - + For each row For each row - + Firing Disparadores - + On insert On insert - - + + On delete On delete - - + + On update On update - + On truncate On truncate - + Arguments Argumentos - + Table Tabla - + Trigger func. func. Trigger. - - - + + + Columns Columnas - + Condition Condición - + Deferment Diferimiento - + Event Evento - + Execution mode Modo Ejecución - + Commands Comandos - + Position Posición - + Comparison type Tipo comparación - + Ref. columns Ref. columnas - + Expressions Expresiones - + Fill factor Factor de relleno - + No inherit No hereda - + Op. classes Op. clases - + Operators Operador - + Ref. table Tabla Ref - + Unique Unique - + Predicate Predicado - + Collations Intercalaciones - + Inherited Heredado - - Snippets - Snippets + + Client encoding + - + + Configuration file + + + + + Data directory + + + + + Dynamic library path + + + + + Dynamic shared memory + + + + + Hba file + + + + + Listen addresses + + + + + Max. connections + + + + + Listen port + + + + + Server encoding + + + + + SSL + + + + + SSL ca file + + + + + SSL cert file + + + + + SSL crl file + + + + + SSL key file + + + + + Server version + + + + + Ident file + + + + + Password encryption + + + + + Connection ID + + + + + Server PID + + + + + Server protocol + + + + + Referrers + + + + + Snippets + Snippets + + + Drop object Drop object - + Drop cascade Drop cascade - + Truncate Truncate - + Trunc. cascade Trunc. cascade - + Show data Mostrar dato - + Reload properties Recargar propiedades - + Update Actualizar - + Rename Renombrar - + Source code Código fuente - + Quick refresh - + Full refresh - + + -- Source code unavailable for this kind of object -- + + + + Do you really want to drop the object <strong>%1</strong> <em>(%2)</em>? ¿De verdad quiere borrar el objeto <strong>%1</strong> <em>(%2)</em>? - + Do you really want to <strong>cascade</strong> drop the object <strong>%1</strong> <em>(%2)</em>? This action will drop all the other objects that depends on it. - + Src. table: %1 Src. column(s): %2 - + Ref. table: %1 Ref. column(s): %2 - + -- Source code genaration for buil-in and base types currently unavailable -- - + -- Source code unavailable for the object %1 (%2). -- - Do you really want to <strong>cascade</strong> drop the object <strong>%1</strong> <em>(%2)</em>? This action will drop all the other objects that depends on it? - ¿De verdad quieres borrar en <strong>cascade</strong> el objecto <strong>%1</strong> <em>(%2)</em>? ¿Esta acción se borra todos los otros objetos que dependen de ella? + + + Warning + Advertencia + + + + You're running a demonstration version! The data manipulation feature is available only in the full version! + Usted está ejecutando una versión de demostración! La función de manipulación de datos sólo está disponible en la versión completa! + + + + <strong>CAUTION:</strong> You are about to drop the entire database <strong>%1</strong>! All data will be completely wiped out. Do you really want to proceed? + <strong>ATENCION:</strong> Vas a dejar toda la base de datos <strong>%1</strong>! Todos los datos serán completamente eliminados. ¿Realmente desea continuar? - + Do you really want to truncate the table <strong>%1</strong>? ¿De verdad quiere truncar la tabla <strong>%1</strong>? - + Do you really want to <strong>cascade</strong> truncate the table <strong>%1</strong>? This action will truncate all the tables that depends on it? ¿De verdad quieres truncar en <strong>cascade</strong> la tabla <strong>%1</strong>? ¿Esta acción truncar todas las tablas que depende de ella? @@ -3377,10 +3503,6 @@ Ref. column(s): %2 Spacing: Espaciado: - - Schemas per row - Esquema por fila - Spacing between objects @@ -3391,19 +3513,11 @@ Ref. column(s): %2 Schemas per row: Esquema por fila: - - Resolve some of the object's dependencies by query the catalog when a needed object does not exists on the loaded set. In some cases it's necessary to combine this option with others below. This option does not applies to database level objects like role, tablespace and language as well for data types and extensions. - Resolver algunas de las dependencias del objeto de consulta del catálogo, cuando no existe un objeto necesario en el conjunto cargado. En algunos casos es necesario combinar esta opción con otros de abajo. Esta opción no se aplica a los objetos de nivel de base de datos como el papel, espacio de tabla y el lenguaje, así como para los tipos de datos y extensiones. - Automatically resolve dependencies Resolver dependencias automáticamente - - Connect and list available databases - Conectar y listar bases de datos disponibles - @@ -3462,10 +3576,6 @@ Ref. column(s): %2 Ignore import errors Ignorar errores de importación - - All catalog queries as well the created objects' source code are printed to standard outupt (stdout). - Todas las consultas de catálogo, así el código fuente de los objetos creados se imprimen a la salida estándar (stdout). - All catalog queries as well the created objects' source code are printed to standard output (stdout). @@ -3542,72 +3652,72 @@ Ref. column(s): %2 Cancelar - + &Import &Importar - + &Close &Cerrar - + <strong>ATTENTION:</strong> You are about to import objects to the current working model! This action will cause irreversible changes to it even in case of critical errors during the process. Do you want to proceed? <strong>ATENCIÓN:</strong> Estás a punto de importar objetos al modelo actual de trabajo! Esta acción provocará cambios irreversibles a él, incluso en caso de errores críticos durante el proceso. ¿Quieres proceder? - + Importing process aborted! Proceso de Importación abortado! - + Importing process canceled by user! Proceso de Importación cancelado por usuario! - + Importing process sucessfuly ended! Proceso de Importación terminado satisfactoriamente! - + No databases found Base de datos no encontrada - + Found %1 database(s) Encontrada %1 bases de dato(s) - + Retrieving objects from database... Recuperando objetos de base de datos... - + Retrieving cluster level objects... Recuperando objetos a nivel de clúster... - + Retrieving objects of schema `%1'... Recuperando objetos del esquema `%1'... - - Retrieving objects of table `%1'... - Recuperando objetos de la tabla `%1'... + + Retrieving objects of `%1' (%2)... + - + This is a PostgreSQL built-in data type and cannot be imported. Esta es una tipo de datos incorporado PostgreSQL y no se puede importar. - + This is a pgModeler's built-in object. It will be ignored if checked by user. Esta es objeto incorporado del pgModeler. Se ignora si se activa por el usuario. @@ -3626,62 +3736,62 @@ Ref. column(s): %2 Recuperando objetos... `%1' - - - Creating object `%1' (%2)... - Creando objecto `%1' (%2)... + + Creating object `%1' (%2), oid `%3'... + + + + + Trying to recreate object `%1' (%2), oid `%3'... + - - Trying to recreate object `%1' (%2)... - Intentar recrear objeto `%1' (%2)... + + Creating object `%1' (%2)... + Creando objecto `%1' (%2)... - + Import failed to recreate some objects in `%1' tries. Importación no pudo recrear algunos objetos en `%1' intento. - + Creating permissions for object `%1' (%2)... Creación permisos por objecto `%1' (%2)... - + Creating columns permissions... Creación permisos de columnas... - + Updating relationships of `%1' (%2)... - + Validating relationships... - + Assigning sequences to columns... - Update relationships of `%1' (%2)... - Actualizar relaciones de `%1' (%2)... - - - + The database import ended but some errors were generated and saved into the log file `%1'. This file will last until pgModeler quit. La importación de base de datos terminó pero algunos errores se genera y se guarda en el archivo de registro `%1'. Este archivo se prolongará hasta salga de pgModeler. - + Destroying unused detached columns... Destruyendo columnas separadas no utilizados... - + Creating table inheritances... Creación de herencias de tabla... @@ -3689,78 +3799,74 @@ Ref. column(s): %2 DatabaseModel - + The demonstration version can create only `%1' instances of each object type! You've reach this limit for the type: `%2' La versión de demostración sólo puede crear `%1' instancias de cada tipo de objeto! Tienes que llegar a este límite para el tipo: `%2' - + Loading: `%1' (%2) Cargando: `%1' (%2) - - + + Validating relationships... - + Generating %1 of the object `%2' (%3) Generando %1 del objecto `%2' (%3) - + Saving object `%1' (%2) - + Saving metadata of the object `%1' (%2) - + Metadata file successfully saved! - + Process successfully ended but no metadata was saved! - + Creating object `%1' (%2) Creando objecto `%1' (%2) - + Object `%1' (%2) already exists. Ignoring. - + Loading metadata for object `%1' (%2) - + Object `%1' (%2) not found. Ignoring metadata. - + Metadata file successfully loaded! DatabaseWidget - - Form - Formulario - Attributes @@ -3842,10 +3948,6 @@ Ref. column(s): %2 DomainWidget - - Form - Formulario - Default Value: @@ -3882,12 +3984,12 @@ Ref. column(s): %2 Donate to pgModeler - + Hacer una donación a pgModeler Hide this widget - Ocultar este widget + Ocultar este widget @@ -3897,12 +3999,12 @@ Ref. column(s): %2 <html><head/><body><p>pgModeler is brought to you thanks to a <span style=" font-style:italic;">great effort to create and distribute a quality product</span>. This project is reaching out levels of maturity never imagined. All this is the result of a joint work between its author and the <span style=" font-weight:600;">Open Source community</span>. <br/><br/>This software has a long way to go yet and with your help we'll keep maintaining the good job and bringing new improvements on each release. If you did like pgModeler and thinks it deserves a contribution please make a donation!</p></body></html> - + <html><head/><body><p>pgModeler es traído a usted gracias a un <span style=" font-style:italic;">gran esfuerzo para crear y distribuir un producto de calidad</span>. Este proyecto está alcanzando niveles de madurez nunca imaginados. Todo esto es el resultado de un trabajo conjunto entre su autor y la <span style=" font-weight:600;">comunidad Open Source </span>. <br/><br/>Este software tiene un largo camino por recorrer y con su ayuda seguiremos manteniendo el buen trabajo y trayendo nuevas mejoras en cada versión. Si te gustó pgModeler y cree que merece una contribución, haz una donación!</p></body></html> I want to help! - + ¡Quiero ayudar! @@ -3913,47 +4015,47 @@ Ref. column(s): %2 Formulario - + Column: Columna: - + Expression: Expresión: - + Collation: Colación: - + Operator Class: Operador de Clases: - + Operator: Operador: - + Sorting: Ordenación: - + Ascending Ascendente - + Descending Descendente - + Nulls first Nulos primeros @@ -3983,37 +4085,33 @@ Ref. column(s): %2 Nulos Primero - + Collation Colación - + Operator Operador - + Expression Expresión - + Yes Si - + No No EventTriggerWidget - - Form - Formulario - Event: @@ -4049,802 +4147,841 @@ Ref. column(s): %2 - Zero length assignment! - Longitud asignación igual a Cero! - - - Assignment of a precision greater than the length of the type! Asignación de una precisión mayor que la longitud del tipo! - + Assignment of an invalid precision to type time, timestamp or interval. The precision in this case must be equal to or less than 6! Asignación de una precisión no válido para el tipo de tiempo, marca de tiempo o intervalo. La precisión en este caso debe ser igual o inferior a 6! - + Assignment of a not allocated column to object `%1' (%2)! Asignación de una columna no asignados a objeto `%1' (%2)! - + Reference to a column which index is out of the capacity of the column list! La referencia a una columna que índice está fuera de la capacidad de la lista de columnas! - + Assignment of not allocated object! Asignación de objeto no asignado! - + Assignment of a not allocated schema to object `%1' (%2)! Asignación de un esquema no asignado al objeto `%1' (%2)! - + The object `%1' (%2) has inconsistent SQL or XML definition! El objeto `%1' (%2) tiene la configuración inconsistente (definición SQL / XML no válido)! - + The object `%1' (%2) already exists on `%3' (%4)! El objeto `%1' (%2) ya existe en `%3' (%4)! - + The object `%1' (%2) cannot be assigned because there is already exists in the container object `%3'! El objeto `%1' (%2) no puede ser asignado porque ya se existe en el objeto contenedor `%3'! - + Assigning object of an invalid type! Asignación de objeto de un tipo no válido! - + Removing an object of an invalid type! Eliminación de un objeto de un tipo no válido! - + Obtaining an object of an invalid type! Obtención de un objeto de un tipo no válido! - + Assignment of empty name to table return type! Asignación de nombre vacío de tipo de tabla de retorno! - + The insertion of the parameter `%1' will not be possible because there is another parameter with same name in the function `%2'! La inserción del parámetro `%1' no será posible porque no hay otro parámetro con el mismo nombre en la función `%2'! - + The insertion of the table return type `%1' will not be possible because there is another return type with the same name in the `%2'! La inserción del tipo de tabla de retorno `%1' no será posible porque hay otro tipo de retorno con el mismo nombre en el `%2'! - + Reference to a parameter which index is out of the parameter list bounds! La referencia a un evento que no pertenece a disparar! - + Reference to an event which does not belongs to trigger! La referencia a un evento que no pertenece al trigger! - + The column `%1' cannot be assigned to the trigger `%2' because they belongs to different parent tables! La columna `%1' no puede ser asignada a un Trigger `%2' porque no pertenece a la tabla padre! - + Assignment of a not allocated function to object `%1' (%2)! Asignación de una función no asignada a objeto `%1' (%2)! - + Assignment of a function which return type is different from `%1'! Asignación de una función que tipo de retorno es diferente de `%1'! - + Assignment of a function which parameter count is invalid to the object `%1' (%2)! Asignación de una función que cuente parámetro no es válido para el objeto `%1' (%2)! - + Assignment of a function which language is invalid! Asignación de una función que el lenguaje no es válido! - + Event trigger function must be coded in any language other than SQL! Función de disparo de eventos debe estar codificado en cualquier idioma que no sea SQL! - + Assignment of not allocated table to object `%1' (%2)! Asignación de tabla no asignado a objeto `%1' (%2)! - + Reference to an argument which index is out of argument list bounds! La referencia a un argumento que el índice está fuera de la capacidad de la lista de argumentos! - + Assignment of empty name to an object! Asignación de nombre vacío a un objeto! - + Assignment of a name which contains invalid characters! Asignación de nombre no válido a un objeto! - + Assignment of a name which length exceeds the maximum of 63 characters! Asignación de un nombre cuya longitud supera el máximo de 63 caracteres! - + Assignment of schema object which type is invalid! Asignación de objeto que tipo de esquema no válido! - + Assignment of tablespace object with invalid type! Asignación de objeto de tablespace con tipo no válido! - + Assignment of tablespace to an invalid object! Asignación de tablespace a un objeto no válido! - + Assignment of tablespace to a constraint which type is invalid! To belong to a tablespace the constraint must be a primary key or unique! Asignación de espacio de tabla a una restricción de qué tipo es válido! Para pertenecer a un espacio de tabla la restricción debe ser una clave primaria o único! - + Assignment of owner object which type is invalid! Asignación de objeto que tipo de propietario no es válido! - + Assignment of owner to an invalid object! Asignación de propietario para un objeto no válido! - + Assignment of appended or prepended SQL to an invalid object! Asignación de SQL añadido o preañadido a un objeto no válido! - + Reference to a function with invalid type! La referencia a una función con tipo no válido! - + Reference to an argument of the operator with invalid type! La referencia a un argumento del operador con el tipo no válido! - + Reference to an operator with invalid type! La referencia a un operador con tipo no válido! - + Assignment of value to an invalid option type on role! Asignación de valor a un tipo de opción no válida en el rol! - + Reference to an invalid role type! La referencia a un tipo de rol no válido! - + The insertion of the role `%1' is not possible because this is already being referenced by role `%2'! La inserción del rol `%1' no es posible porque esto ya está siendo referenciado por rol `%2'! - + Reference redundancy detected by having the role `%1' referencing the role `%2'! Referencia redundancia detecta por tener el rol `%1' referencia al rol `%2'! - + The role `%1' can not be listed as a member of itself! El rol `%1' no puede ser listado como un miembro de sí mismo! - + Reference to a role which index is out of role list bounds! La referencia a un rol el índice del cual está fuera de la lista de rol límites! - + Insertion of empty command to the rule! Inserción de comando nulo en la regla! - + Reference to a command which index is out of the command list bounds! La referencia a un comando que el índice está fuera de la capacidad de la lista de comandos! - + Is not possible to create a self generalization/copy relationship! The table can not inherit or copy their own attributes! No es posible crear una relación de auto generalización / dependecy! La tabla no puede heredar o copiar sus propios atributos! - + Assignment of an object that already belongs to another table! Asignación de un objeto que ya pertenece a otra tabla! - + Assignment of a schema to the sequence which differs from the schema of the owner table! Asignación de un esquema de la secuencia que se diferencia del esquema de la tabla dueño! - + Assignment of an invalid value to one of the sequence attributes! Asignación de un valor no válido para uno de los atributos de secuencia! - + Assignment of a minimum value to the sequence which is greater than the maximum value! Asignación de un valor mínimo a la secuencia que es mayor que el valor máximo! - + Assignment of a start value to the sequence which is extrapolating the range defined by minimum and maximum values! Asignación de un valor de inicio a la secuencia que se extrapolando el rango definido por valores mínimo y máximo! - + Assignment of a null increment value to the sequence! Asignación de un valor nulo de incremento a la secuencia! - + Assignment of null cache value to the sequence! Asignación de cache de secuencia con valor nulo! - + Assignment of owner table which is not in the same schema as the sequence `%1'! Asignación de dueño de tabla que no está en el mismo esquema que la secuencia `%1'! - + Assignment of owner table which does not belong to the same owner of the sequence `%1'! Asignación de dueño de tabla que no pertenece al mismo dueño de la secuencia `%1'! - + Assignment of a nonexistent owner column to the sequence `%1'! Asignación de una dueño inexistente a una columna para secuencia `%1'! - + Assignment of an owner column to the sequence `%1' that is not related to any table! Asignación de una dueño a una columna para la secuencia `%1' que no está relacionada a ninguna tabla! - + Reference to a label which index is out of labels list bounds! Referencia a una etiqueta que el índice está fuera de límites de la lista de etiquetas! - + Allocation of object with invalid type! Asignación del objeto con tipo no válido! - + Assignment of a function with invalid return type to object `%1' (%2)! Asignación de función con tipo de retorno inválido a objeto `%1' (%2)! - + Assignment of a function with invalid parameter(s) type(s) to object `%1' (%2)! Asignación de función con tipo de parâmetro(s) inválido(s) a objeto `%1' (%2)! - + Assignment of not allocated language! Asignación de el lenguaje no asignado! - + Assignment of language object which type is invalid! Asignación de objeto de lenguaje que el tipo no es válido! - + Reference to data type with an index outside the capacity of data types list! Referencia al tipo de datos con un índice fuera de la capacidad de la lista actualizada tipos! - + Assignment of a null type to object `%1' (%2)! - + Unable to write the file `%1' due to one or more errors in the definition generation process! - + The configuration of the relationship `%1' generates a redundancy between the relationships `%2'. Redundancy on identifier or generalization/copy relationships are not accepted since they result in incorrect column spreading making the model inconsistent! - + + Unable to load the configuration file `%1'! Please check if file exists in its folder and/or if it is not corrupted! + + + + + Invalid syntax in file `%1', line %2, column %3! + + + + + Invalid instruction `%1' on file `%2', line %3, column %4! + + + + + Unknown attribute `%1' in file `%2', line %3, column %4! + + + + + Invalid metacharacter `%1' in file `%2', line %3, column %4! + + + + + Invalid operator `%1' in comparison expression, file `%2', line %3, column %4! + + + + + Attribute `%1' with an undefined value in file `%2', line %3, column %4! + + + + + Attribute `%1' with an invalid name in file `%2', line %3, column %4! + + + + + Could not access the file or directory `%1'! Make sure that it exists or if the user has access permissions on it! + + + + + Could not load file `%1'. The same appears to be inconsistent or one of its dependencies (DTD files) has errors or is missing! + + + + Reference to a tuple with an invalid index or the result is empty (no tuples)! - + Invalid use of a view reference as whole SQL definition! The assigned reference must be an expression! - + At the moment pgModeler does not support the creation of primary keys which some columns were generated by relationship connection. To create primary keys with this feature you can use the field `Identifier' or the tab `Primary key' on relationship editing form! - + Reference to a function id which is incompatible with the user define type configuration! - + + Unsupported PostgreSQL version (%1) detected! Valid versions are between %2 and %3. + + + + Invalid use of variadic parameter mode! This mode can be used only with an array or "any" data type! - + + The object `%1' (%2), oid `%3', could not be imported due to one or more errors! Check the exception stack for more details. `HINT:' if the object somehow references objects in `pg_catalog' or `information_schema' consider enable the importing of system objects. + + + + Assignment of an invalid object to `%1' (%2)! The assigned object must be of type `%3'. - + It's not possible convert the type of the column `%1' to serial! It must have an `integer' based type and its default value must be a call to `nextval(seq_name::regclass)' function or a sequence object must be directly assigned to the column! - + Trying to undo/redo an invalid operation over an object that does not exists anymore or can't be handled! The operation history will be cleaned up. - + A parent table of `%1' which OID is `%2' was not found in the set of imported objects! - + The enumeration `%1' can't be assigned to the type `%2' because contains invalid characters! - + The enumeration `%1' can't be assigned to the type `%2' because is too long! - + The connection was idle for too long and was automatically closed! - + The connection was unexpectedly closed by the database server `%1' at port `%2'! - Assignment of a null type to to object `%1' (%2)! - Asignación de un tipo nulo de oponerse a `%1' (%2)! + + Failed to drop the database `%1' because it is defined as the default database for the connection `%2'! + - + Assignment of invalid type to the object! Asignación de un tipo inválido a objeto! - + Assignment of an empty directory to object `%1' (%2)! Asignación de un diretório vacio a objeto: `%1' (%2)! - + Obtaining types with invalid quantity! Obtención de tipos con una cantidad no válida! - + Insertion of item which already exists in the attributes list of the type! Inserción de objeto que ya existe en la lista del tipo de atributos! - + Insertion of invalid item in the attributes list of the type! Inserción de item inválido en la lista del tipo de atibutos! - + Insertion of item which already exists in the enumarations list of the type! Inserción de item ya existente en la lista del tipo de enumeraciones! - + Insertion of invalid item in the enumerations list of the type! Inserción de item inválido en laa lista del tipo de enumeraciones! - + Reference to an attribute which index is out of the attributes list bounds! Referencia a un atributo que el índice está fuera de la capacidad de la lista de atributos! - + Reference to an enumeration which index is out of the enumerations list bounds! Referencia a una enumeración con índice fuera de la capacidad de la lista de enumeraciones! - + Assignment of invalid configuration to the type! Asignación de configuración no válida para el tipo! - The data type `%1' can not be assigned because it already exists in the types list of the aggregate function `%2'! - El tipo de dato `%1' no puede ser asignado pues el mismo ya existente en la lista de tipos de la función de agregación `%2'! - - - + Assignment of an operator which input type count is invalid to aggregate function! Asignación de operador a una función de agregacíon con cantidad de tipos de entrada inválida! - + Assignment of an operator which types of arguments is invalid! Asignación de operador con argumentos de tipos inválidos! - + Assignment of system reserved name to the object `%1' (%2)! Asignación de nombre reservado por el sistema a objeto `%1' (%2)! - + One function with invalid configuration is been used by the object `%1' (%2)! Una función de configuración inválido está siendo usada por el objeto `%1' (%2)! - + Assignment of an invalid strategy/support number to an operator class element! Asignación de un número inválido de estratégia/suporte del elemento de clase de operadores! - + Insertion of element which already exists in the element list! Inserción de elemento ya existente en la lista de elementos! - + Reference to an element which index is out of element list bounds! Referencia a un elemento con índice fuera de límites de la lista de elementos! - + Reference to an object which index is out of object list bounds! La referencia a un objeto que el índice está fuera de límites de la lista de objetos! - + Removal of an object not allocated! Eliminación de un objeto no asignado! - + The object `%1' (%2) can not be removed because it is being referenced by object `%3' (%4)! El objeto `%1' (%2) no puede ser removido pues está siendo referenciado por el objeto `%3' (%4)! - + The object `%1' (%2) can not be removed because it is being referenced by object `%3' (%4) that belongs to `%5' (%6)! El objeto `%1' (%2) no pode ser removido pues está siendo referenciado por el objeto `%3' (%4) perteneciente a `%5' (%6)! - + Operation with object(s) which type(s) is invalid! Operación con objeto(s) de tipo(s) inválido(s)! - + Reference to object with invalid type! Referencia a un objeto con tipo inválido! - + Operation with object not allocated! Operación con objeto no asignado! - + The creation of the relationship `%1' between the table `%2' and `%3' can not be done because one does not have a primary key. If the relationship is of the type n-n both tables must have primary keys! La criación de la Relación `%1' entre las tabla `%2' y `%3' no puede ser hecha pues una de ellas no posee una llave primária. Si la relación es del tipo n-n ambas tablas deben tener claves principales! - + The relationship of the type 1-1 where both tables are mandatory participation is not implemented because it requires fusion between the tables that breaks the modeling done by the user! La relación del tipo 1-1, donde ambas tablas son la participación obligatoria no se aplica, ya que requiere la fusión entre las tablas que rompe el modelado realizado por el usuario! - + Assignment of an invalid expression to the object! Asignación de expresión inválida a objeto! - + Assignment of a primary key to a table which already has one! Asignación de llave primaria a una tabla la cual ya poseia una! - + Identifier relationship can not be created for a self relationship, relationships of the type n-n, copy or generalization! Identificador relación no se puede crear de una relación autorelaciones del tipo n-n, dependencia o la generalización! - + Unable to create a copy relationship because the column `%1' in table `%2' already exists in table `%3'! Imposible crear una Relación de dependencia pues la columna `%1' de la tabla `%2' ya existe en la tabla `%3'! - + Unable to create the generalization relationship because the column `%1' in table `%2' can not be merged with the column `%3' of table `%4' because they have incompatible types! Imposible crear una Relación de generalización pues la columna `%1' de la tabla `%2' no puede ser funcionada con la columna `%3' de la tabla `%4' por ser de tipos incompatibles! - + Unable to create the generalization relationship because the constraint `%1' in table `%2' can not be merged with the constraint `%3' of table `%4' due to their incompatible composition! - + An attribute can not be added to a copy or generalization relationship! Un atributo no puede ser adicionado a una Relación de generalización o dependencia! - + A foreign key can not be added to a relationship because is created automatically when this is connected! Una llave estrangera no puede ser adicionado a um Relación pues esta es creada automaticamente en el momento de la conexión de la mismo! - + The object `%1' (%2) is referencing the object `%3' (%4) which was not found in the model! El objeto `%1' (%2) está referenciando el objeto `%3' (%4) el cual no fue encontrado en la lista de objetos del mismo tipo en el modelo! - + Reference to an user-defined data type that not exists in the model! Referencia un tipo de dato definido por el usuário el cual no existe en el modelo! - + Assignment of invalid maximum size to operation list! Asignación de tamaño máximo inválido a lista de operaciones! - + Unable to write the file or directory `%1'! Make sure the output directory exists, or if the user has write permissions over it! Imposible escribir en el archivo `%1'! Asegurase de que el diretório existe o si el usuário tiene permisos de aceso al mismo! - Unable to write the file `%1'' due to one or more errors in the definition generation process! - Imposible escribir el modelo en el archivo `%1'' debido a uno o más errores en el proceso de geración de la definición de el mismo! - - - + There is already a relationship between `%1' (%2) and `%3' (%4) in the model! Ya existe una Relación entre `%1' (%2) y `%3' (%4) en el modelo! - The configuration of the relationship `%1' generates a redundancy between the relationships `%2'. Redundancy on identifier or generalization/copy relationships are not accepted since they result in incorrect column spreading making the model inconsistent! - La configuración de la Relación `%1' genera una redundancia entre las Relaciones `%2'. Redundancia de Relaciones identificadores o de generalización/dependencia no son acetados pues resulta en una propagación incorreta de columnas tornando el modelo inconsiste! - - - + One or more objects were invalidated and automatically removed because they were referencing table columns which were included through relationships and which no longer exists due to disconnection of relationships or exclusion of such generated columns! Uno o más objetos fueron invalidadas y se eliminan de forma automática, ya que se hacer referencia a columnas de tabla que se incluyeron a través de relaciones y que ya no existe debido a la desconexión de las relaciones o la exclusión de tales columnas generadas! - + The primary key `%1' can only be allocated if declared within a block of code that defines a table or relationship! La llave primaria `%1' sólo puede ser asignada si es declarada dentro de un bloque de código que define una tabla o Relación! - + Reference to an invalid privilege type! Referencia a un tipo de privilégio inválido! - + Insertion of a role which already exists in the role list of the permission! La inserción de un rol que ya existe en la lista de roles de los permisos! - + Assignment of privilege incompatible with the type of object referenced by permission! Asignación de privilegios incompatibles con el tipo de objeto al que hace referencia el permiso! - + There is already a permission on object `%1' (%2) which has one or more equal roles from those present on permission to be assigned to the object! Ya existe una permiso sobre el objeto `%1' (%2) que tiene uno o más iguales roles de de aquellos presentes en el permiso para ser asignado al objeto! - + A permission is referencing the object `%1' (%2) which was not found in the model! Una permiso está referenciando al objeto `%1' (%2) el cual no fue encontrado en el modelo! - + The object `%1' (%2) can not be created because its not being assigned to any schema! El objeto `%1' (%2) no puede ser creado por no estar asignado a ningun esquema! - + The tablespace `%1' can not be inserted into the model because it points to the same directory as the tablespace `%2'! El tablespace `%1' no puede ser insertado en el modelo pues apunta para el mismo diretório que el tablespace '%2'! - + It is not possible to create arrays of domains or sequences (dimension >= 1)! PostgreSQL does not yet implement this feature! No es posíble crear arreglos de domínios o secuencias (dimención >= 1)! PostgreSQL todavía no implementa esta funcionalidad! - + The function `%1' can not get a source code as a definition because its language is set to C. Use the attributes symbol and dynamic library instead! La función `%1' no puede obtener un código fuente como una definición, porque su lenguaje se establece en C. Use el símbolo de atributos y la biblioteca dinámica en su lugar! - + The function `%1' can have the attributes symbol and dynamic library configured only if the language is set to C. For all other cases you must specify a source code that defines it in the DBMS! La función %1' puede tener el símbolo de atributos y la biblioteca dinámica configurada sólo si el idioma se establece en C. Para todos los demás casos se debe especificar un código fuente que lo define en el SGBD! - + The operator `%1' can not be assigned as a comutator of operator `%2' because it has incompatible settings! El operador %1'; no puede ser asignado como comutador de operador `%2' porque tiene configuración incompatibles! - + The operator `%1' can not be assigned as negator of operator `%2' because it has incompatible settings! El operador `%1' no puede ser asignado como negador del operador `%2' porque tiene configuración incompatibles! - + The type `%1' can not self refer in the attributes `element' or `copy type' or be used as a data type of an attribute in the configuration of a composite type! El tipo `%1' no puede ser referenciado en los atributos `elementos' o `tipo cópia' o ser usado como tipo de dato de un atributo en la configuración de tipo compuesto! - + Assignment of invalid element to type `%1'! Asignación de elemento no válido con el tipo `%1'! - + Assignment of invalid alignment to type `%1'! Asignación de elemento no válido con el tipo `%1'! - + Assignment of invalid name to the table generated from N-N relationship! Asignación de nombre no válido a la tabla genera a partir de la relación N-N! - + The relationship `%1' can not make use of the special primary key because it is marked as identifier or it is a self relationship! La Relación `%1' no puede hacer uso de la clave primaria especial. Sólo las relaciones de generalización / dependencia tienen acceso a este recurso! - + The object `%1' (%2) can not be edited or deleted because it was automatically included through a relationship! If the object is an attribute or constraint the modifications must be done on the relationship editing form. El objeto `%1' (%2) no puede ser editado o eliminado porque estaba incluido automáticamente a través de una relación! Para manipular el objeto es necesario hacerlo desde el formulario de edición de la relación que mantiene. - + The object `%1' (%2) can not be deleted because it is protected! El objeto `%1' (%2) no puede ser excluído por estar protegido! - + The group `%1' has already been declared earlier! El grupo `%1' ya fue declarado anteriormente! - + The group `%1' can not be built in the groups declaration block (%2)! El grupo `%1' no puede ser construído en el bloque de declaración de grupos (%2)! - + The group `%1' was built but not declared in the groups declaration block (%2)! El grupo `%1' fue construído pero no declarado en el bloque de declaración de grupos (%2)! - + The group `%1' can not be built without possessing child elements! El grupo `%1' no se puede construir sin poseer elementos hijos! - + The group `%1' can not be built once more because this was done in previous blocks! El grupo `%1' no puede ser construído nuevamente debido a que ya fue construído en el bloque anteriores! - + The group `%1' has been declared but not built! El grupo `%1' fue declarado pero no construído! - + Reference to a column of the objects table with invalid index! - + Reference to a row of the objects table with invalid index! Referencia a uaa columna de la tabla de objetos con índice inválido! - + The object `%1' (%2) can not be manipulated because it is reserved to PostgreSQL! This object is present in the database model only as a reference! El objeto `%1' (%2) no puede ser manipulado porque está reservado para PostgreSQL! Este objeto está presente en el modelo de base de datos sólo como una referencia! - + The new configuration of the function invalidates the object `%1' (%2)! In this case it is needed to undo the relationship between the affected object and function in order to the new configuration to take effect! La nueva configuración de la función invalida El objeto `%1' (%2)! En este caso se necesita para deshacer la relación entre el objeto afectado y la función de forma que la nueva configuración de este último tenga efecto! - + A view reference must be used in at least one these SQL scopes: View Definition, SELECT-FROM, FROM-WHERE or After WHERE! Una Referencia de Vista debe tener por lo menos una aplicación SQL: SELECT-FROM, FROM-WHERE o después WHERE! - + Constraints like primary key, foreign key or unique must have at least one column related to them! For foreign keys must be selected, in addition, the referenced columns! Restricciones como clave primaria, clave externa o único deben tener al menos una columna relacionada con ellos! Para las claves externas se deben seleccionar, además, el columnas referenciadas! - Unable to load one or more configuration files! Please check if files exists in the configuration folder and if they are not corrupted to preventing this error to occur again on the next startup! - Imposible cargar uno o más archivos de configuración! Por favor verifique si los archivos existen en la carpeta de configuración y si no se corrompen a la prevención de este error que se produzca de nuevo en el siguiente inicio! - - - Could not find the default settings file `%1'! To restore default settings check the existence of the file and try again! No fue posíble encontrar el archivo de configuración por defecto `%1'! Para restaurar la configuración predeterminada comprobar la existencia del archivo y vuelva a intentarlo! - + The export process failed due to an error triggered by the PostgreSQL server in an attempt to execute a SQL command. For more details about the error check the exception stack! ** Executed SQL command: ** @@ -4852,378 +4989,295 @@ Ref. column(s): %2 %1 El proceso de exportación falló debido a un error provocado por el servidor PostgreSQL en un intento de ejecutar un comando SQL. Para más detalles sobre el error verificar la excepción pila! -** Comando SQL ejecutado: ** - -%1 - - - - Could not load the plugin `%1' from the library `%2'! Message returned by plugin manager: `%3' - No fue posible cargar el plugin `%1' a partir de la biblioteca `%2'! Mensaje devuelto por el administrador de plugins: `%3' - - - - One or more plugins were not activated due to errors during the loading process! Check the exception stack for more details. - Uno o más plugins no se activan debido a errores durante el proceso de carga! Compruebe la pila de la excepción para obtener más detalles. - - - - Invalid syntax in file %1, line %2, column %3! - Sintaxis inválida en el archivo %1, fila %2, columna %3! - - - - Invalid instruction `%1' on file %2, line %3, column %4! - Instrución inválida `%1' en el archivo %2, linea %3, columna %4! - - - - Unknown attribute `%1' in file %2, line %3, column %4! - Atributo `%1' desconocido en el archivo %2, linea %3, columna %4! - - - - Invalid metacharacter `%1' in file %2, line %3, column %4! - Inválido metacaracter `%1' en el archivo %2, linea %3, columna %4! +** Comando SQL ejecutado: ** + +%1 - - Invalid operator `%1' in comparison expression, file %2, line %3, column %4! - Operador no válido `%1' en la expresión de comparación, el archivo %2, línea %3, columna %4! + + Could not load the plugin `%1' from the library `%2'! Message returned by plugin manager: `%3' + No fue posible cargar el plugin `%1' a partir de la biblioteca `%2'! Mensaje devuelto por el administrador de plugins: `%3' - - Attribute `%1' with an undefined value in file %2, line %3, column %4! - Atributo `%1' con valor indefinido en el archivo %2, linea %3, columna %4! + + One or more plugins were not activated due to errors during the loading process! Check the exception stack for more details. + Uno o más plugins no se activan debido a errores durante el proceso de carga! Compruebe la pila de la excepción para obtener más detalles. - Attribute `%1' with an invalid name in file %2, line %3, column %4! - Atributo `%1' con un nombre invalido el archivo file %2, linea %3, columna %4! - - - Assignment of empty XML buffer to parser! Asignación de buffer de código XML vacio o parser! - Could not access the file or directory %1! Make sure that it exists or if the user has access permissions on it! - No se pudo acceder al archivo o directorio% 1! Asegúrese de que existe o si el usuario tiene permisos de acceso sobre el mismo! - - - Assignment of empty DTD file name! Asignación de nombre de archivo DTD vacio! - + Assignment of empty name to the DTD declaration! Asignación de nombre vacio para la declaración DTD! - + Error while interpreting XML buffer at line %1 column %2. Message generated by the parser: %3. %4 Error mientras se interpretar búfer XML en línea %1 columna %2. Mensage generada por el parser: %3 %4 - + Operation on unallocated element tree! It is necessary to load the XML parser buffer and interpret it so that the tree is generated! Operación de árbol de elementos sin asignar! Es necesario para cargar el tampón parser XML e interpretar de manera que se genera el árbol! - Could not load file %1. The same appears to be inconsistent or one of its dependencies (DTD files) has errors or is missing! - No se pudo cargar el archivo %1. El mismo parece ser inconsistente o una de sus dependencias (archivos DTD) tiene errores o no se encuentra! - - - Operation with unallocated tree element! Operación con elemento de árbol sin asignar! - + Operation with element which does not exists in the element tree currently loaded! Existe Funcionamiento con elemento que no lo hace en el árbol de elementos cargados actualmente! - + Assignment of a value to an invalid connection parameter! Asignación de un valor a un parámetro de conexión no válido! - + Operation on connection not established! Operación en la conexión no se ha establecido! - + Attempt to connect without define configuration parameters! Intenta conectarse sin definir los parámetros de configuración! - + Attempt to start a connection already stablished! Intenta iniciar una conexión ya establecida! - + Could not connect to the database. Message returned: `%1' No se pudo conectar a la base de datos. Mensage retornada: `%1' - + Assignment of not allocated SQL command result! Asignación de no asignados resultado de comandos SQL! - + Unable to allocate the result of the SQL command because the response from the DBMS was not understood by the client! No se puede asignar el resultado del comando SQL porque la respuesta de los DBMS no fue entendido por el cliente! - + Unable to allocate command result for the SQL because the server has generated a fatal error! Message returned by the DBMS: `%1' No se puede asignar resultado de comandos para el SQL porque el servidor ha generado un error fatal! Mensage retornada por el SGBD: `%1' - + Reference to a column of tuple with invalid index! Referencia a una columna de tupla con índice no válido! - + Reference to a column of tuple with invalid name! Referencia a una columna de tupla con nombre no válido! - Reference to a tuple with index invalid or the result is empty (no tuples)! - La referencia a una tupla con índice no válido o el resultado es vacías (no hay tuplas)! - - - + Reference to a column of a tuple which was not yet initialized (tuple navigation not started)! Referencia a una columna de una tupla que aún no se ha inicializado (navegación de tupla no iniciado)! - + Could not execute the SQL command. Message returned: `%1' No se pudo ejecutar el comando SQL. Mensage retornada: %1 - Invalid use of a view referece as whole SQL definition! The assigned reference must be an expression! - Uso inválido de un referece vista como la definición de SQL entera! La referencia asignado debe ser una expresión! - - - + Assignment of a second definition expression to the view! Asignación de una segunda expresión definición a la vista! - + It is not possible mix ordinary references (SELECT-FROM, FROM-WHERE, After WHERE) with references used as view SQL definition! No es posible la mezcla referencias ordinarias (SELECT-FROM, FROM-WHERE, After WHERE) con referencias utilizadas como definición SQL de la vista! - + Assignment of collation object which type is invalid! Asignación de objeto que tipo de colación no es válido! - At the moment pgModeler does not support the creation of primary keys which some columns were generated by relationship connection. To create primary keys with this feature you can use the field `Indentifier' or the tab `Primary key' on relationship editing form! - Por el momento pgModeler no admite la creación de las claves principales que algunas columnas se generaron por la conexión relación. Para crear claves primarias con esta característica, puede usar el campo `Indentifidor' o en la ficha `Clave primaria' en el formulario de edición de la relación! - - - + Collations must be created at least with attributes LC_COLLATE and LC_CTYPE defined! Colaciones deben crear al menos con los atributos definidos LC_COLLATE y LC_CTYPE! - + The object `%1' (%2) cannot reference itself! This operation is not permitted for this kind of object! El objecto `%1' (%2) no se puede hacer referencia a sí mismo! No se permite esta operación para este tipo de objeto! - + Only operator families which uses `btree' as indexing method are accepted by operator class elements! Sólo las familias de operadores que utiliza ``btree' como método de indexación son aceptados por elementos de clase operador! - + Reference to an invalid copy table option! Referencia a una opción de tabla de copia no válida! - + Copy relationship between tables `%1' and `%2' cannot be done because the first one already copies attributes from `%3'! Tables can have only one copy table! Copia relación entre las tablas %1' y `%2' no se puede hacer porque el primero ya copias de los atributos `%3'! Las tablas pueden tener sólo una mesa de copia! - + The INSTEAD OF mode cannot be used on triggers that belongs to tables! This is available only for view triggers! El modo INSTEAD OF no se puede utilizar en los triggers que pertenece a tabla! Este servicio está disponible sólo para ver triggers! - + The TRUNCATE event can only be used when the trigger executes for each statement and belongs to a table! El evento TRUNCATE sólo se puede utilizar cuando el disparador se ejecuta para cada declaración y pertenece a una mesa! - + The INSTEAD OF mode cannot be used on view triggers that executes for each statement! El modo INSTEAD OF no puede ser utilizado en vista desencadenantes que ejecuta para cada declaración! - + Constraint triggers can only be executed on AFTER events and for each row! Restricciones de triggers de sólo pueden ejecutarse en eventos AFTER y para cada fila! - + A view trigger cannot be AFTER/BEFORE when it executes for each row! Un trigger de vista no puede ser AFTER/BEFORE cuando se ejecuta para cada fila! - + A trigger cannot make reference to columns when using INSTEAD OF mode and UPDATE event! Un trigger no puede hacer referencia a las columnas cuando se utiliza el modo INSTEAD OF y el evento UPDATE! - + Assignment of a column which has no parent table to the object `%1' (%2)! Asignación de una columna que no tiene ninguna tabla padre al objeto `%1' (%2)! - + Only constraint triggers can be deferrable or reference another table! Solo las restricción de triggers pueden ser prorrogable o hacer referencia a otra tabla! - Reference to a function id which is incompatible whit the user define type configuration! - Referencia a un identificador de función que es la pizca incompatibles al usuario definir la configuración de tipo! - - - + The operator class assigned to the object `%1' (%2) must use `btree' as indexing method! El operador de clase asignado al objeto `%1' (%2) puede usar `btree' como metodo de indexado! - Unsupported PostgreSQL version (%1) detected! Valid versions are: %2 - Incompatible versión (%1) de PostgreSQL detectada! Versiones válidos son: %2 - - - The validation process failed due to an error triggered by the validation helper. For more details about the error check the exception stack! El proceso de validación ha fallado debido a un error provocado por el ayudante de validación. Para más detalles sobre el error verificar la excepción pila! - + The extension `%1' is registered as a data type and cannot have the attribute `handles datatype' modified! La extensión `%1' se registra como un tipo de datos y no se puede tener el atributo `handles datatype' modificado! - + The fk relationship `%1' cannot be created because the foreign-key that represents it was not created on table `%2'! La relación fk `%1' no se puede crear porque la clave externa que representa no se ha creado en la tabla `%2'! - + Assignement of an invalid object name pattern to the relationship `%1'! Asignacion de un patrón de nombre de objeto no válido a la relación `%1'! - + Reference to an invalid object name pattern id on the relationship `%1'! Referencia a un inválido nombre del objeto patrón Identificación de la relación `%1'! - Invalid use of variadic parameter mode! This mode can be used only with array data types! - Uso no válido de modo de parámetros variadic! Este modo sólo se puede utilizar con los tipos de datos serie! - - - + Mixing incompatibles DBMS export modes: `ignore object duplications', `drop database' or `drop objects' cannot be used with `simulate export'! Mezcla incompatibles del SGDB en modos de exportación: `ignore object duplications', `drop database' or `drop objects' no se puede utilizar con `simulate export'! - + Mixing incompatibles DROP options: `drop database' and `drop objects' cannot be used at the same time! Mezcla incompatibles en la opción DROP: `drop database' y `drop objects' no puede ser utilizado al mismo tiempo! - + Invalid object id swapping operation! The objects involved are the same! Invalida operación de intercambio del objeto id! Los objetos involucrados son lo mismo! - + Invalid object id swapping operation! The database itself, tablespaces or roles cannot have the ids swapped! Invalida operación de intercambio del objeto id! La propia base de datos, tablespaces o roles no pueden tener los ids de intercambiar! - + The widget already has a parent and cannot be assigned to a different object! El widget de ya cuenta con uno de los padres y no puede ser asignado a un objeto diferente! - The object `%1' (%2) could not be imported due to one or more errors! Check the exception stack for more details. - El objeto `%1' (%2) no podía ser importado debido a uno o más errores! Compruebe la pila de la excepción para obtener más detalles. - - - Could not load the database model file `%1'. Check the error stack to see details. Try to run `pgmodeler-cli --fix-model' in order to correct the structure of the file if that is the case. No se pudo cargar el archivo de modelo de base de datos `%1'. Compruebe la pila de errores para ver los detalles. Intente ejecutar `pgmodeler-cli --fix-model' con el fin de corregir la estructura del archivo si ese es el caso. - + The column `%1' cannot reference it's parent table `%2' as data type! La columna `%1' no puede hacer referencia es la tabla padre `%2' como tipo de datos! - + Operation with an invalid element id `%1'! Operación con un elemento id `%1' no válido! - + Reference to an invalid color id `%1' for element `%2'! La referencia a un id `%1' de color no válido para el elemento `%2'! - Assignment of an invalid object to `%1' (%2)! The assigned object must be of type `%3' - Asignación de un objeto no válido a %1' (%2)! El objeto asignado debe ser de tipo `%3' - - - + The sequence `%1' can't be assigned to the column `%2' because the data type of the latter is incompatible. The type used must be an integer one! La secuencia `%1' no puede ser asignada a la columna `%2' debido a que el tipo de datos de este último es incompatible. El tipo que se utiliza debe ser un número entero! - + The option to generate temporary object names can only be used in simulation mode! La opción para generar nombres de objeto temporal sólo se puede utilizar en el modo de simulación! - It's not possible convert the type of the column `%1' to serial! It must have an `integer' based type and its default value must be a call to `nextval(seq_name::regclass)' function! - No es posible convertir el tipo de la columna `%1' a serial! Debe tener una tipo de base `integer' y su valor por defecto debe ser una llamada a la función `nextval(seq_name::regclass)'! - - - + Could not assign the variable `%1' to event trigger's filter. Currently, PostgreSQL supports only the `TAG' variable! No se pudo asignar la variable `%1' al filtrar el evento trigger's. Actualmente, PostgreSQL soporta sólo la variable `TAG'! - + Could not perform the `%1' operation on `%2' using the data on row `%3'! All changes were rolled back. ** Returned error ** @@ -5236,31 +5290,23 @@ Mensage retornada por el SGBD: `%1' %4 - + Malformed unescaped value on row `%1' column `%2'! Valor sin escapar con formato incorrecto en la fila `%1' columna `%2'! - Trying to undo/redo an invalid operation over an object that does not exists anymore! The operations history will be cleaned up. - Intenta deshacer/rehacer una operación no válida sobre un objeto que no existe más! La historia operaciones se limpiará. - - - + The object `%1' (%2) can't be handled because some needed fields are not set! Please, make sure to fill at least the requires fields in order to properly create or update the object. El objeto `%1' (%2) no se pueden manejar debido a que algunos campos necesarios no están ajustados! Por favor, asegúrese de llenar al menos la requiere campos con el fin de crear o actualizar correctamente el objeto. - + A relationship can only be swapped by other object of the same kind! Una relación sólo puede ser intercambiado por otro objeto del mismo tipo! ExtensionWidget - - Form - Formulario - Version: @@ -5290,87 +5336,83 @@ Mensage retornada por el SGBD: `%1' Formulario - + Replace one occurrence Reemplazar una ocurrencia - + Replace Reemplazar - + Replace all occurrences Reemplazar todas las ocurrencias - + Replace All Reemplazar todas - + Replace the selection and find the next one Reemplace la selección y buscar la siguiente - + Replace && Find Reemplazar && Buscar - + Replace: Reemplazar: - + Find: Buscar: - + Find previous Buscar anterior - + Shift+F3 Shift+F3 - + Find next Buscar siguiente - + F3 F3 - + Case sensitive Caso sensible - + Regular expression Expresón regular - + Whole words Palabras completas FunctionWidget - - Form - Formulario - Attributes @@ -5391,11 +5433,6 @@ Mensage retornada por el SGBD: `%1' Rows Returned: Filas Retornadas: - - - Langague: - Lenguaje: - Return Method: @@ -5406,18 +5443,15 @@ Mensage retornada por el SGBD: `%1' Behavior: Comportamiento: - - Simple - Simples - Set Conjunto - Table - Tabla + + Language: + @@ -5519,539 +5553,609 @@ Mensage retornada por el SGBD: `%1' Diseño && General - + General General - - The opened models will be saved periodically - Los modelos abiertos se guardarán periódicamente - - - - Autosave interval: - Interval Autosalva: - - - + Operation history: - Histórico Operaciones: - - - - minute(s) - minuto(s) - - - - items - items + Histórico de operaciones: - + Check if there is a new version on server Compruebe si hay una nueva versión en el servidor - - Check for updates at startup - Comprobar actualizaciones en el arranque - - - - pixels - pixeles - - - - Grid size: - Tamaño Cuadrícula: - - - + Design Diseño - + Graphical objects (table, views and textboxes) will be created in a single step without the need to click on canvas Los objetos gráficos (mesa, puntos de vista y los cuadros de texto) se crearán en un solo paso sin la necesidad de hacer clic sobre lienzo - + Simplify creation of graphical objects Simplificar la creación de objetos gráficos - + After loading the model the last zoom and position on canvas will be restored Después de cargar el modelo se restaurará el último zoom y la posición en la lona - + Save and restore last position and zoom Salvar y restaurar la última posición y el zoom - Disable antialiasing for lines and texts improving performance on huge models (requires restart) - Deshabilitar antialiasing de líneas y textos mejorar el rendimiento en los modelos grandes (requiere reiniciar) - - - + Disable render smoothness + Deshabilitar renderizado suave Deshabilitar render suave - + Hide the object that represents the relationship name Ocultar el objeto que representa el nombre de relación - + Hide relationship name Ocultar nombre de la relación - Operations like save, export and diff will be executed without asking user to validate the model - Operaciones como guardar, exportar y diff se ejecutarán sin preguntar el usuario para validar el modelo - - - + Validate before save, export or diff Validar antes de guardar, exportar o diff - - Hide the object which represents the tag assigned to the table - Ocultar el objeto que representa la etiqueta asignada a la tabla + + Hide the object which represents the tag assigned to the table + Ocultar el objeto que representa la etiqueta asignada a la tabla + + + + Hide table tags + Ocultar etiquetas de tabla + + + + Start move the canvas when the cursor is on the canvas edges + Iniciar mover el lienzo cuando el cursor está en los bordes de la lona + + + + Move canvas by keep mouse on corners + Mueva la lona por el ratón torreón en las esquinas + + + + Hide the portion of table which represent triggers, indexes and rules + Ocultar la parte de la tabla que representan triggers, índices y reglas + + + + Hide table extended attributes + Ocultar atributos de tabla extendida + + + + Enable SQL code completion + Activar autocompletado de código SQL + + + + Printing && Code + Imprimir && Cógigo + + + + pt + pt + + + + Size: + Tamaño: + + + + Font: + Fuente: + + + + Printing + Imprimiendo + + + + + Options: + Opciones: + + + + Disable antialiasing for lines and texts improving performance when handling huge models. + + + + + Triggers a dialog asking the user to validate the model before a save, export or diff operation. + + + + + When enabled this option creates a placeholder object at the previous table's position when starting to move it. This will cause graphical updates on relationship lines to be performed only when the drag & drop action is done improving the performance. Disabling placeholders will cause those updates to be executed every time the table's position changes a single pixel (classical behavior). + + + + + Use placeholders when moving tables + + + + + Toggles the code completion in all fields that accepts the input of SQL commands. + + + + + Minimum object opacity (%): + + + + + Defines the minimum opacity percentage applied to the objects when using the fade out feature. A zero opacity causes the object to be completely hidden not being possible to interact with it in the canvas area. + - - Hide table tags - Ocultar etiquetas de tabla + + Canvas grid size: + - - Start move the canvas when the cursor is on the canvas edges - Iniciar mover el lienzo cuando el cursor está en los bordes de la lona + + Defines the vertical and horizontal grid size. This value affects the spacing of objects when using object grid alignment feature. + - - Move canvas by keep mouse on corners - Mueva la lona por el ratón torreón en las esquinas + + By default the range selection is triggered with Shift + left click. By checking this option range selection will be activated only with a single click and move. + - - Hide the portion of table which represent triggers, indexes and rules - Ocultar la parte de la tabla que representan triggers, índices y reglas + + Trigger range selection with a single click + - - Hide table extended attributes - Ocultar atributos de tabla extendida + + Defines the maximum amount of elements held in the operation history. Once reached the maximum number the history is automatically cleaned. + - - By default panning mode is triggered with left click and range selection with Shift + left click. - Por defecto el modo de paneo se activa con un clic izquierdo y selección de rango con Shift + clic izquierdo. + + Defines the period when the opened models will be saved automatically. + - - Swap panning and range selection triggers - Paneo de Swap y rango de selección disparadores de triggers + + Autosave interval (minutes): + - Toggles the code completion in all fields that accepts the input of SQL commads. - Alterna la finalización de código en todos los campos que acepta la entrada de commads SQL. + + Replaces any straight line in relationship by curved ones in order to improve the model's visualization. + - - Enable SQL code completion - Activar autocompletado de código SQL + + Use curved lines for relationships + - - Printing && Code - Imprimir && Cógigo + + SQL history max. length: + - Code font style - Estilo de la fuente del código + + Souce code editor: + - - pt - pt + + lines + lineas - - Size: - Tamaño: + + Clear the entire SQL comand history. + - - Font: - Fuente: + + Clear history + Limpiar historial - - Printing - Imprimiendo + + Configurations directory: + Directorio de configuraciones: - - - Options: - Opciones: + + Browse the source code editor application + Examinar la aplicación del editor de código fuente - - Disable antialiasing for lines and texts improving performance when handling huge models. - + + Open in file manager + Abrir en el administrador de archivos - - Triggers a dialog asking the user to validate the model before a save, export or diff operation. - + + Check updates at startup + Comprobar actualizaciones al inicio - - When enabled this option creates a placeholder object at the previous table's position when starting to move it. This will cause graphical updates on relationship lines to be performed only when the drag & drop action is done improving the performance. Disabling placeholders will cause those updates to be executed every time the table's position changes a single pixel (classical behavior). + + Souce code editor args: - - Use placeholders when moving tables - + + User interface language: + Idioma de la interfaz de usuario: - - Toggles the code completion in all fields that accepts the input of SQL commands. + + 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. - + Code style - + Colors: Colores: - + Display line numbers - + Highlight lines at cursor's position - + Custom tab width: - + Print grid Imprimir cuadrícula - + Print page numbers Imprimir número de página - + Paper: Papel: - + A0 (841 x 1189 mm) A0 (841 x 1189 mm) - + A1 (594 x 841 mm) A1 (594 x 841 mm) - + A2 (420 x 594 mm) A2 (420 x 594 mm) - + A3 (297 x 420 mm) A3 (297 x 420 mm) - + A4 (210 x 297 mm) A4 (210 x 297 mm) - + A5 (148 x 210 mm) A5 (148 x 210 mm) - + A6 (105 x 148 mm) A6 (105 x 148 mm) - + A7 (74 x 105 mm) A7 (74 x 105 mm) - + A8 (52 x 74 mm) A8 (52 x 74 mm) - + A9 (37 x 52 mm) A9 (37 x 52 mm) - + B0 (1030 x 1456 mm) B0 (1030 x 1456 mm) - + B1 (728 x 1030 mm) B1 (728 x 1030 mm) - + B10 (32 x 45 mm) B10 (32 x 45 mm) - + B2 (515 x 728 mm) B2 (515 x 728 mm) - + B3 (364 x 515 mm) B3 (364 x 515 mm) - + B4 (257 x 364 mm) B4 (257 x 364 mm) - + B5 (182 x 257 mm) B5 (182 x 257 mm) - + B6 (128 x 182 mm) B6 (128 x 182 mm) - + B7 (91 x 128 mm) B7 (91 x 128 mm) - + B8 (64 x 91 mm) B8 (64 x 91 mm) - + B9 (45 x 64 mm) B9 (45 x 64 mm) - + C5E (163 x 229 mm) C5E (163 x 229 mm) - + Comm10E (105 x 241 mm) Comm10E (105 x 241 mm) - + DLE (110 x 220 mm) DLE (110 x 220 mm) - + Executive (191 x 254 mm) Ejecutivo (191 x 254 mm) - + Folio (210 x 330 mm) Folio (210 x 330 mm) - + Ledger (432 x 279 mm) Ledger (432 x 279 mm) - + Legal (216 x 356 mm) Legal (216 x 356 mm) - + Letter (216 x 279 mm) Carta (216 x 279 mm) - + Tabloid (279 x 432 mm) Tabloid (279 x 432 mm) - + Custom Personalizar - + Orientation: Orientación: - + Landscape Landscape - + Portrait Portrait - + Unity: Unidad: - + Custom Size: Tamaño Personalizado: - + Width: Ancho: - + Height: Altura: - + Page Margins: Márgenes de página: - + Left: Izquierdo: - + Left margin Margen izquierdo - + Top: Superior: - + Top margin Margen superior - + Right: Derecho: - + Right margin Margen derecho - + Bottom: Inferior: - + Bottom margin Margen inferior - + Milimeters Milímetros - + Pixels Pixeles - + Inches Pulgadas - + Centimeter Centímetros - + Line numbers' font color - + Line numbers' background color - + Highlighted line color - + The little brown fox jumps over the lazy dog + + + System default + + + + + All files (*.*) + + + + + Load file + + - GraphicalView + GenericSQLWidget - - Connected rels: %1 - Rels conectados: %1 + + SQL code + Código SQL @@ -6064,10 +6168,6 @@ Mensage retornada por el SGBD: `%1' IndexWidget - - Form - Formulario - Attributes @@ -6121,10 +6221,6 @@ Mensage retornada por el SGBD: `%1' LanguageWidget - - Form - Formulario - Trusted: @@ -6219,843 +6315,709 @@ Mensage retornada por el SGBD: `%1' Ctrl+F - msg - msg - - - + &File &Archivo - + &Edit &Editar - Help - A&yuda - - - + &Show &Mostrar - &Plugins - &Plugins - - - + General General - + Controls Controles - + &Load &Cargar - + Sa&ve as - + E&xit - + &Salir - + Exit pgModeler - + Salir de pgModeler - + &About pgModeler - + &Acerca de pgModeler - + &Print - + Im&primir - + Print model - + Imprimir modelo - + &Undo - + Undo operation - + &Redo - + Redo operation - + &Export &Exportar - + Ctrl+Shift+E - + &Show grid - + Mostrar &grid - + &Close &Cerrar - + &Normal zoom - + &Align to grid - + &Alinear a la cuadrícula - + Show &delimiters - + Mostrar &delimitadores - + &Settings - + &Configuración - + F12 F12 - + &Overview - + &Support - + &Soporte - + Access the support page - + Acceder a la página de soporte - + New Nuevo - + &Diff - + &Diff - + Design database models - + Shift+D - + Shift+M - + &Bug report - + Report a bug - + Reportar un error - + Donate - + Donar - + Help pgModeler by donating! - + ¡Ayuda a pgModeler donando! - + Objects me&tadata - + Objects metadata - - Ctrl+N - Ctrl+N + + Arrange objects + - Save - Guardar + + Rearrange objects on the canvas hierarchically + Reorganizar los objetos en el lienzo jerárquicamente + + + + Ctrl+N + Ctrl+N - + Ctrl+S Ctrl+S - + Zoom in Zoom + - + Ctrl+= Ctrl+= - + Zoom out Zoom - - + Zoom - Zoom - - + He&lp - + A&yuda - + Pl&ugins - + &New - + &Nuevo - + New model Nuevo modelo - + &Save &Guardar - + &Zoom in - + Zoo&m out - + Ctrl+- >Ctrl+- - Load - Cargar - - - + Ctrl+O Ctrl+O - Save as - Guardar como - - - Exit - Salir - - - + Ctrl+Q Ctrl+Q - About pgModeler - Acerca de pgModeler - - - + F4 F4 - Print - Imprimir - - - + Ctrl+P Ctrl+P - Undo - Deshacer - - - + Ctrl+Z Ctrl+Z - Redo - Rehacer - - - + Ctrl+Y Ctrl+Y - Export - Exportar - - - + Export the current opened model in different modes Exportar el modelo abierto actual en diferentes modos - + &Recent Models - + &Modelos Recientes - + &Import &Importar - + Rest&ore Session - + &Restaurar Sesión - + &Fix a model - + Arreglar un modelo - + &Check for update - + &Buscar actualizaciones - + Ctrl+Shift+S Ctrl+Shift+S - + Show grid Mostrar cuadrícula - + Ctrl+G Ctrl+G - Close - Cerrar - - - + Close current model Cerrar modelo actual - + Ctrl+W Ctrl+W - Normal zoom - Zoom normal - - - + Ctrl+0 Ctrl+0 - Align to grid - Alinear a la cuadrícula - - - + Align objects position to grid - Alinear objetos posición de cuadrícula + Alinear la posición de los objetos con la cuadrícula - + Ctrl+H Ctrl+H - Show delimiters - Mostrar delimitadores - - - + Show the page delimiters - Mostrar los delimitadores página + Mostrar los delimitadores de la página - + Ctrl+L Ctrl+L - Settings - Configuraciones - - - + Edit pgModeler settings Editar configuraciones de pgModeler - + Save all - Guardar todos - - - Overview - Vista General + Guardar todo - + Show the model overview - Mostrar el visión general modelo + Mostrar visión general del modelo - + F10 F10 - Wiki - Wiki - - - Access the wiki pages - Accesos a las páginas wiki - - - + F1 F1 - + New object - + Plugins Plugins - + Access the list of loaded plugins Acceda a la lista de plugins cargados - Recent Models - Modelos Recientes - - - + Load recently opened model - Cargar modelo abiertos recientes - - - Import - Importar + Cargar modelos abiertos recientemente - + Import existing database to new model (reverse engineering) Importación de base de datos existente para nuevo modelo (ingeniería inversa) - + Ctrl+Shift+I Ctrl+Shift+I - Restore Session - Restaurar sesión - - - Fix a model - Fijar un modelo - - - + New version found! Nueva versión encontrado! - + Update for the current version is available on project's site Actualización para la versión actual está disponible en el sitio del proyecto - Check for update - Buscar actualizaciones - - - + action_main_menu action_main_menu - + Main menu Menú principal - + Show expanded - Mostrar expandió + Mostrar expandido - + Expands the main menu bar in classical mode Expande la barra de menú principal en el modo clásico - + Hide main menu Ocultar menú principal - + Hides the main menu bar and put the action on a separated action Oculta la barra de menú principal y poner la acción en una acción separada - + Ctrl+Shift+H Ctrl+Shift+H - Diff - Diff - - - + Determine the changes between model and database Determinar los cambios entre el modelo y la base de datos - + Ctrl+Shift+D - + Welcome Bienvenidos - + Welcome screen Pantalla de bienvenida - + Shift+W - + Design Diseño - Design datase models - Modelos Diseño datase - - - + Manage Administrar - + Manage existent databases - Administrar base de datos existente - - - Bug report - Reporte de Bug + Administrar base de datos existentes - + (Demo) (Demo) - - Save all models - Guardar todos los modelos - - - Some models were modified! Do you really want to quit pgModeler without save them? - Se modificaron algunos modelos! ¿De verdad quiere dejar de fumar pgModeler sin salvarlos? - Saving temp. models Guardando modelos temp - + Clear Menu Limpiar Menú - + The demonstration version can create only `one' instance of database model! La versión de demostración sólo puede crear `una' instancia de modelo de base de datos! - - + + Save model Guardar Modelo - The model was modified! Do you really want to close without save it? - El modelo fue modificado! ¿De verdad quiere cerrar sin guardarlo? - - - + Save modified model(s) - + Guardar modelo(s) modificado(s) - + The following models were modified but not saved: %1. Do you really want to quit pgModeler? - + Los siguientes modelos fueron modificados pero no guardados: %1. ¿De verdad quieres salir de pgModeler? - + The model <strong>%1</strong> was modified! Do you really want to close without save it? - + Se ha modificado el modelo <strong>%1</strong>. ¿Realmente quieres cerrar sin guardarlo? - - + + Warning Advertencia - + You're running a demonstration version! The model saving feature is available only in the full version! Usted está ejecutando una versión de demostración! La función de ahorro de modelo está disponible sólo en la versión completa! - - - + + + Confirmation Confirmación - + <strong>WARNING:</strong> The model <strong>%1</strong> is invalidated! It's recommended to validate it before save in order to create a consistent model otherwise the generated file will be broken demanding manual fixes to be loadable again! <strong>ADVERTENCIA:</strong> El modelo <strong>%1</strong> está invalidado! Se recomienda para validarlo antes de guardar con el fin de crear un modelo coherente de lo contrario el archivo generado se romperá exigiendo correcciones manuales que sea cargable de nuevo! - + Save anyway Guardar de todos modos - - - + + + Validate Validar - + Save '%1' as... Guardar '%1' como... - - + + Database model (*.dbm);;All files (*.*) Modelo de base de datos (*.dbm);; Todos los arquivos (*.*) - + Access support page - + You're running a demonstration version! Note that you'll be able to create only <strong>%1</strong> instances of each type of object and some key features will be disabled or limited!<br/><br/>You can purchase a full binary copy or get the source code at <a href='http://pgmodeler.com.br'>pgmodeler.com.br</a>. <strong>NOTE:</strong> pgModeler is an open source software, but purchasing binary copies or providing some donations will support the project and cover all development costs.<br/><br/> <strong>HINT:</strong> in order to test all features it's recommended to use the <strong>demo.dbm</strong> model located in </strong>Sample models</strong> at <strong>Welcome</strong> view.<br/><br/><br/><br/> - You're running a demonstration version! The model export feature can be tested twice per pgModeler execution! - Usted está ejecutando una versión de demostración! La función de exportación modelo puede ser probado dos veces por la ejecución pgModeler! + + Rearrange objects over the canvas is an irreversible operation! Would like to proceed? + - + <strong>WARNING:</strong> The model <strong>%1</strong> is invalidated! Before run the export process it's recommended to validate in order to correctly create the objects on database server! - <strong>ADVERTENCIA:</strong> El modelo <strong>%1</strong> está invalidado! Antes de ejecutar el proceso de exportación se recomienda para validar el fin de crear correctamente los objetos en el servidor de base de datos! + <strong>ADVERTENCIA:</strong> El modelo <strong>%1</strong> está invalidado. Antes de ejecutar el proceso de exportación se recomienda validar para crear correctamente los objetos en el servidor de base de datos! - + Export anyway Exportar de todas modos - You're running a demonstration version! The database import (reverse engineering) feature is available only in the full version! - Usted está ejecutando una versión de demostración! La importación de base de datos característica (ingeniería inversa) sólo está disponible en la versión completa! - - - You're running a demonstration version! The model-database diff feature is available only in the full version! - Usted está ejecutando una versión de demostración! La función diff modelo de base de datos sólo está disponible en la versión completa! - - - + <strong>WARNING:</strong> The model <strong>%1</strong> is invalidated! Before run the diff process it's recommended to validate in order to correctly analyze and generate the difference between the model and a database! <strong>ADVERTENCIA:</strong> El modelo <strong>%1</strong> está invalidado! Antes ejecutar el proceso diff se recomienda para validar el fin de analizar correctamente y generar la diferencia entre el modelo y una base de datos! - + Diff anyway Diff de todas modo - + Database model printing Imprimir modelo de Base de datos - + Changes were detected in the definitions of paper/margin of the model which may cause the incorrect print of the objects. Do you want to continue printing using the new settings? To use the default settings click 'No' or 'Cancel' to abort printing. Se detectaron cambios en las definiciones de papel / margen del modelo que pueden causar la impresión incorrecta de los objetos. ¿Quieres continuar con la impresión utilizando la nueva configuración? Para utilizar la configuración predeterminada, haga clic 'No' o 'Cancel' para abortar la impresión. - + Load model Cargar modelo - + Could not load the database model file `%1'. Check the error stack to see details. You can try to fix it in order to make it loadable again. No se pudo cargar el archivo de modelo de base de datos `%1'. Compruebe la pila de errores para ver los detalles. Usted puede tratar de arreglarlo con el fin de hacer que se puede cargar de nuevo. - + Fix model Fijar modelo - + Cancel Cancelar - Open Wiki pages - Abrir páginas wiki - - - + This action will open a web browser window! Want to proceed? Esta acción abrirá una ventana del navegador web! ¿Quieres continuar? - + (no samples found) - (no hay ejemplos encontradas) - - - You're running a demonstration version! Note that you'll be able to create only <strong>%1</strong> instances of each type of object and some key features will be disabled!<br/><br/>You can purchase a full binary copy or get the source code at <a href='http://pgmodeler.com.br'>pgmodeler.com.br</a>. <strong>NOTE:</strong> pgModeler is an open source software, but purchasing binary copies or providing some donations will support the project and cover all development costs.<br/><br/><br/><br/> - Usted está ejecutando una versión de demostración! Tenga en cuenta que y apos; va a ser capaz de crear solamente una instancia <strong>%1</strong> de cada tipo de objeto y algunas características clave se desactivarán!<br/><br/>Usted puede comprar una copia binaria total o obtener el código fuente de <a href='http://pgmodeler.com.br'>pgmodeler.com.br</a>. -<strong>NOTA:</strong> pgModeler es un software de código abierto, pero la compra de copias binarias o proporcionar algunas donaciones apoyará el proyecto y cubrir todos los costos de desarrollo.<br/><br/><br/><br/> - - - The execution of demonstration version has finished! Did you like pgModeler and want to purchase it? Use the following promocodes and receive good discounts:<br/><br/> <strong>D3M02BR0NZ3</strong> (Discount on bronze package)<br/> <strong>D3M02S1LV3R</strong> (Discount on silver package)<br/> <strong>D3M02G0LD</strong> (Discount on gold package)<br/> <strong>D3M02PL4T1NUM</strong> (Discount on platinum package)<br/> <strong>D3M02D14M0ND</strong> (Discount on diamond package)<br/> <br/>Thank you for testing pgModeler! - La ejecución de la versión de demostración ha terminado! ¿Te ha gustado pgModeler y quiere comprarlo? Utilice los siguientes promocodes y recibir buenos descuentos:<br/><br/> <strong>D3M02BR0NZ3</strong> (Descuento un paquete de bronce)<br/> <strong>D3M02S1LV3R</strong> (Descuento un paquete de plata)<br/> <strong>D3M02G0LD</strong> (Descuento un paquete de oro)<br/> <strong>D3M02PL4T1NUM</strong> (Descuento un paquete de platino)<br/> <strong>D3M02D14M0ND</strong> (Descuento un paquete de diamante)<br/> <br/>Gracias por probar pgModeler! + (no hay ejemplos encontrados) - + save guardar - + export exportar - + diff diff - + Executing pending <strong>%1</strong> operation... Ejecución de operarienes pendientes <strong>%1</strong>... @@ -7073,69 +7035,69 @@ Mensage retornada por el SGBD: `%1' msg - + Exceptions Excepciones - + Show raw text errors or information. Mostrar errores de texto crudos o información. - + Show/hide exceptions stack. Mostrar/ocultar pila excepciones. - + ... ... - - + + &Yes &Si - - + + &No &No - + Cancel Cancelar - + &Ok &Ok - + &Cancel &Cancelar - + Error Error - + Alert Alerta - + Information Información - + Confirmation Confirmación @@ -7183,174 +7145,214 @@ Mensage retornada por el SGBD: `%1' Opciones - + Handles the following database model attributes in the metadata file: author, zoom factor, last position and default objects. - + Database model metadata - + Handles the objects' positioning in the metadata file. - + Objects' positioning - + Handles the objects' custom colors in the metadata file. Currently available only for relationships and schemas. - + Custom object's colors - + Handles the objects' protection status in the metadata file. - + Objects' protection status - + Handles the objects' SQL disabled status in the metadata file. - + Objects' SQL disabled status - Handles the objects' custom SQL commands in the metadata file. + Handles the objects' fade out status in the metadata file. - Custom SQL commands + Objects' fade out status - Save textboxes to the output file when extracting metadata. When loading the file textboxes are recreated and duplicated ones are ignored. + Save tags to the output file when extracting metadata. When loading the file, the tags are recreated and duplicated ones are ignored. - - Textbox objects + + Save textboxes to the output file when extracting metadata. When loading the file, the textboxes are recreated and duplicated ones are ignored. - - Save tags to the output file when extracting metadata. When loading the file tags are recreated and duplicated ones are ignored. + + Handles the objects' custom SQL commands in the metadata file. + + + + + Custom SQL commands + Textbox objects + + + + Tag objects - + + Handles the tables' and views' extended attributes display status in the metadata file. + + + + + Tables' extended attributes display + + + + + Save generic SQL objects to the output file when extracting metadata. When loading the file, the objects are recreated and duplicated ones are ignored. + + + + + Generic SQL objects + + + + Backup file: - - + + Select file - + ... ... - - Apply to: + + Extracts the objects' metadata from the loaded models and apply to the current focused model. A backup file can be specified to where the focused model's current metadata will be saved. - - Operation: + + &Extract and restore + + + + + Extracts the objects metadata from one of the loaded models saving the info to a backup file. + + + + + Extract &only - - Extracts the objects metadata from one of the loaded models and apply to the current model. + + Reads the objects' metadata from a previously saved backup file and apply to the current model. - - Extract from a &model + + &Restore a backup file - - Reads the objects metadata from a previously saved backup file and apply to the current model. + + Apply to: - - Restore a bac&kup file + + Operation: - + Output Salida - + Progress label... - - + + model not saved yet - + The backup file cannot be the same as the input model! - + Extracting metadata to file `%1' - + Saving backup metadata to file `%1' - + Applying metadata from file `%1' - + Metadata processing aborted! - + Objects metadata file (*.omf);;All files (*.*) @@ -7373,406 +7375,399 @@ Mensage retornada por el SGBD: `%1' Configuraciones - + Input database Base de datos de entrada - + Connection: Conexión: - Connect and list available databases - Conectar y listar las bases de datos disponibles - - - + ... ... - + Database: bases de datos: - - Options - Opciones - - - Ignores as many as possible errors on import step. This option generates a incomplete diff. - Ignora mayor número posible de errores en la etapa de importación. Esta opción genera un diff incompleta. - - - + Ignore import errors Ignorar errores de importación - Clears the data of all tables which will have columns modified. This is useful to avoid errors related to type casting. <strong>WARNING:</strong> DO NOT use this option on production server and always make a backup before use this options. - Borra los datos de todas las tablas que se han modificado las columnas. Esto es útil para evitar errores relacionados con el tipo de conversión. <strong>ADVERTENCIA:</strong> NO use esta opción en el servidor de producción y siempre hacer una copia de seguridad antes de utilizar esta opción. - - - + Trucate tables before alter columns Trucate tablas antes alterar las columnas - Import system (built in) objects. Use this if the import step is returning errors. - Sistema de Importación (incorporada) objetos. Utilice esta opción si el paso de importación está volviendo errores. - - - + Import system objects Importar objectos del sistema - Import extension objects. Use this if the import step is returning errors even importing built in ones. - Importar extensión de objecto. Utilice esta opción si el paso de importación está volviendo errores incluso importadora construidas en unos. - - - + Import extension objects Importar extensión de objecto - + For DROP command, the objects that depends on an object to be dropped will be deleted as well. For TRUNCATE command, tables that are linked to a table to be truncated will be truncate too. <strong>NOTE:</strong> this option can affect more objects than listed in the output or diff preview. Para comando DROP, los objetos que depende de un objeto que se retiren serán eliminados también. Para comando TRUNCATE, tablas que están vinculadas a una mesa para truncar se truncará también. <strong>NOTA:</strong> esta opción puede afectar a varios objetos que se enumeran en la salida o diff vista previa. - + Drop or truncate in cascade mode Drop o truncate en cascada mode - + Permissions already set on database objects will be kept.The ones configured on the model will be applied to the database. Permisos ya establecidos en los objetos de base de datos serán los kept.The configuradas en el modelo se puede aplicar a la base de datos. - + Keep object's permissions Mantenga los permisos del objeto - + Database cluster level objects like roles and tablespaces will not be dropped. No se cayeron objetos de base de datos a nivel de grupo como los roles y espacios de tabla. - + Keep cluster objects Mantenga objetos clúster - + Recreate only unmodifiable objects Recrear objetos sólo no modificables - Instead of use an ALTER command to modify certain kind of objects a DROP and CREATE will be used in order to do a full modification. This option does not affects database objects. - En lugar de utilizar el comando ALTER para modificar un cierto tipo de objetos un DROP y CREATE serán utilizados con el fin de hacer una modificación completa. Esta opción no afecta a los objetos de base de datos. - - - + Force recreation of objects Forzar recreación de objetos - + Ignores errors generated by duplicated objects when exporting the diff to database. Ignora errores generados por objetos duplicados cuando se exporta el diff de base de datos. - + Ignore duplicity errors Ignorar duplicidad de errores - + Serial columns are converted to integer and having the default value changed to <strong>nextval(sequence)</strong> function call. By default, a new sequence is created for each serial column but checking this option sequences matching the name on column's default value will be reused and will not be dropped. Columnas de serie se convierten a entero y haber cambiado el valor predeterminado para llamada a la función <strong>nextval(sequence)</strong>. De forma predeterminada, se crea una nueva secuencia para cada columna de serie, pero marcando esta opción secuencias que coinciden con el nombre en valor por defecto de la columna se volverá a utilizar y no se borró. - + Reuse sequences on serial columns Reciclar secuencias sobre columnas de serial - + Diff mode Modo diff - + Override the PostgreSQL version when generating the diff. The default is to use the same version as the input database. Anular la versión de PostgreSQL al generar el diff. El valor por defecto es usar la misma versión que la base de datos de entrada. - + Use PostgreSQL: Use PostgreSQL: - + Compares the model and the input database storing the diff in a SQL file for later usage. Compara el modelo y la base de datos de entrada almacenar el diff en un archivo SQL para un uso posterior. - Store in SQL file - Almacenar en archivo SQL - - - + File: Archivo: - + Select output file Seleccionar archivo de salida - + Compares the model and the input database generating a diff and applying it directly to the latter. <strong>WARNING:</strong> this mode causes irreversible changes on the database and in case of failure the original structure is not restored, so make sure to have a backup before proceed. Compara el modelo y la base de datos de entrada generar un diff y aplicándolo directamente a éste. < strong>ADVERTENCIA:</strong> este modo provoca cambios irreversibles en la base de datos y en caso de fallo de la estructura original no se restablece, así que asegúrese de tener una copia de seguridad antes de proceder. - Apply on server - Aplicar en el servidor - - - + Ignores as many as possible errors on import step. This option generates an incomplete diff. - + Clears the data of all tables which will have columns modified. This is useful to avoid errors related to type casting. <strong>WARNING:</strong> DO NOT use this option on production servers and always make a backup before use it. - + Import system (built-in) objects. Use this if the import step is returning errors related to missing objects. - + Import objects created by extensions. Use this if the import step is returning errors even importing built in ones. - + Instead of use an ALTER command to modify certain kind of objects a DROP and CREATE will be used in order to do a full modification. This option does not affects the database object. - + No command to rename the destination database will be generated even the model's name differ from database name. - + Preserve database name - + Avoid the generation of DROP commands for objects that exists in database but not in the model. This is useful when diff a partial model against the complete database. - + Do not drop missing objects - + Store in S&QL file - + Appl&y on server - + + Diff + Diff + + + + Import && Export + + + + + Import + Importar + + + + Export + Exportar + + + + This advanced option causes pgModeler to ignore extra errors by their numeric codes. These errors must be informed in the input below and separeted by space. For the complete list of error codes check the PostgreSQL docs, section <strong> Appendix A. PostgreSQL Error Codes</strong>. <strong>WARNING:</strong> use this option with extreme care since it can interfere in final export result. + + + + + Ignore error codes + + + + Output Salida - + Changes: Cambios: - + Cancel Cancelar - + Progress label... Etiqueta de progreso... - + Step label... Etiqueta de pasos... - + <html><head/><body><p>Objects marked with an <span style=" font-weight:600;">ALTER</span> may not be effectively changed unless that the differences detected are in attributes that can be modified through ALTER commands otherwise no operationwill be performed or, if the force recreation is checked, the object will be dropped and created again.</p></body></html> <html><head/><body><p>Objetos marcados con un <span style=" font-weight:600;">ALTER</span> No se puede cambiar de manera efectiva a menos que las diferencias detectadas son en los atributos que se pueden modificar a través de comandos ALTER de lo contrario no se realizará ninguna operationwill o, si la fuerza de la recreación está marcada, el objeto será dado de baja y creó de nuevo.</p></body></html> - + Objects to be created Objetos que se creen - - - - + + + + 0 0 - + Objects to be dropped Objetos que se borran - + Possible objects to be changed Objetos posibles de ser cambiados - + Ignored objects (system ones or with sql disabled) Objetos ignorados (los del sistema o con sql disabilitado) - + Diff Preview Vista previa Diff - + &Apply diff &Aplicar diff - + &Generate &Generar - + &Close &Cerrar - - + + Waiting process to start... Proceso en espera para iniciar... - + Importing database <strong>%1</strong>... Importando base de datos <strong>%1</strong>... - + Comparing the model <strong>%1</strong> and database <strong>%2</strong>... Comparando el modelo <strong>%1</strong> y la base de datos <strong>%2</strong>... - + Confirmation Confirmación - + <strong>WARNING:</strong> The generated diff is ready to be exported! Once started this process will cause irreversible changes on the database. Do you really want to proceed? <strong>ADVERTENCIA:</strong> El diff generada está listo para ser exportado! Una vez iniciado este proceso provocará cambios irreversibles en la base de datos. ¿Realmente desea continuar? - + Apply diff Aplicar diff - + Preview diff Vista previa Diff - + Exporting diff to database <strong>%1</strong>... Exportando diff a base de datos <strong>%1</strong>... - + Diff process paused. Waiting user action... Proceso Diff en pausa. Esperando acción del usuario... - + Saving diff to file <strong>%1</strong> Guardando diff a archivo <strong>%1</strong> - + Diff process sucessfully ended! Proceso Diff finalizado satisfactoriamente! - - + + No operations left. No hay operaciones a la izquierda. - + Operation cancelled by the user. Operación cancelada por el usuario. - + Process aborted due to errors! Proceso abortado debido a errores! - + -- SQL code purposely truncated at this point in demo version! - + -- No differences were detected between model and database. -- -- No se detectaron diferencias entre el modelo y la base de datos. -- - + Error code <strong>%1</strong> found and ignored. Proceeding with export. Error de código encontrado <strong>%1</strong> y ignorado. Procediendo con la exportación. - + Save diff as... Salvar diff como... - + SQL code (*.sql);;All files (*.*) Código SQL (*.sql);;Todos los archivos (*.*) @@ -7795,227 +7790,217 @@ Mensage retornada por el SGBD: `%1' Configuración - + Database server Servidor de Bases de datos - + pgModeler ignores errors generated by duplicated objects and creates only that ones which does not exists in the database. This option may be used when an object was created after a previous model export. El pgModeler ignora los errores generados por objetos duplicados y sólo crea objetos del modelo que no existen en la base de datos. Esta opción se puede usar cuando un objeto fue creado después de una exportación de modelo posterior. - + Ignore object duplicity Ignorar duplicidad de objetos - + Connection: Conexión: - + PostgreSQL version in which the SQL code should be generated. It is recommended to select this option only when the version of the DBMS, somehow, is not identifiable or if you need to generate a specific version of SQL code for test purposes. PostgreSQL versión en la que se debe generar el código SQL. Se recomienda seleccionar esta opción sólo cuando la versión del SGDB, de alguna manera, no es identificable o si usted necesita para generar una versión específica de código SQL con fines de prueba. - - + + PostgreSQL: PostgreSQL: - + + This advanced option causes pgModeler to ignore extra errors by their numeric codes. These errors must be informed in the input below and separeted by space. For the complete list of error codes check the PostgreSQL docs, section <strong> Appendix A. PostgreSQL Error Codes</strong>. <strong>WARNING:</strong> use this option with extreme care since it can interfere in final export result. + + + + + Ignore error codes + + + + If <strong>DB</strong> is checked pgModeler will destroy the database if already exists on the server. When <strong>Objects</strong> is checked pgModeler will execute the DROP command attached to SQL-enabled objects. <strong>WARNING:</strong> this option leads to data loss so make sure to have a backup first. Si <strong>BD</strong> se comprueba pgModeler destruirá la base de datos si ya existe en el servidor. Cuando <strong>Objetos</strong> se comprueba pgModeler ejecutará el comando DROP unido a objetos de SQL-habilitado. <strong>ADVERTENCIA:</strong> esta opción conduce a la pérdida de datos, así que asegúrese de tener una copia de seguridad primero. - + Drop: Borrar: - + DB BD - Objects - Objectos - - - + pgModeler will destroy the database if already exists on the server. Make sure to have a backup before use this option because all data will be lost. pgModeler destruirá la base de datos si ya existe en el servidor. Asegúrese de tener una copia de seguridad antes de usar esta opción porque se perderán todos los datos. - PNG Image - Imagen PNG - - - + Zoom: Zoom: - + Show grid Mostrar cuadrícula - + Show delimiters Mostrar delimitadores - + Exporting the model page by page will generate files with a <strong>_p[n]</strong> suffix where <strong>n</strong> is the page id. Check if the current user has write permission on output folder. Exportación de la página modelo por página generará archivos con un <strong>_p[n]</strong> sufijo donde <strong>n</strong> es el identificador de página. Compruebe si el usuario actual tiene permiso de escritura en la carpeta de salida. - + Page by page Página por página - - + + Select target file Seleccionar archivo de destino - - + + ... ... - Image: - Imagen: - - - + SQL file Archivo SQL - - + + File: Archivo: - + Ob&jects - + Graphics file - - Image (PNG) - - - - + Type: Tipo: - - Vectorial (SVG) + + PostgreSQL version in which the SQL code should be generated + PostgreSQL versión en la que se debe generar el código SQL + + + + I&mage (PNG) - - PostgreSQL version in which the SQL code should be generated - PostgreSQL versión en la que se debe generar el código SQL + + &Vectorial (SVG) + - + Output Salida - + Cancel Cancelar - + Progress label... Etiqueta de progreso... - + &Export &Exportar - + &Close &Cerrar - + Error code <strong>%1</strong> found and ignored. Proceeding with export. Error de código encontrado en <strong>%1</strong> y ignorado. Procediendo con la exportación. - + Initializing model export... Inicializando exportación del modelo... - + Saving file '%1' Guardar archivo '%1' - - + + Exporting process aborted! Porceso de exportación abortado! - + Export model as... Exportar modelo como... - + SQL script (*.sql);;All files (*.*) - + Portable Network Graphics (*.png);;All files (*.*) - + Scalable Vector Graphics (*.svg);;All files (*.*) - SQL code (*.sql);;All files (*.*) - Código SQL(*.sql);;Todos los archivos (*.*) - - - Imagen PNG (*.png);;Todos los archivos (*.*) - Imagen PNG (*.png);;Todos los archivos (*.*) - - - + Exporting process canceled by user! Proceso de exportación cancelada por el usuario! - + Exporting process sucessfuly ended! Proceso de exportación terminó satisfactoriamente! @@ -8023,156 +8008,140 @@ Mensage retornada por el SGBD: `%1' ModelExportHelper - + Generating SQL code for PostgreSQL `%1' Generación de código SQL para PostgreSQL `%1' - + Output SQL file `%1' successfully written. Archivo SQL de salida `%1' escrito satisfactoriamente. - + Rendering objects to page %1/%2. Renderiando objetos a la página %1/%2. - + Output image `%1' successfully written. Imagen de salida `%1' escrito satisfactoriamente. - + Exporting model to SVG file. - + SVG representation of database model - + SVG file generated by pgModeler - + Output file `%1' successfully written. - + Starting export to DBMS. Comenzando exportación a SGDB. - + PostgreSQL version detection overridden. Using version `%1'. Versión detección PostgreSQL anulado. Al usar la versión. Usar la versión `%1'. - + PostgreSQL `%1' server detected. Servidor PostgreSQL `%1' detectado. - + Generating temporary names for database, roles and tablespaces. Generar nombres temporales para bases de datos, roles y tablespaces. - + Enabling the SQL code for database `%1' to avoid errors. Habilitar el código SQL para la base de datos `%1' para evitar errores. - + Ignoring object duplication errors. Ignorando los errores de duplicación de objetos. - + Ignoring the following error code(s): `%1'. Ignorando el código de error siguiente (s): `%1'. - + Trying to drop database `%1'. Tratando de borrarr la base de datos `%1'. - + Simulation mode activated. Modo de simulación activado. - Creating object `%1' (%2). - Creación de objetos `%1' (%2). - - - Creating database `%1'. - Creando basea de datos `%1'. - - - Connecting to database `%1'. - Conectando a base de datos`%1'. - - - + Generating SQL for `%1' objects... Generación de SQL para los objetos `%1'... - + Destroying objects created on the server. Destruyendo los objetos creados en el servidor. - + Restoring original names of database, roles and tablespaces. Restauración de los nombres originales de base de datos, roles y tablespaces. - Dropping object `%1' (%2). - Borrando objetos `%1' (%2). - - - - - + + + Creating object `%1' (%2) Creando objecto `%1' (%2) - + Creating database `%1' - + Connecting to database `%1' - + Renaming `%1' (%2) to `%3' - - + + Dropping object `%1' (%2) Borrando objetos `%1' (%2) - + Changing object `%1' (%2) Cambiando objecto `%1' (%2) - + Running auxiliary command. Ejecución de comandos auxiliar. @@ -8250,18 +8219,6 @@ p, li { white-space: pre-wrap; } Fix tries: Fijar intentos: - - <!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:'Monospace'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Waiting process to start...</p></body></html> - <!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:'Monospace'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Proceso que espera para iniciar...</p></body></html> - Select input file @@ -8321,30 +8278,22 @@ p, li { white-space: pre-wrap; } - + Alt+C - - Ctrl+Up - Ctrl+Up - Next model Siguiente modelo - Ctrl+Down - Ctrl+Down - - - + Close model Cerrar modelo - + ... ... @@ -8490,6 +8439,12 @@ p, li { white-space: pre-wrap; } Model overview Vista general del modelo + + + Failed to generate the overview image. +The requested size %1 x %2 was too big and there was not enough memory to allocate! + + ModelRestorationForm @@ -8543,20 +8498,16 @@ p, li { white-space: pre-wrap; } &Restore &Restaurar - - Modified: %1 - Modificado: %1 - ModelValidationHelper - + There are pending errors! SQL validation will not be executed. Hay errores pendientes! No se ejecutará la validación de SQL. - + Operation canceled by the user. Operación cancelada por el usuario. @@ -8569,143 +8520,123 @@ p, li { white-space: pre-wrap; } Formulario - + Enables the validation of SQL code in DBMS. This process requires the use of a pre-configured connection. SQL validation will occur only in the last step (when all objects were validated) or when there are no warnings. - + Connection to be used in the SQL validation - + pgModeler will generate unique and temporary names for database, role and tablespace objects. This option avoids object duplication errors when running the SQL validation. - + Use unique temporary names for cluster level objects - + Warnings: does not prevents model to be saved. Advertencias: no previene modelo para ser salvos. - - + + 0 0 - + Errors: model will not be saved while there are validation errors. Errores: modelo no se guardará mientras que hay errores de validación. - + Hide this widget Ocultar este widget - + ... ... - Use unique temporary names for database, role and tablespace objects - Utilice nombres temporales únicos para objetos de base de datos, de rol y tablespace - - - Enable validation of SQL code on DBMS (requires connection) - Habilitar validación de código SQL en DBMS (requiere conexión) - - - + SQL Validation: Validación de SQL: - Connection alias - Alias de conexión - - - + PostgreSQL version Versión PostgreSQL - SQL validation, if enabled, will occur only on the last step or when there are no warnings. - Validación de SQL, si está habilitado, se producirá sólo en el último paso o cuando no hay advertencias. - - - Using temporary names will avoid object duplication errors when running the SQL validation. - El uso de nombres temporales evitará errores de duplicación de objetos cuando se ejecuta la validación de SQL. - - - + Try to resolve the reported issues. Trate de resolver los problemas comunicados. - + Apply Fix Aplicar Fijar - + Ctrl+S Ctrl+S - + Clear validation results Limpiar resultados de la validación - + Clear Limpiar - + Try to apply a fix on the selected validation info. Trate de aplicar una solución en la información de validación seleccionado. - + Options Opciones - + Cancel the SQL validation in progress. Cancelar la validación de SQL en curso. - + Cancel Cancelar - + Esc Esc - + Change the creation order for two objects by swapping their ids Cambiar el orden de la creación de dos objetos mediante el canje de sus ids - + Swap Ids Intercambiar Ids - + Va&lidate Va&lidar @@ -8715,84 +8646,72 @@ p, li { white-space: pre-wrap; } Autodetectar - + The object <strong>%1</strong> <em>(%2)</em> [id: %3] is being referenced by <strong>%4</strong> object(s) before its creation. El objeto <strong>%1</strong> <em>(%2)</em> [id:% 3] está siendo referenciado por <strong>%4</strong> objeto(s) antes de su creación. - + The object <strong>%1</strong> <em>(%2)</em> [id: %3]%4 is referencing columns created by <strong>%5</strong> relationship(s) but is created before them. El objeto <strong>%1</strong> <em>(%2)</em> se hace referencia a las columnas creadas por <strong>%5</strong> relación (es), pero se crea ante ellos. - + The object <strong>%1</strong> <em>(%2)</em> has a name that conflicts with <strong>%3</strong> object's name(s). El objeto <strong>%1</strong> <em>(%2)</em> tiene un nombre que entre en conflicto con <strong>%3</strong> nombre(s) de objteto(s). - + The relationship <strong>%1</strong> [id: %2] is in a permanent invalidation state and needs to be relocated. - + <strong>HINT:</strong> 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. - + SQL validation not executed! No connection defined. - + Database model successfully validated. - The relationship <strong>%1</strong> [id: %2] is in a permanent invalidation state and need to be rellocated. - La relación <strong>%1</strong> [id: %2] está en un estado permanente invalidación y necesitan ser recargado. - - - + SQL validation failed due to error(s) below. <strong>NOTE:</strong><em> These errors does not invalidates the model but may affect operations like <strong>export</strong> and <strong>diff</strong>.</em> Validación de SQL ha fallado debido a un error (s) a continuación. <strong>NOTA:</strong><em> Estos errores no invalida el modelo, pero pueden afectar a las operaciones como <strong>export</strong> and <strong>diff</strong>.</em> - <strong>HINT:</strong> try to swap the mentioned relationship by another one in order to solve this situation. Note that other objects may be lost in this process. - <strong>HINT:</strong> intentar cambiar la relación mencionada por otro con el fin de resolver esta situación. Tenga en cuenta que otros objetos se pueden perder en este proceso. - - - + <em>The above object was created by a relationship. Change the name pattern on it's generator relationship. Fix will not be applied!</em> <em>El objetivo anterior fue creado por una relación. Cambiar el patrón de nombre en él la relación de generador. Fijar no se aplicará!</em> - + Conflicting object: <strong>%1</strong> <em>(%2)</em>. Objeto en conflicto: <strong>%1</strong> <em>(%2)</em>. - + Relationship: <strong>%1</strong> [id: %2]. Relación: <strong>%1</strong> [id: %2]. - + Referrer object: <strong>%1</strong> <em>(%2)</em> [id: %3]. Objeto referente:: <strong>%1</strong> <em>(%2)</em> [id: %3]. - Database model sucessfully validated. - Modelo de base de datos con éxito validado. - - - + Running SQL commands on server... Ejecución de comandos SQL en el servidor... - + Processing object: %1 Procesando object: %1 @@ -8800,397 +8719,493 @@ p, li { white-space: pre-wrap; } ModelWidget - + One to One (1-1) Uno a Uno (1-1) - + One to Many (1-n) - Uno a Mucho (1-n) + Uno a Muchos (1-n) - + Many to Many (n-n) Mucho a Mucho (n-n) - - + + Copy Copiar - Generalization - Generalización - - - + Inheritance Herencia - + <strong>ATTENTION:</strong> The database model is protected! Operations that could modify it are disabled! <strong>ATENCIÓN:</strong> El modelo de base de datos está protegida! Operaciones que podrían modificar la misma son habilitado! - + Source Fuente - + Alt+S Alt+S - + Show object source code Exibir el código-Fuente del objeto - - + + Properties Propiedades - + Space Espacio - + Edit the object properties Edita las propriedades del objeto - - + + Protect Proteger - - + + Unprotect Desproteger - + Protects object(s) from modifications Protege objeto(s) a partir de las modificaciones - - + + Delete Eliminar - + Del Del - - + + Del. cascade Del. cascada - + Shift+Del Shift+Del - + Select all Seleccionar todos - + Ctrl+A Ctrl+A - + Selects all the graphical objects in the model Selecciona todos los objetos gráficos en el modelo - + Convert Convertir - + Ctrl+C Ctrl+C - + Paste Pegar - + Ctrl+V Ctrl+V - + Cut Cortar - + Ctrl+X Ctrl+X - + Deps && Referrers Deps && Referreridos - + New Nuevo - + Add a new object in the model Adicionar un nuevo objeto en el modelo - + Quick Rápido - + Quick action for the selected object Acciones rápidas para la selección de objecto - + Rename Renombrar - + F2 F2 - + Quick rename the object Renombrar rápida del objeto - + Move to schema Mover al esquema - + Set tag Configurar tag - + Edit permissions Editar permisos - + Ctrl+E Ctrl+E - + Change owner Cambiar propietario - + Select children Seleccione los hijos - + + Select tagged + + + + Highlight Aspecto interesante - + Open relationship Abrir relación - + Custom SQL - Personalizas SQL + Personalizar SQL - + Alt+Q Alt+Q - + Convert to sequence Converir a secuencia - + Convert to serial - Converir a seral + Converir a serial - + Break line Saltos de líena - + Remove points Remover puntos - + Enable SQL Habilitar SQL - + Disable SQL - Deshaabilitar SQL + Deshabilitar SQL - + + Duplicate + Duplicar + + + + Ctrl+D + + + + + Extended attributes + Atributos extendidos + + + + Show + Mostrar + + + + Hide + Ocultar + + + + Jump to table + Ir a tabla + + + + Fade in/out + + + + + + Fade in + + + + + + Fade out + + + + + + + Relationships + Relaciones + + + + Swap ids + + + + + Edit the objects creation order by swapping their ids + + + + 90° (vertical) 90° (vertical) - + 90° (horizontal) 90° (horizontal) - + 90° + 90° (vertical) 90° + 90° (vertical) - + 90° + 90° (horizontal) 90° + 90° (horizontal) - + + + + All objects + Todos los objetos + + + + + Schemas + + + + + + Tables + Tablas + + + + + Views + Vistas + + + + + Textboxes + + + + Zoom: %1% Zoom: %1% - + Do you really want to convert the relationship into an intermediate table? ¿Realmente desea convertir la relación en una tabla intermedia? - + Loading database model Cargando modelo de base de datos - + Saving database model Guardando modelo de base de datos - + Do you want to %1 the selected schema's children too? - + protect - + unprotect - + Also copy all dependencies of selected objects? This minimizes the breakdown of references when copied objects are pasted into another model. También copiar todas las dependencias de los objetos seleccionados? Esto minimiza la ruptura de referencias cuando los objetos copiados se pegan en otro modelo. - + Pasting objects... Pegar Objetos... - + Validating object: `%1' (%2) Validando El objeto: `%1' (%2) - + Generating XML for: `%1' (%2) Generando código XML del objeto: `%1' (%2) - + Pasting object: `%1' (%2) Pegar Objetos: `%1' (%2) - + Not all objects were pasted to the model due to errors returned during the process! Refer to error stack for more details! No todos los objetos se pegan a la modelo debido a errores devueltos durante el proceso! Consulte a un error de pila para más detalles! - + <strong>CAUTION:</strong> You are about to delete objects in cascade mode which means more objects than the selected will be dropped too. Do you really want to proceed? <strong>PRECAUCIÓN:</strong> Estás a punto de eliminar objetos en modo de cascada que significa más objetos que el seleccionado se redujo también. ¿Realmente desea continuar? - + <strong>CAUTION:</strong> Remove multiple objects at once can cause irreversible invalidations to other objects in the model causing such invalid objects to be deleted too. Do you really want to proceed? <strong>PRECAUCIÓN:</strong> Eliminar varios objetos a la vez puede causar invalidaciones irreversibles a otros objetos en el modelo que causa este tipo de objetos no válidos para ser borrados también. ¿Realmente desea continuar? - + <strong>CAUTION:</strong> Remove a relationship can cause irreversible invalidations to other objects in the model causing such invalid objects to be deleted too. Do you really want to proceed? <strong>PRECAUCIÓN:</strong> Eliminar una relación puede causar invalidaciones irreversibles a otros objetos en el modelo que causa este tipo de objetos no válidos para ser borrados también. ¿Realmente desea continuar? - + Do you really want to delete the selected object? ¿Realmente desea eliminar el objeto seleccionado? - + The cascade deletion found some problems when running! Some objects could not be deleted or registered in the operation's history! Please, refer to error stack for more details. La eliminación en cascada encontró algunos problemas al ejecutar! Algunos objetos no podían ser borrados o registrados en la historia de la operación! Por favor, consulte a un error de la pila para obtener más detalles. - + (no objects) (no hay objetos) - + Source code Código fuente - + Constraints Restricciones @@ -9198,39 +9213,35 @@ p, li { white-space: pre-wrap; } ModelsDiffHelper - + Processing object `%1' (%2)... Procesando objecto `%1' (%2)... - + Skipping object `%1' (%2)... Omitiendo objeto `%1' (%2)... - + Processing diff infos... Procesando diff infos... - + Processing `%1' info for object `%2' (%3)... - + No differences between the model and database. - + Preparing diff code... - - Comparison between model and database finished. - Comparación entre el modelo y la base de datos terminado. - NewObjectOverlayWidget @@ -9256,7 +9267,7 @@ p, li { white-space: pre-wrap; } - + A A @@ -9286,7 +9297,7 @@ p, li { white-space: pre-wrap; } Esquema - + Domain Dominio @@ -9296,268 +9307,278 @@ p, li { white-space: pre-wrap; } Conversión - + Aggregate Agregado - + Collation Collation - + Table Tabla - + Type Tipo - + Op. Family Op. Familia - + Sequence Sequencia - + Extension Extensión - + Function Función - + Op. Class Op. Clase - + Operator Operador - + View Vista - - + + Permissions Permisos - + Rule Regla - + Index Indice - + Column Columna - + Constraint Restricción - + + Generic SQL + + + + Trigger Trigger - + Many-to-many - Mucho-a-mucho + Muchos-a-muchos - + One-to-many - Uno-a-mucho + Uno-a-muchos - + One-to-one Uno-a-uno - + Inheritance Herencia - + Copy Copia - + G G - + K K - + H H - + J J - + D D - + E E - + F F - + L L - + O O - + U U - + I I - + R R - + S S - + Q Q - + T T - + P P - + M M - + Y Y - + W W - + 9 9 - + Z Z - + X X - + C C - + V V - + B B + 8 + 8 + + + 1 1 - + 2 2 - + 3 3 - + 5 5 - + 4 4 - + 0 0 @@ -9565,84 +9586,121 @@ p, li { white-space: pre-wrap; } NumberedTextEditor - + + + Load file + + + + + Load the object's source code from an external file + + + + + Edit source + + + + + Edit the source code in the preferred external editor + + + + + Clear + Limpiar + + + Upper case - + Lower case - + Ident right - + Ident left + + + SQL file (*.sql);;All files (*.*) + Archivo SQL (*.sql);;Todos los archivos (*.*) + + + + The source code is currently being edited in the application `%1' (pid: %2)! Only one instance of the source code editor application is allowed. + + + + + Could not start the source code editor application `%1'! Make to sure that the source editor path defined in the general settings points to a valid executable and the current user has permission to run the application. Error message returned: `%2' + + ObjectDepsRefsWidget - - Form - Formulario - Dependencies Dependencias - - + + ID ID - - + + Object Objecto - - + + Type Tipo - - + + Parent Object Objeto Padre - - + + Parent Type Tipo del Padre - + Exclude indirect dependencies Excluir dependencias indirectas - + References Referencias - + Include indirect references Incluir referencias indirectas - + This object does not exists anymore. The dependencies and references listing are disabled. Este objeto no existe más. Las dependencias y referencias listadas se deshabilitan. @@ -9665,7 +9723,7 @@ p, li { white-space: pre-wrap; } Patrón: - + Find Buscar @@ -9708,7 +9766,7 @@ p, li { white-space: pre-wrap; } Hide this widget - Ocultar este widget + Ocultar este widget @@ -9736,37 +9794,37 @@ p, li { white-space: pre-wrap; } Sensible Case - + ID ID - + Object Objecto - + Type Tipo - + Parent Object Objecto Padre - + Parent Type Tipo del Padre - + Found <strong>%1</strong> object(s). Encontrado objecto(s) <strong>%1</strong>. - + No objects found. Objetos no encontrados. @@ -9872,86 +9930,88 @@ p, li { white-space: pre-wrap; } + Duplicate item + + + + + Ctrl+D + + + + Edit Item Editar Item - + Space Espacio - + Move Up Mover Arriba - + Ctrl+Up Ctrl+Up - + Move Down Mover Abajo - + Ctrl+Down Ctrl+Down - + Move to start Mover al inicio - + Ctrl+Home Ctrl+Home - + Move to end Mover al final - + Ctrl+End, Ctrl+S Ctrl+End, Ctrl+S - - + + Confirmation Confirmación - + Do you really want to remove the selected item? ¿Realmente desea eliminar el elemento seleccionado? - - Do you really want to remove the all items? - ¿Realmente desea eliminar los todos los artículos? + + Do you really want to remove all the items? + OperationList - + (invalid object) (objeto no válido) - - Undoing change on object `%1' (%2). - Deshacer el cambio en el objeto `%1' (%2). - - - Redoing change on object `%1' (%2). - Rehacer el cambio en el objeto `%1' (%2). - OperationListWidget @@ -10008,65 +10068,53 @@ p, li { white-space: pre-wrap; } Rehacer - + Object: %1 Objecto: %1 - + Name: %1 Nambre: %1 - + created creado - + removed removido - + modified modificado - + moved movido - + Operation: %1 Operación: %1 - Undoing operations... - Deshacer operaciones... - - - Redoing operations... - Rehacer operaciones... - - - + Operation history exclusion Exclusión del historia de Operación - + Delete the executed operations history is an irreversible action, do you want to continue? Eliminar el historial de operaciones ejecutadas es una acción irreversible, es lo que quieres continuar? OperatorClassWidget - - Form - Formulario - Default Class: @@ -10151,10 +10199,6 @@ p, li { white-space: pre-wrap; } OperatorFamilyWidget - - Form - Formulario - Indexing: @@ -10163,10 +10207,6 @@ p, li { white-space: pre-wrap; } OperatorWidget - - Form - Formulario - MERGES @@ -10235,10 +10275,6 @@ p, li { white-space: pre-wrap; } ParameterWidget - - Form - Formulario - Default Value: @@ -10267,10 +10303,6 @@ p, li { white-space: pre-wrap; } PermissionWidget - - Form - Formulario - @@ -10299,14 +10331,6 @@ p, li { white-space: pre-wrap; } Privileges Privilégios - - Grant - Grant - - - Revoke - Revoke - Edit permissions @@ -10358,446 +10382,417 @@ p, li { white-space: pre-wrap; } Vista previa Código - - Type: - Tipo: - - - - Role - Rol - - - - Id - Id - - - - Leave the <em><strong>Roles</strong></em> empty to create a permission applicable to <strong><em>PUBLIC</em></strong>. - Deje los <em><strong>Roles</strong></em> vacío para crear un permiso aplicable a <strong><em>PUBLIC</em></strong>. - - - - -- No permissions defined for the specified object! - -- No hay permisos definidos para el objeto especificado! - - - - /* Could not generate the SQL code preview for permissions! - / * No se pudo generar el código SQL para previsualización permisos! - - - - PgModelerCLI - - - Unrecognized option '%1'. - Opción no reconocido '%1'. - - - - Value not specified for option '%1'. - El valor no se especifica para la opción '%1'. - - - - Option '%1' does not accept values. - Opción '%1' no acepta valores. - - - - Connection aliased as '%1' was not found on configuration file. - Conexión con alias como '%1' no se ha encontrado en el archivo de configuración. - - - - Usage: pgmodeler-cli [OPTIONS] - El uso: pgmodeler-cli [OPTIONS] - - - - - command line interface. - interfaz de línea de comandos. - - - - PostgreSQL Database Modeler Project - pgmodeler.com.br - Proyecto Modelador Base de datos PostgreSQL - pgmodeler.com.br - - - - Copyright 2006-2015 Raphael A. Silva <raphael@pgmodeler.com.br> - Copyright 2006-2013 Raphael A. Silva <rkhaotix@gmail.com> - - - This CLI tool provides the operations to export pgModeler's database models without -the need to load them on graphical interface as well to fix model files to the most recent -accepted structure. All available options are described below. - Esta herramienta proporciona una manera de exportar pgModeler's modelos de base de datos sin -la necesidad de cargarlos en la interfaz gráfica. Todos los disponibles exportación -modos se describen a continuación. - - - - General options: - Opciones Generales: - - - - %1, %2=[FILE] Input model file (.dbm). Mandatory use when fixing a model or exporting it. - %1, %2=[FILE] Archivo de modelo de entrada (.dbm).Uso obligatorio al fijar un modelo o exportarlo. - - - - %1, %2=[FILE] Output file. Mandatory use when fixing model or export to file or png. - %1, %2=[FILE] Archivo de salida. Disponible sólo en la exportación a un archivo o png. - - - - %1, %2 Try to fix the structure of the input model file in order to make it loadable again. - %1, %2 Trate de fijar la estructura del archivo de modelo de entrada con el fin de hacer que se puede cargar de nuevo. - - - - %1, %2 Model fix tries. When reaching the maximum count the invalid objects will be discard. - %1, %2 Trata fijar Modelo. Al alcanzar el número máximo se descartan los objetos no válidos. - - - - %1, %2 Export to a sql script file. - %1, %2 Exportar a un archivo de secuencia de comandos SQL. - - - - %1, %2 Export to a png image. - %1, %2 Exportar una imagen a png. - - - - %1, %2 Export directly to a PostgreSQL server. - %1, %2 Exportar directamente a un servidor PostgreSQL. - - - - %1, %2 List available connections on %3 file. - %1, %2 Lista de conexiones disponibles en archivo %3. - - - - %1, %2 Version of generated SQL code. Only for file or dbms export. - %1, %2 Versión de código SQL generado. Sólo para archivo o dbms exportación. - - - - %1, %2 Silent execution. Only critical errors are shown during process. - %1, %2 Ejecución silenciosa. Sólo los errores críticos se muestran durante el proceso. - - - - %1, %2 Show this help menu. - %1, %2 Mostrar este menú de ayuda. - - - PNG export options: - opciones de exportación PNG: + + Type: + Tipo: - - %1, %2 Draws the grid on the exported png image. - %1, %2 Dibuja la cuadrícula en la imagen PNG exportado. + + Role + Rol - - %1, %2 Draws the page delimiters on the exported png image. - %1, %2 Dibuja los delimitadores de página en la imagen PNG exportado. + + Id + Id - %1, %2 Each page will be exported on a separated png image. - %1, %2 Cada página se exportará en una imagen png separada. + + Leave the <em><strong>Roles</strong></em> empty to create a permission applicable to <strong><em>PUBLIC</em></strong>. + Deje los <em><strong>Roles</strong></em> vacío para crear un permiso aplicable a <strong><em>PUBLIC</em></strong>. - %1, %2=[FACTOR] Applies a zoom (in percent) before export to png image. Accepted zoom interval: %3-%4 - %1, %2=[FACTOR] Aplica un zoom (en porcentaje) antes de la exportación a la imagen png. Intervalo de zoom aceptado: %3-%4 + + -- No permissions defined for the specified object! + -- No hay permisos definidos para el objeto especificado! - - DBMS export options: - Opciones de exportación del SGDB: + + /* Could not generate the SQL code preview for permissions! + / * No se pudo generar el código SQL para previsualización permisos! + + + PgModelerCLI - - %1, %2 Ignores errors related to duplicated objects that eventually exists on server side. - %1, %2 Ignora los errores relacionados con los objetos duplicados que existe el tiempo en el lado del servidor. + + Unrecognized option '%1'. + Opción no reconocido '%1'. - - %1, %2 Drop the database before execute a export process. - %1, %2 Borar la base de datos antes de ejecutar un proceso de exportación. + + Value not specified for option '%1'. + El valor no se especifica para la opción '%1'. - - %1, %2 Runs the DROP commands attached to SQL-enabled objects. - %1, %2 Ejecuta los comandos DROP unidos a objetos de SQL-habilitado. + + Option '%1' does not accept values. + Opción '%1' no acepta valores. - - %1, %2 Simulates a export process. Actually executes all steps but undoing any modification. - %1, %2 Simula un proceso de exportación. En realidad ejecuta todos los pasos pero deshacer cualquier modificación. + + Connection aliased as '%1' was not found on configuration file. + Conexión con alias como '%1' no se ha encontrado en el archivo de configuración. - - %1, %2 Generates temporary names for database, roles and tablespaces when in simulation mode. - > %1, %2 Genera nombres temporales para bases de datos, funciones y espacios de tabla cuando en el modo de simulación. + + Usage: pgmodeler-cli [OPTIONS] + El uso: pgmodeler-cli [OPTIONS] - - %1, %2=[ALIAS] Connection configuration alias to be used. - %1, %2=[ALIAS] Alias de configuración de conexión a utilizar. + + + command line interface. + interfaz de línea de comandos. - - %1, %2=[HOST] PostgreSQL host which export will operate. - %1, %2=[HOST] Host PostgreSQL cuya exportación funcionará. + + PostgreSQL Database Modeler Project - pgmodeler.com.br + Proyecto Modelador Base de datos PostgreSQL - pgmodeler.com.br - - %1, %2=[PORT] PostgreSQL host listening port. - %1, %2=[PORT] PostgreSQL host puerto de escucha. + + Copyright 2006-2015 Raphael A. Silva <raphael@pgmodeler.com.br> + Copyright 2006-2013 Raphael A. Silva <rkhaotix@gmail.com> - %1, %2=[USER] PosrgreSQL username. - %1, %2=[USER] Nombre de usuario PosrgreSQL. + + This CLI tool provides the operations to export pgModeler's database models without +the need to load them on graphical interface as well to fix model files to the most recent +accepted structure. All available options are described below. + Esta herramienta proporciona una manera de exportar pgModeler's modelos de base de datos sin +la necesidad de cargarlos en la interfaz gráfica. Todos los disponibles exportación +modos se describen a continuación. - %1, %2=[PASSWORD] PosrgreSQL user password. - %1, %2=[PASSWORD] Contraseña de usuario PosrgreSQL. + + General options: + Opciones Generales: - - %1, %2=[DBNAME] Connection's initial database. - %1, %2=[DBNAME] Base de datos inicial de conexión. + + DBMS export options: + Opciones de exportación del SGDB: - + Miscellaneous options: Otros Opciones: - - %1, %2=[ACTION] Handles the file association to .dbm files. The ACTION can be [%3 | %4]. - %1, %2=[ACTION] Maneja la asociación de archivos a .dbm archivos. La acción puede ser [%3 | %4]. - - - + There are no connections configured. No hay conexiones configuradas. - + Available connections (alias : conn. string) Conexiones disponibles (alias:. Conn cadena) - + No export mode specified! No se especifica el modo de exportación! - + Export, fix model and update mime operations can't be used at the same time! Las operaciones de exportación, modelo fijo y actualización mime no se pueden utilizar al mismo tiempo! - Multiple export mode especified! - Modo de exportación múltiple especifidado! - - - + No input file specified! Sin archivo de entrada especificado! - + No output file specified! Sin archivo de salida especificado! - + Input file must be different from output! Archivo de entrada debe ser diferente de la salida! - + Incomplete connection information! Información de conexión incompleto! - + Invalid zoom specified! Inválido Zoom especificado! - + Invalid action specified to update mime option! Acción inválida para actualizar opción mimo! - + Starting model fixing... Iniciar fijación modelo... - + Starting mime update... Iniciar actualización de mime... - + Starting model export... Comenzando del modelo de exportación ... - + Loading input file: Cargando archivo de entrada: - + Fixed model file: Fijando archivo de modelo: - + Model successfully fixed! Modelo fijado correctamente! - Mime database sucessfully updated. - Base de datos de Mime actualizada correctamente. + + PNG and SVG export options: + - - This CLI tool provides the operations to export pgModeler's database models without - the need to load them on graphical interface as well to fix model files to the most recent - accepted structure. All available options are described below. + + %1, %2=[FILE] Input model file (.dbm). Mandatory use when fixing a model or exporting it. + + + + + %1, %2=[FILE] Output file. Mandatory use when fixing model or export to file or png. + + + + + %1, %2 Try to fix the structure of the input model file in order to make it loadable again. - %1, %2 Export to a svg file. + %1, %2 Model fix tries. When reaching the maximum count the invalid objects will be discard. + + + + + %1, %2 Export to a sql script file. + + + + + %1, %2 Export to a png image. + + + + + %1, %2 Export to a svg file. + + + + + %1, %2 Export directly to a PostgreSQL server. + + + + + %1, %2 List available connections on %3 file. + + + + + %1, %2 Version of generated SQL code. Only for file or dbms export. - PNG and SVG export options: + %1, %2 Silent execution. Only critical errors are shown during process. - - %1, %2 Each page will be exported on a separated png image. (Only for PNG) + + %1, %2 Show this help menu. - %1, %2=[FACTOR] Applies a zoom (in percent) before export to png image. Accepted zoom interval: %3-%4 (Only for PNG) + %1, %2 Draws the grid on the exported png image. + + + + + %1, %2 Draws the page delimiters on the exported png image. + + + + + %1, %2 Each page will be exported on a separated png image. (Only for PNG) + + + + + %1, %2=[FACTOR] Applies a zoom (in percent) before export to png image. Accepted zoom interval: %3-%4 (Only for PNG) + + + + + %1, %2 Ignores errors related to duplicated objects that eventually exists on server side. + + + + + %1, %2=[CODES] Ignores additional errors by their codes. A comma-separated list of alphanumeric codes should be provided. + + + + + %1, %2 Drop the database before execute a export process. + + + + + %1, %2 Runs the DROP commands attached to SQL-enabled objects. + + + + + %1, %2 Simulates a export process. Actually executes all steps but undoing any modification. - %1, %2=[USER] PostgreSQL username. + %1, %2 Generates temporary names for database, roles and tablespaces when in simulation mode. - %1, %2=[PASSWORD] PostgreSQL user password. + %1, %2=[ALIAS] Connection configuration alias to be used. + + + + + %1, %2=[HOST] PostgreSQL host which export will operate. + + + + + %1, %2=[PORT] PostgreSQL host listening port. + + + + + %1, %2=[USER] PostgreSQL username. + + + + + %1, %2=[PASSWORD] PostgreSQL user password. - + + %1, %2=[DBNAME] Connection's initial database. + + + + + %1, %2=[ACTION] Handles the file association to .dbm files. The ACTION can be [%3 | %4]. + + + + Multiple export mode specified! - + Mime database successfully updated. - + Export to PNG image: Exportar a imagen PNG: - + Export to SVG file: - + Export to SQL script file: Exportar a archivo de comandos SQL: - + Export to DBMS: Exportar a SGDB: - + Export successfully ended! Exportación terminó correctamente! - + Extracting objects' XML... Exportando objetos XML... - + Invalid input file! It seems that is not a pgModeler generated model or the file is corrupted! Archivo de entrada no es válido! Parece que no es un modelo pgModeler generada o el archivo está dañado! - + Recreating objects... Recreando objetos... - + ** Object(s) that couldn't fixed: ** Objeto(s) que no podían ser fijado: - + WARNING: There are objects that maybe can't be fixed. Trying again... (tries %1/%2) ADVERTENCIA: Hay objetos que tal vez no se pueden arreglar. Tratando de nuevo ... (Trata %1/%2) - + Database model files (.dbm) are already associated to pgModeler! Archivos de modelo de base de datos (.dbm) ya están asociados a pgModeler! - + There is no file association related to pgModeler and .dbm files! No hay ninguna asociación de archivos relacionados con pgModeler y archivos .dbm! - + Mime database operation: %1 Operación Mime de base de datos: %1 - + Can't erase the file %1! Check if the current user has permissions to delete it and if the file exists. No se puede borrar el archivo% 1! Compruebe si el usuario actual tiene permisos para eliminarlo y si existe el archivo. - + Running update-mime-database command... Ejecución de comando update-mime-database... @@ -10823,17 +10818,17 @@ modos se describen a continuación. PgModelerUiNS - + Do you want to apply the <strong>SQL %1 status</strong> to the object's references too? This will avoid problems when exporting or validating the model. ¿Desea aplicar el <strong>SQL %1 estatus</strong> a las referencias del objeto también? Esto evitará problemas al exportar o validar el modelo. - + disabling deshabilitando - + enabling habilitando @@ -10848,7 +10843,7 @@ modos se describen a continuación. Data Type - Tipo de Dado + Tipo de Dato @@ -10929,7 +10924,7 @@ modos se describen a continuación. [ ]: - + NONE NONE @@ -10980,10 +10975,10 @@ modos se describen a continuación. new_database - - - - + + + + %1 (line: %2) %1 (line: %2) @@ -11029,158 +11024,178 @@ modos se describen a continuación. Modo de Conexión - - This mode is available only for <strong>one-to-one</strong>, <strong>one-to-many</strong> and <strong>fk relationships</strong> but provides a better semantics when linking tables by placing the lines on the exact point where the relationship occurs. - Este modo está disponible sólo para <strong>uno-a-uno</strong>, <strong>uno-a-muchos</strong> y <strong>relaciones fk</strong> pero proporciona una mejor semántica al vincular tablas mediante la colocación de las líneas en el punto exacto donde se produce la relación. - - - + Connect FK to PK columns Conecte FK a columnas PK - - This mode is the classical one. It connects the relationship to tables through their central points. - Este modo es el clásico. Se conecta la relación a las tablas a través de sus puntos centrales. + + This mode renders the relationships in crow's foot notation which has a better semantics and readability. It also determines the optimal point where the relationship is connected on the tables' edges taking their position into account. + + + + + Crow's foot notation + + This mode determines the optimal point where the relationship is connected on the tables' edges taking their position into account. It implies the usage of the classical ER notation. + + + + + Connect tables' edges + + + + + This mode is available only for <strong>one-to-one</strong>, <strong>one-to-many</strong> and <strong>fk relationships</strong> but provides a better semantics when linking tables by placing the lines on the exact point where the relationship occurs. It implies the usage of the classical ER notation. + + + + + This mode is the classical one. It connects the relationship to tables through their central points. It implies the usage of the classical ER notation. + + + + Connect tables' center points Conecte tabla a puntos central - + FK Settings && Patterns Configurar FK && Patrones - + Foreign key settings Configurar llave foránea - + Deferral: Diferimiento: - + Deferrable: Diferible: - + ON DELETE: ON DELETE: - + ON UPDATE: ON UPDATE: - + Name patterns Nombre patrones - + Pattern for foreign key generated based upon reference table's pk (1-1 and 1-n) or based upon source table's pk (n-n). Patrón de llave foránea generada basa en pk de las tablas de referencia (1-1 y 1-n) o basada en pk (nn) de las tablas de origen. - + Foreign Key (Source): Llave Foránea (Fuente): - + Relationship type: Tipo de relación: - + Pattern for columns generated based upon target table's pk (n-n). Patrón de columnas generadas basa en pk (nn) de las tablas de destino. - + Column (Target): Columna (Target): - + One to one (1:1) Uno a uno (1:1) - + One to many (1:n) Uno a muchos (1:n) - + Many to many (n:n) muchos a muchos (n:n) - + Generalization Generalización - + Copy Copia - + Pattern for columns generated based upon reference table's pk (1-1 and 1-n) or based upon source table's pk (n-n). Patrón de columnas generadas basa en pk de las tablas de referencia (1-1 y 1-n) o basada en pk (nn) de las tablas de origen. - + Column (Source): Column (Fuente): - + Pattern for foreign key generated based upon target table's pk (n-n). Patrón de llave foránea generada basa en pk (nn) de las tablaa de destino. - + Foreign Key (Target): Lave Foránea (Destino): - + Pattern for unique key generated by the relationship. Patrón de llave única generada por la relación. - + Unique Key Name: Nombre Llave Única: - - + + Pattern for primary key generated by identifier relationship. Patrón para la llave primaria generada por la relación identificador. - + Primary Key Name: Nombre Llave Primaria: - + Primary Key Column: Columna Llave Primaria: - + Default por Defecto @@ -11188,331 +11203,311 @@ modos se describen a continuación. RelationshipWidget - Form - Formulario - - - + General General - + Table 1: Tabla 1: - + Name Patterns Nombre Patrones - - + + Use the values defined on settings dialogs for the fields below Utilice los valores definidos en la configuración de los cuadros de diálogo de los campos siguientes - - + + Use global settings for these fields Utilice la configuración global de estos campos - + Pattern for columns generated based upon reference table's pk (1-1 and 1-n) or based upon source table's pk (n-n). Patrón de columnas generadas basa en pk de las tablas de referencia (1-1 y 1-n) o basada en pk (nn) de las tablas de origen. - + Column (Source): Columna (Fuente): - + Pattern for columns generated based upon target table's pk (n-n). Patrón de columnas generadas basa en pk (nn) de las tablas de destino. - Column (Destino): - Columna (Destino): - - - + Column (Target): Columna (Target): - + Pattern for foreign key generated based upon reference table's pk (1-1 and 1-n) or based upon source table's pk (n-n). Patrón de llave foránea generada basa en pk de las tablas de referencia (1-1 y 1-n) o basada en pk (nn) de las tablas de origen. - + Foreign Key (Source): Llave Foránea (Fuente): - + Pattern for foreign key generated based upon target table's pk (n-n). Patrón de llave foránea generada basa en pk (nn) de tabla de destino. - + Foreign Key (Target): Llave Foránea (Destino): - - + + Pattern for primary key generated by identifier relationship. Patrón para la llave primaria generada por la relación identificador. - + Primary Key Name: Nombre Llave Primaria: - + Pattern for unique key generated by the relationship. Patrón de llave única generada por la relación. - + Unique Key Name: Nombra Llave Única: - + Primay Key Column: Columna Llave Primaria: - + Cardinality: Cardinalidad: - - + + Name of the table generated from many to many relationship Nombre de la tabla generada a partir de relación muchos a muchos - + Gen. Table Name: Nombre tabla Gen.: - + Rel. Type: Tipo Rel.: - + Table 2: Tabla 2: - + [SRC] is required [SRC] es requirido - + [DST] is required [DST] es requirido - + Foreign key Settings Configuración de Llave Foránea - + Deferrable: Diferible: - + Deferral: Diferimiento: - + ON DELETE: - + ON UPDATE: ON DELETE: - + One to one relationship Relación uno a uno - + &1-1 - + &gen - + E&XCLUDING - 1-1 - 1-1 - - - + One to many relationship Relación de uno a muchos - + 1-n 1-n - + Many to many relationship Relación de muchos a muchos - + n-n n-n - + Generalization relationship (inheritance) Relación de generalización (herencia) - gen - gen - - - + Dependency / Copy relationship Relación de Dependencia / Copia - + dep dep - + Relationship generated via foreign key Relación generada a través de clave externa - + fk fk - + The receiver's primary key will be composed by the generated foreign key columns. Clave principal del receptor estará compuesta por las columnas llave foránea generadas. - + Identifier Identificador - + Instead of create a multi-valued primary key with the generated foreign keys columns a single column is created and used as primary key. En lugar de crear una clave principal de varios valores con las teclas extranjero generada columnas se crea una sola columna y se utiliza como clave principal. - + Single PK column Una sola columna PK - + Custom Color: Color personalizado: - + Copy Options Opciones de copia - + INDEXES INDEXES - + COMMENTS COMMENTS - + INCLUDING INCLUDING - + DEFAULTS DEFAULTS - EXCLUDING - EXCLUDING - - - + CONSTRAINTS CONSTRAINTS - + Use defaults Usar valores predeterminados - + ALL ALL - + STORAGE STORAGE - + Attributes Atributos - + Constraints Resticciones - + Primary key Llave Primaria - + Advanced Avanzado @@ -11548,10 +11543,6 @@ modos se describen a continuación. This advanced tab shows the objects (columns or table) auto created by the relationship's connection as well the foreign keys that represents the link between the participant tables. Esta pestaña avanzado muestra los objetos (columnas o tabla) de automóviles creados por la conexión de la relación, así las claves externas que representa el enlace entre las mesas de los participantes. - - Available tokens to define name patterns:<br/> <strong>%1</strong> = Reference (source) primary key column name. <em>(Ignored on constraint patterns)</em><br/> <strong>%2</strong> = Reference (source) table name.<br/> <strong>%3</strong> = Receiver (destination) table name.<br/> <strong>%4</strong> = Generated table name. <em>(Only for n:n relationships)</em> - Fichas disponibles para definir patrones de nombre:<br/> <strong>%1</strong> = Referencia (fuente) nombre de la columna de clave principal. <em>(Ignorado en los patrones de restricción)</em><br/> <strong>%2</strong> = Referencia (fuente) nombre de la tabla.<br/> <strong>%3</strong> = Receptor (destino) nombre de la tabla.<br/> <strong>%4</strong> = Nombre de la tabla generada. <em>(Sólo para relaciones n: n)</em> - Available tokens to define name patterns:<br/> <strong>%1</strong> = Reference (source) primary key column name. <em>(Ignored on constraint patterns)</em><br/> <strong>%2</strong> = Reference (source) table name.<br/> <strong>%3</strong> = Receiver (destination) table name.<br/> <strong>%4</strong> = Generated table name. <em>(Only for n:n relationships)</em> @@ -11563,80 +11554,76 @@ modos se describen a continuación. por Defecto - + Referer View: Vista Intermedia: - + Referer view references one or more columns of a table to construct it's own columns. Vista Intermedia hace referencia a una o más columnas de una tabla de construir es propias columnas. - + Referenced table has its columns referenced by a view in order to construct the columns of this latter. Tabla referenciada tiene sus columnas referenciadas por una vista para construir las columnas de este último. - + Referer Table: Tabla Intermedia: - + Referer table references one or more columns of a table through foreign keys. This is the (n) side of relationship. Tabla intermedia referencia a una o más columnas de una tabla a través de claves externas. Este es el lado (n) de relación. - + Referenced table has its columns referenced by a table's foreign key. This is the (1) side of relationship. Tabla referenciada tiene sus columnas referenciadas por una mesa y apos; s clave externa. Esta es la (1) lado de relación. - + Referenced Table: Tabla Referenciada: - - + + Reference Table: Tabla Referencia: - + Reference table has the columns from its primary key will copied to the receiver table in order to represent the linking between them. This is the (1) side of relationship. Tabla de referencia tiene las columnas de su clave primaria se copian en la tabla del receptor con el fin de representar a la vinculación entre ellos. Esta es la (1) lado de relación. - + Receiver Table: Tabla Receptora: - + Receiver (or referer) table will receive the generated columns and the foreign key in order to represent the linking between them. This is the (n) side of relationship. Receptor tabla (o intermedia) recibirá las columnas generadas y la clave externa con el fin de representar a la vinculación entre ellos. Este es el lado (n) de relación. - + In many-to-many relationships both tables are used as reference to generate the table that represents the linking. Columns from both tables are copied to the resultant table and two foreign keys are created as well in order to reference each participant table. En muchos-a-muchos relación ambas tablas se utilizan como referencia para generar la tabla que representa la vinculación. Las columnas de ambas tablas se copian en la tabla resultante y dos claves externas se crean así con el fin de hacer referencia a cada mesa participante. - - + + is required es requerido RoleWidget - - Form - Formulario - yyyy-MMM-dd hh:mm:ss @@ -11716,12 +11703,6 @@ modos se describen a continuación. Encrypted Encriptada - - Assigning <strong><em>-1</em></strong> to <strong><em>Connections</em></strong> creates a role without connection limit.<br/> Unchecking <strong><em>Validity</em></strong> creates an role that never expires. - Asignación <strong><em>-1</em></strong> pra <strong><em>Conexiones/em></strong> crea un rol sin límite de conexión.<br -> -Desmarcando <strong><em>Validity</em></strong> crea un rol que nunca expire. - Assigning <strong><em>-1</em></strong> to <strong><em>Connections</em></strong> creates a role without connection limit.<br/> Unchecking <strong><em>Validity</em></strong> creates an role that never expires. @@ -11735,10 +11716,6 @@ Desmarcando <strong><em>Validity</em></strong> crea un r RuleWidget - - Form - Formulario - Event: @@ -11783,225 +11760,264 @@ Desmarcando <strong><em>Validity</em></strong> crea un r Formulario - - Load SQL script - Cargar script de comandos SQL + + Save SQL commands + Guardar comandos SQL - - &Load - &Cargar + + Search in SQL code + - - - Save SQL commands - Guardar comandos SQL + + Close the current SQL script + - - &Save - &Guardar + + SQL script currently handled + - - Search in SQL code + + (not saved) + + + + + Handle external SQL script - - &Find - &Buscar + + &Script + - + Alt+F Alt+F - + + Fi&nd + + + + + Ctrl+S + Ctrl+S + + + Run the specified SQL command Ejecutar un comando SQL especificada - + Run SQL Ejecutar SQL - + F6 F6 - + Clear sql input field and results Limpiar campo de entrada de SQL y resultados - + Clear All Limpiar Todos - - + + Export results to a CSV file Exportar resultados a un acchivo CSV - + Snippe&ts Snippe&ts - + E&xport E&xportar - + Toggles the output pane - + &Output - + Alt+O Alt+O - - - - Results + + Current working database - - Messages + + + + Results - - History + + Messages - Shows the command history - Mostrar histórico de comandos - - - &History - &Histórico - - - Alt+H - Alt+H - - - Command History - Histórico de Comandos - - - Clear sql input field and results. - Limpiar campo de entrada sql y los resultados. - - - Clear - Limpiar + + History + - - + + + ... ... - 0 - 0 + + SQL file (*.sql);;All files (*.*) + Archivo SQL (*.sql);;Todos los archivos (*.*) - Rows returned: - Filas retornadas: + + Load + Cargar - - SQL file (*.sql);;All files (*.*) - Archivo SQL (*.sql);;Todos los archivos (*.*) + + Save + - - [binary data] - [datos binarios] + + Save as + Guardar como - [<strong>%1</strong>] SQL command successfully executed. <em>Rows affected <strong>%2</strong></em> - [<strong>%1</strong>] Comando SQL ejecutado con éxito. <em>Filas afectadas <strong>%2</strong></em> + + [binary data] + [datos binarios] - + No results retrieved or changes done due to the error above. - - + + Messages (%1) - + Results (%1) - + [%1]: SQL command successfully executed. <em>%2 <strong>%3</strong></em> - + Rows affected - + Rows retrieved - + Load SQL commands Cargar comandos SQL - + Save CSV file Guardar archivos CSV - + Comma-separated values file (*.csv);;All files (*.*) Archivo de valores separados por comas (*.csv);;Todos los archivos (*.*) - + The SQL input field and the results grid will be cleared! Want to proceed? El campo de entrada de SQL y la cuadrícula de resultados se borrará! ¿Quieres continuar? - + Copy selection Copiar la selección - + + Plain format + + + + + CVS format + + + + + This action will wipe out all the SQL commands history for all connections! Do you really want to proceed? + + + + Clear history + Limpiar historial + + + + Save history + + + + + Reload history + + + + + Find in history + + + + + Hide find tool + + + + + This action will wipe out all the SQL commands history for the current connection! Do you really want to proceed? @@ -12013,110 +12029,125 @@ Desmarcando <strong><em>Validity</em></strong> crea un r Formulario - + Database explorer Explorar Base de Datos - + Disconnect from all databases - + Update the database list - + Toggle the object's attributes grid - + Attributes Atributos - + Alt+R Alt+R - + Toggle the display of source code pane - - + + Source code Código fuente - Connect to server - Conectar al servidor - - - - + + ... ... - Disconnect from server - Desconectar del servidor + + SQL execution + Ejecutar SQL - Browse selected database. - Explorar base de datos seleccionada. + + Warning + Advertencia - Drop the selected database - Borrar base de datos seleccionada + + <strong>ATTENTION:</strong> Disconnect from all databases will close any opened tab in this view! Do you really want to proceed? + + + + SceneInfoWidget - Shift+Del - Shift+Del + + Form + Formulario - Update the database list. - Actualizar listado de base de datos. + + + Current position of the mouse in the canvas + - - SQL execution - Ejecutar SQL + + + + + - + - - - - Warning - Advertencia + + + Currently selected object(s) + - - <strong>ATTENTION:</strong> Disconnect from all databases will close any opened tab in this view! Do you really want to proceed? + + + Dimensions of the selected object(s) - - <strong>CAUTION:</strong> You are about to drop the entire database <strong>%1</strong>! All data will be completely wiped out. Do you really want to proceed? - <strong>ATENCION:</strong> Vas a dejar toda la base de datos <strong>%1</strong>! Todos los datos serán completamente eliminados. ¿Realmente desea continuar? + + + Current zoom factor + - - You're running a demonstration version! The data manipulation feature is available only in the full version! - Usted está ejecutando una versión de demostración! La función de manipulación de datos sólo está disponible en la versión completa! + + No selection + + + + + N/A + + + + + Sel. objects: %1 + SchemaWidget - - Form - Formulario - Fill color: @@ -12130,10 +12161,6 @@ Desmarcando <strong><em>Validity</em></strong> crea un r SequenceWidget - - Form - Formulario - Cyclic: @@ -12334,10 +12361,6 @@ Desmarcando <strong><em>Validity</em></strong> crea un r SourceCodeWidget - - Form - Formulario - Version: @@ -12349,47 +12372,47 @@ Desmarcando <strong><em>Validity</em></strong> crea un r PostgreSQL - + iconecodigo iconecodigo - + SQL SQL - + Code display: Visualización de Código: - + Original Originales - + Original + depedencies' SQL Originales + SQL dependientes - + Original + children's SQL Originales + SQL hijos - + Save the SQL code to a file. Guardar el código SQL code para un archivo. - + Save SQL Guardar SQL - + XML XML @@ -12403,10 +12426,6 @@ Desmarcando <strong><em>Validity</em></strong> crea un r Source code visualization Visualización del código fuente - - <strong>Original:</strong> displays only the original object's SQL code.<br/><br/><strong>Dependencies:</strong> display the original code including all dependencies needed to properly create the selected object.<br/><br/><strong>Children:</strong> display the original code including all children's SQL code. This option is used only by schemas, tables and views. - <strong>Originales:</strong> muestra sólo el código SQL del objeto original.<br/><br/><strong>Dependencias:</strong> muestra el código original, incluyendo todas las dependencias necesarias para crear correctamente el objeto seleccionado. <br/><br/><strong>Hijos:</strong> muestra el código original incluyendo el código SQL de todos los hijos. Esta opción sólo se utiliza por esquemas, tablas y vistas. - <strong>Original:</strong> displays only the original object's SQL code.<br/><br/> <strong>Dependencies:</strong> displays the original code including all dependencies needed to properly create the selected object.<br/><br/> <strong>Children:</strong> displays the original code including all object's children SQL code. This option is used only by schemas, tables and views. @@ -12459,14 +12478,6 @@ Desmarcando <strong><em>Validity</em></strong> crea un r -- SQL code purposely truncated at this point in demo version! - - - --- SQL code purposely truncated at this point on demo version! - - --- Código SQL propósito trunca en este punto en versión demo! - -- SQL code unavailable for this type of object -- @@ -12480,10 +12491,6 @@ Desmarcando <strong><em>Validity</em></strong> crea un r SwapObjectsIdsWidget - - Form - Formulario - Change objects creation order @@ -12496,27 +12503,67 @@ Desmarcando <strong><em>Validity</em></strong> crea un r - + ID: ID: - + Before: Anterior: - - It's recommended to use this feature only when the SQL validation fails in cases when a object is being referenced in portions where the ordinary validation couldn't reach, e.g., inside of a rule command or check constraint expression. - Se recomienda utilizar esta función sólo cuando la validación de SQL falla en los casos cuando un objeto se hace referencia en las partes donde la validación ordinario no podría alcanzar, por ejemplo, en el interior de un comando regla o el chequeo de la expresión de restricción. + + Change the objects creation order is an irreversible operation and cause the operations history to be automatically erased. Note that the creation order configured in this form is not definitive and may change after a model validation. + + + + + Swap the object ids changing their creation order + + + + + Swap ids + + + + + Filter: + + + + + ID + ID + + + + Object + Objecto + + + + Type + Tipo + + + + Parent Object + + + + + Parent Type + Tipo del Padre - + Swap the values of the fields Cambie los valores de los campos - + Swap values Cambie los valores @@ -12524,12 +12571,12 @@ Desmarcando <strong><em>Validity</em></strong> crea un r Table - + new_table nueva_tabla - + In demonstration version tables can have only `%1' instances of each child object type or ancestor tables! You've reach this limit for the type: `%2' En la demostración mesas versión sólo pueden tener `%1' instancias de cada tipo de objeto hijo o antepasado de la tabla! Tienes que llegar a este límite para el tipo: `%2' @@ -12542,154 +12589,120 @@ Desmarcando <strong><em>Validity</em></strong> crea un r - + Add empty rows - - - Add + + Ins + Ins + + + + Fills the grid using a CSV file - - Ins - Ins + + <html><head/><body><p>Empty values are assumed as <span style=" font-weight:600;">DEFAULT</span>. To use special values like <span style=" font-weight:600;">NULL</span>, a function call like <span style=" font-weight:600;">now()</span> or a specific data escaping, enclose values in two slashes, e.g., <span style=" font-weight:600;">/value/</span>. To use a slash as part of the value prepend the backslash character, e.g., <span style=" font-weight:600;">\/</span>.</p></body></html> + - + Some invalid or duplicated columns were detected. In order to solve this issue double-click the header of the highlighted ones in order to define the correct name in which the data belongs to or delete the entire column. Note that these columns are completely igored when generating the <strong>INSERT</strong> commands. - + Add an empty column - + Remove all rows from the grid preserving columns - - - Clear - Limpiar - - - + Shift+Del Shift+Del - + Delete the selected rows - - - Delete - - - - - + + Del Del - - <html><head/><body><p>Empty values are assumed as <span style=" font-weight:600;">DEFAULT</span>. To use special values like <span style=" font-weight:600;">NULL</span>, a function call like <span style=" font-weight:600;">now()</span> or a specific data escaping, enclose values in <span style=" font-weight:600;">{}</span>. To use <span style=" font-weight:600;">{</span> or <span style=" font-weight:600;">}</span> as part of the value prepend the backslash character, e.g., <span style=" font-weight:600;">\{</span> or <span style=" font-weight:600;">\}</span>.</p></body></html> - - - - + Duplicate the selected rows - - Duplicate - - - - + Ctrl+D - + Delete the selected columns - + Remove all columns (and rows) from the grid - + Ctrl+Shift+Del - + Delete columns is an irreversible action! Do you really want to proceed? - + Remove all rows is an irreversible action! Do you really want to proceed? - + Remove all columns is an irreversible action! Do you really want to proceed? - + + Unknown column - + Duplicated column - - - (no columns) - - TableObjectView - + Relationship: %1 Relación: %1 - - TableView - - - Connected rels: %1 - Rels conectados: %1 - - TableWidget - - Form - Formulario - Options @@ -12718,7 +12731,7 @@ Relación: %1 &Columns - + &Columnas @@ -12733,59 +12746,35 @@ Relación: %1 &Rules - + &Reglas &Indexes - + &Indíces &Tables - - - - Columns - Columnas - - - Constraints - Restricciones - - - Triggers - Triggers - - - Rules - Reglas - - - Indexes - Índices - - - Tables - Tablas + &Tablas Edit data - + Editar datos Define initial data for the table - + Definir los datos iniciales de la tabla - - - + - + + + Name Nombre @@ -12796,68 +12785,83 @@ Relación: %1 - - + + Type Tipo - + + PK + + + + Default Value Valor por defecto - - Attribute - Atributos + + Attribute(s) + Atributo(s) + + + + It is not possible to mark a column as primary key when the table already has a primary key which was created by a relationship! This action should be done in the section <strong>Primary key</strong> of the relationship's editing form. + + + + + It is not possible to mark a column created by a relationship as primary key! This action should be done in the section <strong>Primary key</strong> of the relationship's editing form. + - + ON DELETE ON DELETE - + ON UPDATE ON UPDATE - + Refer. Table Tabla Refer - + Firing Firing - + Events Eventos - + Execution Ejecución - + Event Evento - + Indexing Indezado - + Parent Padre - + Copy Copia @@ -12877,10 +12881,6 @@ Relación: %1 TagWidget - - Form - Formulario - Colors @@ -12915,23 +12915,19 @@ Relación: %1 TaskProgressWidget - + Executing tasks Ejecutando tareas - - + + Waiting task to start... Esperando tarea para empezar... TextboxWidget - - Form - Formulario - Font: @@ -12975,10 +12971,6 @@ Relación: %1 TriggerWidget - - Form - Formulario - Constraint @@ -13065,22 +13057,18 @@ Relación: %1 Ejecución: - + Column Columna - + Type Tipo TypeWidget - - Form - Formulario - Range @@ -13223,10 +13211,6 @@ Relación: %1 Co&mposite - - Composite - Compuesto - Enumerations @@ -13297,12 +13281,6 @@ Relación: %1 The functions to be assigned to a type should be written in C language and possess, respectively, the following signatures:<br/> <table> <tr> <td><strong>INPUT:</strong> <em>any function(cstring, oid, integer)</em></td> <td><strong>OUTPUT:</strong> <em>cstring function(any)</em></td> </tr> <tr> <td><strong>SEND:</strong> <em>byta function(any)</em></td> <td><strong>RECV:</strong> <em>any function(internal, oid, integer)</em></td> </tr> <tr> <td><strong>TPMOD_IN:</strong> <em>integer function(cstring[])</em></td> <td><strong>TPMOD_OUT:</strong> <em>cstring function(integer)</em></td> </tr> <tr> <td><strong>ANALYZE:</strong> <em>boolean function(internal)</em></td> <tr> </table> - - The functions to be assigned to a type should be written in C language and possess, respectively, the following signatures:<br/> <table> <tr> <td><strong>INPUT:</strong> <em>any function(cstring, oid, integer)</em></td> <td><strong>OUTPUT:</strong> <em>cstring function(any)</em></td> </tr> <tr> <td><strong>SEND:</strong> <em>byta function(any)</em></td> <td><strong>RECV:</strong> <em>any function(internal, oid, integer)</em></td> </tr> <tr> <td><strong>TPMOD_IN:</strong> <em>integer function(cstring[])</em></td> <td><strong>TPMOD_OUT:</strong> <em>cstring function(integer)</em></td> </tr> <tr> <td><strong>ANALYZE:</strong> <em>boolean f - unction(internal)</em></td> <tr> </table> - Las funciones que se asignará a un tipo deben ser escritos en lenguaje C y poseen, respectivamente, las siguientes firmas:<br/> <table> <tr> <td><strong>INPUT:</strong> <em>any function(cstring, oid, integer)</em></td> <td><strong>OUTPUT:</strong> <em>cstring function(any)</em></td> </tr> <tr> <td><strong>SEND:</strong> <em>byta function(any)</em></td> <td><strong>RECV:</strong> <em>any function(internal, oid, integer)</em></td> </tr> <tr> <td><strong>TPMOD_IN:</strong> <em>integer function(cstring[])</em></td> <td><strong>TPMOD_OUT:</strong> <em>cstring function(integer)</em></td> </tr> <tr> <td><strong>ANALYZE:</strong> <em>bool - ean function(internal)</em></td> <tr> </table> - The functions to be assigned to a range type should have the following signatures:<br/><br/><strong>Canonical:</strong> <em>any function(any)</em> <br/><strong>Subtype Diff:</strong> <em>double precision function(subtype, subtype)</em> @@ -13316,10 +13294,6 @@ Relación: %1 Update Notifier Notificación de Actualizaciones - - New update found! - Nueva actualización encontrado! - Hide this widget @@ -13340,10 +13314,6 @@ Relación: %1 mmm dd, yyyy mmm dd, yyyy - - Version: - Versión: - Update found! @@ -13385,52 +13355,34 @@ Relación: %1 Obtener el código fuente - <strong>Note:</strong> Both actions below will open a new web browser window - <strong>Note:</strong> Ambas acciones continuación se abrirá una nueva ventana del navegador web - - - - Recover a package - Recuperar un paquete - - - - Purchase a new package - Comprar un nuevo paquete - - - - + + Failed to check updates No se ha podido comprobar las actualizaciones - - The update notifier failed to check for new versions! Please, verify your internet connectivity and try again! Connection error returned: <strong>%1</strong>. - El notificador de actualización no pudo comprobar si hay nuevas versiones! Por favor, verifique su conexión a Internet y vuelve a intentarlo! Error de conexión devuelto: <strong>%1</strong>. + + The update notifier failed to check for new versions! Please, verify your internet connectivity and try again! Connection error returned: <em>%1</em> - <strong>%2</strong>. + - + No updates found No se encontraron actualizaciones - + You are running the most recent pgModeler version! No update needed. Está ejecutando la versión más reciente pgModeler! Ninguna actualización necesaria. - + The update notifier failed to check for new versions! A HTTP status code was returned: <strong>%1</strong> El notificador de actualización no pudo comprobar si hay nuevas versiones! Un código de estado HTTP fue devuelto: <strong>%1</strong> ViewWidget - - Form - Formulario - References @@ -13462,12 +13414,12 @@ Relación: %1 Usado en: - + Column Columna - + Expression Expresión @@ -13507,126 +13459,129 @@ Relación: %1 Alias de Columna: - + Triggers Triggers - + Rules Reglas - + + Indexes + Índices + + + Table Expression Expresión de tabla - + Code Preview Vista previa código - + Options Opciones - + Tag: Tag: - + Mode: Modo: - + Ordinary Ordinario - + Recursi&ve - + &Materialized - Recursive - Recursivo - - - Materialized - Materializada - - - + With no data Sin datos - + Col./Expr. Col./Expr. - + Alias Alias - + Alias Col. Alias Col. - + Flags: SF FW AW VD Banderas: SF FW AW VD - - To reference all columns in a table (*) just do not fill the field <strong>Column</strong>, this is the same as write <em><strong>[schema].[tablel].*</strong></em> - Para hacer referencia a todas las columnas de una tabla (*) simplemente no llenar el campo <strong>Column</strong>, este es el mismo que el de escritura <em><strong>[schema].[tablel].*</strong></em> + + To reference all columns in a table (*) just do not fill the field <strong>Column</strong>, this is the same as write <em><strong>[schema].[table].*</strong></em> + - - + + + Name Nombre - + Refer. Table Refer. Tabla - + Firing Firing - + Events Eventos - + + Indexing + Indexación + + + Execution Ejecución - + Event Evento - + /* Could not generate the SQL code. Make sure all attributes are correctly filled! / * No se pudo generar el código SQL. Asegúrese de que todos los atributos se rellenan correctamente! @@ -13651,17 +13606,17 @@ Relación: %1 Sample models - Ejemplo de modoles + Ejemplo de modelos Recent models - Modelos Recientes + Modelos recientes Last session - Última sesión + Última sesión diff --git a/libobjrenderer/src/baseobjectview.cpp b/libobjrenderer/src/baseobjectview.cpp index a3ffe261d..1a21cd06a 100644 --- a/libobjrenderer/src/baseobjectview.cpp +++ b/libobjrenderer/src/baseobjectview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -344,8 +344,8 @@ QLinearGradient BaseObjectView::getFillStyle(const QString &id) { if(id==ParsersAttributes::OBJ_SELECTION || id==ParsersAttributes::PLACEHOLDER) { - colors[0].setAlpha(128); - colors[1].setAlpha(128); + colors[0].setAlpha(OBJ_ALPHA_CHANNEL); + colors[1].setAlpha(OBJ_ALPHA_CHANNEL); } grad.setCoordinateMode(QGradient::ObjectBoundingMode); @@ -369,7 +369,7 @@ QPen BaseObjectView::getBorderStyle(const QString &id) if(!colors.empty()) { if(id==ParsersAttributes::OBJ_SELECTION) - colors[2].setAlpha(128); + colors[2].setAlpha(OBJ_ALPHA_CHANNEL); pen.setWidthF(OBJ_BORDER_WIDTH); pen.setColor(colors[2]); @@ -631,17 +631,19 @@ void BaseObjectView::togglePlaceholder(bool visible) } } -float BaseObjectView::getFontFactor(void) +double BaseObjectView::getFontFactor(void) { return(font_config[ParsersAttributes::GLOBAL].font().pointSizeF()/DEFAULT_FONT_SIZE); } -float BaseObjectView::getScreenDpiFactor(void) +double BaseObjectView::getScreenDpiFactor(void) { - float 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/baseobjectview.h b/libobjrenderer/src/baseobjectview.h index cc201a138..5a7aba761 100644 --- a/libobjrenderer/src/baseobjectview.h +++ b/libobjrenderer/src/baseobjectview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -114,7 +114,9 @@ class BaseObjectView: public QObject, public QGraphicsItemGroup { static constexpr double VERT_SPACING=2.0f, HORIZ_SPACING=2.0f, DEFAULT_FONT_SIZE=9.0f, - OBJ_BORDER_WIDTH=0.80f; + OBJ_BORDER_WIDTH=0.85f; + + static constexpr int OBJ_ALPHA_CHANNEL=128; BaseObjectView(BaseObject *object=nullptr); virtual ~BaseObjectView(void); @@ -176,10 +178,10 @@ class BaseObjectView: public QObject, public QGraphicsItemGroup { /*! \brief Returns the current font DPI factor of the screen. This factor is used to resize * objects according to the screen's resolution/font dpi */ - static float getScreenDpiFactor(void); + static double getScreenDpiFactor(void); //! \brief Returns the current factor between the default font size and the current defined one - static float getFontFactor(void); + static double getFontFactor(void); protected slots: //! \brief Make the basic object operations diff --git a/libobjrenderer/src/basetableview.cpp b/libobjrenderer/src/basetableview.cpp index 4fa5ac7e3..362d3f76f 100644 --- a/libobjrenderer/src/basetableview.cpp +++ b/libobjrenderer/src/basetableview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -74,8 +74,6 @@ BaseTableView::BaseTableView(BaseTable *base_tab) : BaseObjectView(base_tab) this->setAcceptHoverEvents(true); sel_child_obj=nullptr; - connected_rels=0; - configurePlaceholder(); } @@ -159,6 +157,8 @@ void BaseTableView::mousePressEvent(QGraphicsSceneMouseEvent *event) if(!this->isSelected() && event->buttons()==Qt::LeftButton && this->ext_attribs_toggler->boundingRect().contains(pnt)) { + Schema *schema = dynamic_cast(this->getSourceObject()->getSchema()); + //We need to force the object to be not selectable so further calls to mousePressEvent doesn't select the object this->setFlag(QGraphicsItem::ItemIsSelectable, false); @@ -173,6 +173,9 @@ void BaseTableView::mousePressEvent(QGraphicsSceneMouseEvent *event) // Using a single shot time to restore the selectable flag QTimer::singleShot(300, [&]{ this->setFlag(QGraphicsItem::ItemIsSelectable, true); }); + //Updating the schema box that holds the object (if visible) + schema->setModified(true); + emit s_extAttributesToggled(); } @@ -260,10 +263,48 @@ void BaseTableView::hoverMoveEvent(QGraphicsSceneHoverEvent *event) } } -void BaseTableView::updateConnectedRelsCount(int inc) +void BaseTableView::addConnectedRelationship(BaseRelationship *base_rel) +{ + BaseTable *tab = dynamic_cast(getSourceObject()); + + if(!base_rel || + (base_rel && + base_rel->getTable(BaseRelationship::SRC_TABLE) != tab && + base_rel->getTable(BaseRelationship::DST_TABLE) != tab)) + return; + + connected_rels.push_back(base_rel); +} + +void BaseTableView::removeConnectedRelationship(BaseRelationship *base_rel) +{ + connected_rels.erase(std::find(connected_rels.begin(), connected_rels.end(), base_rel)); +} + +int BaseTableView::getConnectedRelationshipIndex(BaseRelationship *base_rel) +{ + vector::iterator itr = std::find(connected_rels.begin(), connected_rels.end(), base_rel); + + if(itr != connected_rels.end()) + return(itr - connected_rels.begin()); + + return(-1); +} + +unsigned BaseTableView::getConnectedRelsCount(BaseTable *src_tab, BaseTable *dst_tab) { - connected_rels+=inc; - if(connected_rels < 0) connected_rels=0; + unsigned count = 0; + + for(auto &rel : connected_rels) + { + if((rel->getTable(BaseRelationship::SRC_TABLE) == src_tab && + rel->getTable(BaseRelationship::DST_TABLE) == dst_tab) || + (rel->getTable(BaseRelationship::SRC_TABLE) == dst_tab && + rel->getTable(BaseRelationship::DST_TABLE) == src_tab)) + count++; + } + + return(count); } void BaseTableView::configureTag(void) @@ -315,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()) { @@ -342,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)); @@ -427,7 +469,7 @@ float BaseTableView::calculateWidth(void) int BaseTableView::getConnectRelsCount(void) { - return(connected_rels); + return(connected_rels.size()); } void BaseTableView::requestRelationshipsUpdate(void) @@ -437,6 +479,6 @@ void BaseTableView::requestRelationshipsUpdate(void) void BaseTableView::togglePlaceholder(bool value) { - BaseObjectView::togglePlaceholder(connected_rels > 0 && value); + BaseObjectView::togglePlaceholder(!connected_rels.empty() && value); } diff --git a/libobjrenderer/src/basetableview.h b/libobjrenderer/src/basetableview.h index 261f2e108..67b6b75f0 100644 --- a/libobjrenderer/src/basetableview.h +++ b/libobjrenderer/src/basetableview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -30,14 +30,14 @@ #include "tabletitleview.h" #include "tableobjectview.h" #include "roundedrectitem.h" +#include "baserelationship.h" class BaseTableView: public BaseObjectView { private: Q_OBJECT - /*! \brief Stores the number of relationships connected to this table. This attribute is used - by the rearrange method on ModelWidget */ - int connected_rels; + /*! \brief Stores the references to the relationships connected to this table. */ + vector connected_rels; protected: //! \brief Item groups that stores columns and extended attributes, respectively @@ -71,8 +71,11 @@ class BaseTableView: public BaseObjectView { QVariant itemChange(GraphicsItemChange change, const QVariant &value); - //! \brief Updates the current connected relationship count - void updateConnectedRelsCount(int inc); + void addConnectedRelationship(BaseRelationship *base_rel); + + void removeConnectedRelationship(BaseRelationship *base_rel); + + int getConnectedRelationshipIndex(BaseRelationship *base_rel); //! \brief Configures the tag object when the source object has one. void configureTag(void); @@ -116,6 +119,8 @@ class BaseTableView: public BaseObjectView { //! \brief Toggles the placeholder object when there is at least one relationship connected to the object virtual void togglePlaceholder(bool value); + unsigned getConnectedRelsCount(BaseTable *src_tab, BaseTable *dst_tab); + signals: //! \brief Signal emitted when a table is moved over the scene void s_objectMoved(void); diff --git a/libobjrenderer/src/beziercurveitem.cpp b/libobjrenderer/src/beziercurveitem.cpp index 34b7efd0e..d18f64662 100644 --- a/libobjrenderer/src/beziercurveitem.cpp +++ b/libobjrenderer/src/beziercurveitem.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -21,7 +21,7 @@ BezierCurveItem::BezierCurveItem(QGraphicsItem *parent) : QGraphicsPathItem(parent) { - simple_curve = false; + invert_cpoints = simple_curve = straight_line = false; } void BezierCurveItem::setPath(const QPainterPath &path) @@ -31,61 +31,83 @@ void BezierCurveItem::setPath(const QPainterPath &path) stroke = ps.createStroke(path); } -void BezierCurveItem::setLine(const QLineF &line, bool simple_curve, unsigned rel_type) +void BezierCurveItem::setLine(const QLineF &line, bool simple_curve, bool invert_cpoints) { QPainterPath path; - QRectF brect; - QPointF control_pnt; + this->straight_line = false; + this->invert_cpoints = invert_cpoints; this->simple_curve = simple_curve; - if(simple_curve) + if(line.dx() == 0 || line.dy() == 0) { - if(rel_type == BaseRelationship::RELATIONSHIP_FK) + path = QPainterPath(line.p1()); + path.lineTo(line.p2()); + this->straight_line = true; + } + else + { + if(simple_curve) { - brect.setTopLeft(line.p1()); - brect.setBottomRight(line.p2()); - control_pnt = QPointF(brect.right(), brect.top()); + QPointF cp1, start, end; + + start = line.p1(); + end = line.p2(); + + if(!invert_cpoints) + cp1 = QPointF(start.x(), end.y()); + else + cp1 = QPointF(end.x(), start.y()); + + path = QPainterPath(start); + path.quadTo(cp1, end); } else { - if(line.angle() >= 0 && line.angle() <= 180) + QRectF brect; + + if(!invert_cpoints) { brect.setTopLeft(line.p1()); brect.setBottomRight(line.p2()); - control_pnt = QPointF(brect.left(), brect.bottom()); + path = QPainterPath(brect.topLeft()); + + path.cubicTo(QPointF(brect.center().x(), brect.top()), + QPointF(brect.center().x(), brect.bottom()), + brect.bottomRight()); } else { - brect.setTopLeft(line.p2()); - brect.setBottomRight(line.p1()); - control_pnt = QPointF(brect.right(), brect.top()); + brect.setBottomLeft(line.p1()); + brect.setTopRight(line.p2()); + path = QPainterPath(brect.topRight()); + + path.cubicTo(QPointF(brect.right(), brect.center().y()), + QPointF(brect.left(), brect.center().y()), + brect.bottomLeft()); + } } } - else - { - brect.setTopLeft(line.p1()); - brect.setBottomRight(line.p2()); - } - - path = QPainterPath(brect.topLeft()); - - if(simple_curve) - path.quadTo(control_pnt, brect.bottomRight()); - else - path.cubicTo(QPointF(brect.center().x(), brect.top()), - QPointF(brect.center().x(), brect.bottom()), - brect.bottomRight()); this->setPath(path); } +bool BezierCurveItem::isControlPointsInverted(void) +{ + return(invert_cpoints); +} + bool BezierCurveItem::isSimpleCurve(void) { return(simple_curve); } +bool BezierCurveItem::isStraightLine(void) +{ + return(straight_line); +} + bool BezierCurveItem::contains(const QPointF &pnt) const { return(stroke.contains(pnt)); diff --git a/libobjrenderer/src/beziercurveitem.h b/libobjrenderer/src/beziercurveitem.h index 95601908c..7f8da09c6 100644 --- a/libobjrenderer/src/beziercurveitem.h +++ b/libobjrenderer/src/beziercurveitem.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -33,24 +33,37 @@ class BezierCurveItem: public QGraphicsPathItem { * This object is used to do a better colision detection */ QPainterPath stroke; - /*! \brief Indicate if the curve is a simple one. - * Simple curves in this case are quadratic ones where only a single - * control point is used. Non-simple curves are cubic where two control points are used. - * See QPainterPath::quadTo and QPainterPath::cubicTo for details. */ + bool invert_cpoints; + bool simple_curve; + bool straight_line; + protected: void setPath(const QPainterPath &path); public: BezierCurveItem(QGraphicsItem *parent = 0); - //! \brief Configures the curve based upon a straight line. - void setLine(const QLineF &line, bool simple_curve, unsigned rel_type); + /*! \brief Configures the curve based upon a straight line. + * + * The simple_curve param causes the curve to be drawn using the quadratic mode and one control point. + * Non-simple curves are cubic ones where two control points are used. + * See QPainterPath::quadTo and QPainterPath::cubicTo for details. + * + * The invert_cpoints param causes the control points of the curve to be inverted + * making the curve to be drawn inverted. */ + void setLine(const QLineF &line, bool simple_curve, bool invert_cpoints); - //! \brief Returns if the curve is a simple one (quardatic - one control point) or not (cubic - two control points) + //! \brief Returns if the curve has the control points inverted + bool isControlPointsInverted(void); + + //! \brief Returns if the curve is a simple one (with only one control point) bool isSimpleCurve(void); + //! \brief Returns if the curve object was created from a straight line (90 or 180 degrees) + bool isStraightLine(void); + //! \brief Returns if the specified point is contained by the curve (specifically, by the stroke) virtual bool contains(const QPointF &pnt) const; diff --git a/libobjrenderer/src/graphicalview.cpp b/libobjrenderer/src/graphicalview.cpp index 12b832ac1..d1dccd584 100644 --- a/libobjrenderer/src/graphicalview.cpp +++ b/libobjrenderer/src/graphicalview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/graphicalview.h b/libobjrenderer/src/graphicalview.h index 5c1f962c9..74f559582 100644 --- a/libobjrenderer/src/graphicalview.h +++ b/libobjrenderer/src/graphicalview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/objectsscene.cpp b/libobjrenderer/src/objectsscene.cpp index 71d67e9fc..64bb7337a 100644 --- a/libobjrenderer/src/objectsscene.cpp +++ b/libobjrenderer/src/objectsscene.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -477,10 +477,21 @@ void ObjectsScene::removeItem(QGraphicsItem *item) } } +void ObjectsScene::blockItemsSignals(bool block) +{ + BaseObjectView *obj_view = nullptr; + + for(auto &item : this->items()) + { + obj_view = dynamic_cast(item); + if(obj_view) + obj_view->blockSignals(block); + } +} + void ObjectsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseDoubleClickEvent(event); - //enablePannigMode(false); if(this->selectedItems().size()==1 && event->buttons()==Qt::LeftButton && !rel_line->isVisible()) { @@ -499,6 +510,7 @@ void ObjectsScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { //Gets the item at mouse position QGraphicsItem* item=this->itemAt(event->scenePos().x(), event->scenePos().y(), QTransform()); + bool is_deselection = !this->selectedItems().isEmpty() && !this->itemAt(event->scenePos(), QTransform()); if(selectedItems().empty()) emit s_objectsScenePressed(event->buttons()); @@ -510,8 +522,17 @@ void ObjectsScene::mousePressEvent(QGraphicsSceneMouseEvent *event) if(rel_line->isVisible()) event->setModifiers(Qt::ControlModifier); + if(is_deselection) + this->blockItemsSignals(true); + QGraphicsScene::mousePressEvent(event); + if(is_deselection) + { + this->blockItemsSignals(false); + emit s_objectSelected(nullptr, false); + } + if(event->buttons()==Qt::LeftButton) { sel_ini_pnt=event->scenePos(); @@ -834,12 +855,18 @@ void ObjectsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QPainterPath sel_area; sel_area.addRect(selection_rect->polygon().boundingRect()); + + this->blockItemsSignals(true); this->setSelectionArea(sel_area, Qt::IntersectsItemShape); + this->blockItemsSignals(false); selection_rect->setVisible(false); selection_rect->setPolygon(pol); sel_ini_pnt.setX(NAN); sel_ini_pnt.setY(NAN); + + if(!this->selectedItems().isEmpty()) + emit s_objectsSelectedInRange(); } } @@ -853,11 +880,12 @@ void ObjectsScene::finishObjectsMove(const QPointF &pnt_end) vector points; vector::iterator itr; vector rels, base_rels; + QSet schemas; BaseRelationship *base_rel=nullptr; RelationshipView *rel=nullptr; BaseObjectView *obj_view=nullptr; BaseTableView *tab_view=nullptr; - QList tables; + QSet tables; //Gathering the relationships inside the selected schemsa in order to move their points too for(auto &item : items) @@ -870,7 +898,7 @@ void ObjectsScene::finishObjectsMove(const QPointF &pnt_end) obj_view->togglePlaceholder(false); if(tab_view) - tables.push_back(tab_view); + tables.insert(tab_view); else if(sch_view) { //Get the schema object @@ -894,7 +922,7 @@ void ObjectsScene::finishObjectsMove(const QPointF &pnt_end) rel_list.push_back(dynamic_cast(base_rel->getReceiverObject())); } - tables.append(sch_view->getChildren()); + tables.unite(sch_view->getChildren().toSet()); } } } @@ -980,18 +1008,25 @@ void ObjectsScene::finishObjectsMove(const QPointF &pnt_end) this->setSceneRect(rect); } - if(BaseObjectView::isPlaceholderEnabled()) + for(auto &obj : tables) { - /* Updating relationships related to moved tables. Converting the list of table to a set - in order to remove the duplicated elements */ - for(auto &obj : tables.toSet()) + tab_view=dynamic_cast(obj); + + //Realign tables if the parent schema had the position adjusted too + if(align_objs_grid) { - tab_view=dynamic_cast(obj); - if(tab_view) - tab_view->requestRelationshipsUpdate(); + tab_view->setPos(alignPointToGrid(tab_view->pos())); + schemas.insert(dynamic_cast(tab_view->getSourceObject()->getSchema())); } + + if(BaseObjectView::isPlaceholderEnabled()) + tab_view->requestRelationshipsUpdate(); } + //Updating schemas bounding rects after moving objects + for(auto &obj : schemas) + obj->setModified(true); + emit s_objectsMoved(true); moving_objs=false; sel_ini_pnt.setX(NAN); diff --git a/libobjrenderer/src/objectsscene.h b/libobjrenderer/src/objectsscene.h index 8cfda9fa7..ff080597e 100644 --- a/libobjrenderer/src/objectsscene.h +++ b/libobjrenderer/src/objectsscene.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -136,6 +136,8 @@ class ObjectsScene: public QGraphicsScene { //! \brief Draws a line from the point 'p_start' to the cursor position and simulates the relationship creation void showRelationshipLine(bool value, const QPointF &p_start=QPointF(NAN,NAN)); + void blockItemsSignals(bool block); + public: ObjectsScene(void); ~ObjectsScene(void); @@ -225,6 +227,9 @@ class ObjectsScene: public QGraphicsScene { //! \brief Signal emitted when a object is selected void s_objectSelected(BaseGraphicObject *objeto, bool selecionado); + //! \brief Signal emitted when objects are selected via range selection + void s_objectsSelectedInRange(void); + //! \brief Signal emtted when a blank area of the canvas is pressed void s_objectsScenePressed(Qt::MouseButtons); diff --git a/libobjrenderer/src/relationshipview.cpp b/libobjrenderer/src/relationshipview.cpp index 8e01c50f2..56f02bc64 100644 --- a/libobjrenderer/src/relationshipview.cpp +++ b/libobjrenderer/src/relationshipview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -20,6 +20,7 @@ bool RelationshipView::hide_name_label=false; bool RelationshipView::use_curved_lines=true; +bool RelationshipView::use_crows_foot=false; unsigned RelationshipView::line_conn_mode=RelationshipView::CONNECT_FK_TO_PK; RelationshipView::RelationshipView(BaseRelationship *rel) : BaseObjectView(rel) @@ -28,12 +29,12 @@ RelationshipView::RelationshipView(BaseRelationship *rel) : BaseObjectView(rel) throw Exception(ERR_ASG_NOT_ALOC_OBJECT, __PRETTY_FUNCTION__, __FILE__, __LINE__); for(unsigned i=BaseRelationship::SRC_CARD_LABEL; - i <= BaseRelationship::REL_NAME_LABEL; i++) + i <= BaseRelationship::REL_NAME_LABEL; i++) { if(rel->getLabel(i)) { labels[i]=new TextboxView(rel->getLabel(i), true); - labels[i]->setZValue(i==BaseRelationship::REL_NAME_LABEL ? 0 : 1); + labels[i]->setZValue(i==BaseRelationship::REL_NAME_LABEL ? 1 : 2); this->addToGroup(labels[i]); } else @@ -62,6 +63,9 @@ RelationshipView::RelationshipView(BaseRelationship *rel) : BaseObjectView(rel) for(unsigned i=0; i < 2; i++) { + round_cf_descriptors[i] = nullptr; + cf_descriptors[i] = nullptr; + line_circles[i]=new QGraphicsEllipseItem; line_circles[i]->setRect(QRectF(0,0,GRAPHIC_PNT_RADIUS,GRAPHIC_PNT_RADIUS)); line_circles[i]->setZValue(0); @@ -77,6 +81,7 @@ RelationshipView::RelationshipView(BaseRelationship *rel) : BaseObjectView(rel) RelationshipView::~RelationshipView(void) { QGraphicsItem *item=nullptr; + vector *> rel_lines = { &lines, &fk_lines, &pk_lines, &src_cf_lines, &dst_cf_lines }; while(!curves.empty()) { @@ -101,40 +106,43 @@ RelationshipView::~RelationshipView(void) } } - while(!lines.empty()) + while(!attributes.empty()) { - item=lines.back(); + item=attributes.back(); this->removeFromGroup(item); - lines.pop_back(); + attributes.pop_back(); delete(item); } - while(!fk_lines.empty()) + for(auto &lines : rel_lines) { - item=fk_lines.back(); - this->removeFromGroup(item); - fk_lines.pop_back(); - delete(item); + while(!lines->empty()) + { + item = lines->back(); + this->removeFromGroup(item); + lines->pop_back(); + delete(item); + } } - while(!pk_lines.empty()) - { - item=pk_lines.back(); - this->removeFromGroup(item); - pk_lines.pop_back(); - delete(item); - } + this->removeFromGroup(descriptor); + delete(descriptor); - while(!attributes.empty()) + for(int i =0; i < 2; i++) { - item=attributes.back(); - this->removeFromGroup(item); - attributes.pop_back(); - delete(item); - } + if(cf_descriptors[i]) + { + for(auto &item : cf_descriptors[i]->childItems()) + { + cf_descriptors[i]->removeFromGroup(item); + this->removeFromGroup(item); + delete(item); + } - this->removeFromGroup(descriptor); - delete(descriptor); + this->removeFromGroup(cf_descriptors[i]); + delete(cf_descriptors[i]); + } + } } void RelationshipView::setHideNameLabel(bool value) @@ -157,12 +165,30 @@ bool RelationshipView::isCurvedLines(void) return(use_curved_lines); } +void RelationshipView::setCrowsFoot(bool value) +{ + use_crows_foot = value; + + if(value) + line_conn_mode=RelationshipView::CONNECT_TABLE_EGDES; +} + +bool RelationshipView::isCrowsFoot(void) +{ + return(use_crows_foot); +} + void RelationshipView::setLineConnectionMode(unsigned mode) { - if(mode > CONNECT_FK_TO_PK) - mode=CONNECT_FK_TO_PK; + if(use_crows_foot) + line_conn_mode=CONNECT_TABLE_EGDES; + else + { + if(mode > CONNECT_TABLE_EGDES) + mode=CONNECT_TABLE_EGDES; - line_conn_mode=mode; + line_conn_mode=mode; + } } unsigned RelationshipView::getLineConnectinMode(void) @@ -207,7 +233,7 @@ QVariant RelationshipView::itemChange(GraphicsItemChange change, const QVariant this->setSelectionOrder(value.toBool()); pos_info_rect->setVisible(value.toBool()); pos_info_txt->setVisible(value.toBool()); - obj_selection->setVisible(value.toBool()); + obj_selection->setVisible(value.toBool() && descriptor->isVisible()); this->configurePositionInfo(); for(i=0; i < 3; i++) @@ -238,6 +264,7 @@ QVariant RelationshipView::itemChange(GraphicsItemChange change, const QVariant else color=line_color; + color.setAlpha(255); rel_lines=lines; rel_lines.insert(rel_lines.end(), fk_lines.begin(), fk_lines.end()); rel_lines.insert(rel_lines.end(), pk_lines.begin(), pk_lines.end()); @@ -256,6 +283,51 @@ QVariant RelationshipView::itemChange(GraphicsItemChange change, const QVariant curve->setPen(pen); } + //If the crow's foot descriptors are allocated we change their border color + if(cf_descriptors[0] != nullptr) + { + vector lines; + QVector grad_stops = descriptor->brush().gradient()->stops(); + QColor sel_color = BaseObjectView::getBorderStyle(ParsersAttributes::OBJ_SELECTION).color(); + QLinearGradient grad(QPointF(0,0),QPointF(0,1)); + int color_id = 0; + + grad.setCoordinateMode(QGradient::ObjectBoundingMode); + lines.assign(src_cf_lines.begin(), src_cf_lines.end()); + lines.insert(lines.end(), dst_cf_lines.begin(), dst_cf_lines.end()); + + for(auto &line : lines) + line->setPen(pen); + + for(int idx = 0; idx < 2; idx++) + { + /* If we have a circle that describes optional cardinality we should + * merge its color with the object selection color in order to simulate the + * that the descriptor is selected as well */ + if(value.toBool()) + { + color_id = 0; + for(auto &stop : grad_stops) + { + color = stop.second; + color.setRedF((color.redF() + sel_color.greenF())/2.0f); + color.setGreenF((color.greenF() + sel_color.greenF())/2.0f); + color.setBlueF((color.blueF() + sel_color.blueF())/2.0f); + grad.setColorAt(color_id++, color); + } + + round_cf_descriptors[idx]->setBrush(grad); + } + else + round_cf_descriptors[idx]->setBrush(descriptor->brush()); + + if(this->getSourceObject()->getRelationshipType() == BaseRelationship::RELATIONSHIP_FK) + pen.setStyle(Qt::DashLine); + + round_cf_descriptors[idx]->setPen(pen); + } + } + //Shows/hides the attribute's selection count=attributes.size(); for(i=0; i < count; i++) @@ -279,7 +351,7 @@ void RelationshipView::mousePressEvent(QGraphicsSceneMouseEvent *event) BaseRelationship *base_rel=this->getSourceObject(); //Resets the labels position when mid-button is pressed - if(event->buttons()==Qt::LeftButton && event->modifiers()==(Qt::AltModifier | Qt::ControlModifier)) + if(event->buttons()==Qt::LeftButton && event->modifiers()==(Qt::AltModifier | Qt::ShiftModifier)) { base_rel->resetLabelsDistance(); this->configureLabels(); @@ -393,12 +465,21 @@ void RelationshipView::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if(dynamic_cast(sel_object)) { - BaseRelationship *rel_base=this->getSourceObject(); - vector points=rel_base->getPoints(); + QRectF brect = QRectF(tables[0]->pos() - QPointF(20,20), + tables[0]->pos() + QPointF(tables[0]->boundingRect().width() + 20, tables[0]->boundingRect().height() + 20)), + brect1 = QRectF(tables[1]->pos() - QPointF(20,20), + tables[1]->pos() + QPointF(tables[1]->boundingRect().width() + 20, tables[1]->boundingRect().height() + 20)); - points[sel_object_idx]=event->pos(); - rel_base->setPoints(points); - this->configureLine(); + //We only include the point if it is not inside the tables' bounding rect + if(!brect.contains(event->pos()) && !brect1.contains(event->pos())) + { + BaseRelationship *rel_base=this->getSourceObject(); + vector points=rel_base->getPoints(); + + points[sel_object_idx]=event->pos(); + rel_base->setPoints(points); + this->configureLine(); + } } else if(dynamic_cast(sel_object)) sel_object->setPos(event->pos()); @@ -417,7 +498,7 @@ void RelationshipView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { //Calculates the displacement of the label from the initial pos to the current base_rel->setLabelDistance(sel_object_idx, - QPointF(sel_object->pos() - labels_ini_pos[sel_object_idx])); + QPointF(sel_object->pos() - labels_ini_pos[sel_object_idx])); } sel_object_idx=-1; @@ -432,10 +513,11 @@ void RelationshipView::disconnectTables(void) if(tables[0] && tables[1]) { BaseRelationship *rel_base=this->getSourceObject(); - tables[0]->updateConnectedRelsCount(-1); + + tables[0]->removeConnectedRelationship(rel_base); if(!rel_base->isSelfRelationship()) - tables[1]->updateConnectedRelsCount(-1); + tables[1]->removeConnectedRelationship(rel_base); for(unsigned i=0; i < 2; i++) { @@ -470,10 +552,10 @@ void RelationshipView::configureObject(void) tables[0]=dynamic_cast(rel_base->getTable(BaseRelationship::SRC_TABLE)->getReceiverObject()); tables[1]=dynamic_cast(rel_base->getTable(BaseRelationship::DST_TABLE)->getReceiverObject()); - tables[0]->updateConnectedRelsCount(1); + tables[0]->addConnectedRelationship(rel_base); if(!rel_base->isSelfRelationship()) - tables[1]->updateConnectedRelsCount(1); + tables[1]->addConnectedRelationship(rel_base); configureLine(); connectTables(); @@ -488,7 +570,7 @@ void RelationshipView::configurePositionInfo(void) pos_info_txt->setPos(descriptor->pos().x(), descriptor->pos().y() - pos_info_txt->boundingRect().height()); pos_info_rect->setPos(descriptor->pos().x(), - descriptor->pos().y() - pos_info_rect->boundingRect().height()); + descriptor->pos().y() - pos_info_rect->boundingRect().height()); } } @@ -515,14 +597,19 @@ void RelationshipView::configureLine(void) QString tool_tip; QGraphicsItem *item=nullptr; int i, i1, count, idx_lin_desc=0; - bool conn_same_sides = false, bidirectional=base_rel->isBidirectional(); + bool conn_same_sides = false, + conn_horiz_sides[2] = { false, false }, conn_vert_sides[2] = { false, false }; + unsigned rel_type = base_rel->getRelationshipType(); configuring_line=true; pen.setCapStyle(Qt::RoundCap); if(base_rel->isSelfRelationship()) { - double fator=font_config[ParsersAttributes::GLOBAL].font().pointSizeF()/DEFAULT_FONT_SIZE; + double fnt_factor=font_config[ParsersAttributes::GLOBAL].font().pointSizeF()/DEFAULT_FONT_SIZE, + pos_factor = 0, offset = 0; + unsigned rel_cnt = tables[0]->getConnectedRelsCount(base_rel->getTable(BaseRelationship::SRC_TABLE), + base_rel->getTable(BaseRelationship::DST_TABLE)); /* Sefl-relationshihp line format: @@ -536,24 +623,40 @@ void RelationshipView::configureLine(void) pos=tables[0]->pos(); rect=tables[0]->boundingRect(); - p_central[0].setX(pos.x() + rect.width()); - p_central[0].setY(pos.y() + (rect.height()/2.5f)); + if(rel_cnt > 1) + { + int idx = tables[0]->getConnectedRelationshipIndex(base_rel); + double min_val = min(rect.width(), rect.height()); + + if(idx < 0) idx =0; + pos_factor = min_val * 0.08f * idx; + } - p_central[1].setX(pos.x() + (rect.width()/1.5f)); + p_central[0].setX(pos.x() + rect.width()); + p_central[0].setY(pos.y() + (rect.height() / 3.0f) + pos_factor); + p_central[1].setX(pos.x() + (rect.width() / 1.5f) - pos_factor); p_central[1].setY(pos.y()); - points.push_back(QPointF(p_central[0].x() + (11 * fator), p_central[0].y())); - points.push_back(QPointF(p_central[0].x() + (11 * fator), p_central[1].y() - (11 * fator))); - points.push_back(QPointF(p_central[1].x(), p_central[1].y() - (11 * fator))); + if(p_central[0].y() > pos.y() + rect.height()) + p_central[0].setY(pos.y() + rect.height()); + + if(p_central[1].x() < pos.x()) + p_central[1].setX(pos.x()); + + offset = use_crows_foot ? 23 : 11; + + points.push_back(QPointF(p_central[0].x() + (offset * fnt_factor) + pos_factor, p_central[0].y())); + points.push_back(QPointF(p_central[0].x() + (offset * fnt_factor) + pos_factor, p_central[1].y() - (offset * fnt_factor) - pos_factor)); + points.push_back(QPointF(p_central[1].x(), p_central[1].y() - (offset * fnt_factor) - pos_factor)); + base_rel->setPoints(points); } else { Relationship *rel=dynamic_cast(base_rel); - bool rel_1n=(!bidirectional && - (base_rel->getRelationshipType()==Relationship::RELATIONSHIP_11 || - base_rel->getRelationshipType()==Relationship::RELATIONSHIP_1N || - base_rel->getRelationshipType()==Relationship::RELATIONSHIP_FK)); + bool rel_1n= (rel_type==Relationship::RELATIONSHIP_11 || + rel_type==Relationship::RELATIONSHIP_1N || + rel_type==Relationship::RELATIONSHIP_FK); if(rel && rel->getRelationshipType()==Relationship::RELATIONSHIP_11 && @@ -563,7 +666,7 @@ void RelationshipView::configureLine(void) tables[1]=dynamic_cast(rel->getReceiverTable()->getReceiverObject()); } - if(line_conn_mode==CONNECT_CENTER_PNTS || !rel_1n) + if(line_conn_mode==CONNECT_CENTER_PNTS || line_conn_mode==CONNECT_TABLE_EGDES || !rel_1n) { vector *> ref_lines={ &fk_lines, &pk_lines }; @@ -612,7 +715,7 @@ void RelationshipView::configureLine(void) //In this case the receiver table rect Y must be equal to reference table Y in order to do the correct comparison rec_tab_rect=QRectF(QPointF(rec_tab_view->pos().x(), - ref_tab_view->pos().y()), rec_tab_view->boundingRect().size()); + ref_tab_view->pos().y()), rec_tab_view->boundingRect().size()); if(ref_tab_rect.intersects(rec_tab_rect)) { @@ -665,7 +768,7 @@ void RelationshipView::configureLine(void) pk_pnt=this->mapFromItem(ref_tab_view, QPointF(pk_px + pk_dx, pk_py/pk_points.size())); fk_pnt=this->mapFromItem(rec_tab_view, QPointF(fk_px + fk_dx, fk_py/fk_points.size())); - if(base_rel->getRelationshipType()==Relationship::RELATIONSHIP_FK) + if(rel_type==Relationship::RELATIONSHIP_FK) { p_central[1]=pk_pnt; p_central[0]=fk_pnt; @@ -683,7 +786,7 @@ void RelationshipView::configureLine(void) * This situation may happen when the relationship is being validated and the needed fks was not * created yet. In a second interaction of the rel. validation they are created * and the relationship is properly configured */ - if(base_rel->getRelationshipType()==Relationship::RELATIONSHIP_FK) + if(rel_type==Relationship::RELATIONSHIP_FK) { p_central[1]=pk_pnt=ref_tab_view->getCenter(); p_central[0]=fk_pnt=rec_tab_view->getCenter(); @@ -733,8 +836,162 @@ void RelationshipView::configureLine(void) } } - conn_points[0]=p_central[0]; - conn_points[1]=p_central[1]; + if(base_rel->isSelfRelationship() || line_conn_mode != CONNECT_TABLE_EGDES) + { + conn_points[0]=p_central[0]; + conn_points[1]=p_central[1]; + + points.insert(points.begin(),p_central[0]); + points.push_back(p_central[1]); + } + else if(line_conn_mode == CONNECT_TABLE_EGDES) + { + QRectF brect; + QPolygonF pol; + QLineF edge, line = QLineF(tables[0]->getCenter(), tables[1]->getCenter()); + QPointF pi, center, p_aux[2]; + double font_factor=(font_config[ParsersAttributes::GLOBAL].font().pointSizeF()/DEFAULT_FONT_SIZE) * BaseObjectView::getScreenDpiFactor(), + size_factor = 1, + border_factor = CONN_LINE_LENGTH * 0.30, + min_lim = 0, max_lim = 0, + conn_rels_factors[2] = { 0, 0 }; + unsigned conn_rels_cnt[2] = { 0, 0 }; + + for(int tab_idx = 0; tab_idx < 2; tab_idx++) + { + conn_rels_cnt[tab_idx] = tables[tab_idx]->getConnectedRelsCount(base_rel->getTable(BaseRelationship::SRC_TABLE), + base_rel->getTable(BaseRelationship::DST_TABLE)); + conn_rels_factors[tab_idx] = conn_rels_cnt[tab_idx] == 1 ? 1 : 0.08f * (tables[tab_idx]->getConnectedRelationshipIndex(base_rel)); + + if(!points.empty()) + { + if(tab_idx == 0) + line = QLineF(tables[0]->getCenter(), points[0]); + else + line = QLineF(tables[1]->getCenter(), points[points.size() - 1]); + } + + if(rel_type==BaseRelationship::RELATIONSHIP_GEN || rel_type==BaseRelationship::RELATIONSHIP_DEP) + size_factor = 0.40; + else if(use_crows_foot) + { + if(rel_type==BaseRelationship::RELATIONSHIP_NN || + (tab_idx == 1 && rel_type==BaseRelationship::RELATIONSHIP_FK) || + (tab_idx == 0 && rel_type==BaseRelationship::RELATIONSHIP_1N && base_rel->isTableMandatory(BaseRelationship::SRC_TABLE)) || + (tab_idx == 0 && rel_type==BaseRelationship::RELATIONSHIP_11 && base_rel->isTableMandatory(BaseRelationship::SRC_TABLE)) || + (tab_idx == 1 && rel_type==BaseRelationship::RELATIONSHIP_11 && base_rel->isTableMandatory(BaseRelationship::DST_TABLE))) + size_factor = 1 * font_factor; + else + size_factor = 1.5 * font_factor; + + if(rel_type == BaseRelationship::RELATIONSHIP_GEN || + rel_type == BaseRelationship::RELATIONSHIP_DEP || + rel_type == BaseRelationship::RELATIONSHIP_11 || + (tab_idx == 0 && rel_type == BaseRelationship::RELATIONSHIP_1N) || + (tab_idx == 1 && rel_type == BaseRelationship::RELATIONSHIP_FK)) + border_factor = CONN_LINE_LENGTH * 0.30; + else + border_factor = CONN_LINE_LENGTH * 0.75; + } + else + size_factor = 0.65 * font_factor; + + brect = QRectF(tables[tab_idx]->pos(), tables[tab_idx]->boundingRect().size()); + pol = QPolygonF(brect); + center = tables[tab_idx]->getCenter(); + + for(int idx = 0; idx < pol.size() - 1; idx++) + { + edge.setP1(pol.at(idx)); + edge.setP2(pol.at(idx + 1)); + + if(line.intersect(edge, &pi)==QLineF::BoundedIntersection) + { + /* Adjusting the intersection point if there're more than one relationship connected the current table + * this will cause all relationships to be aligned together */ + if(conn_rels_cnt[tab_idx] > 1) + { + double max_dim = max(brect.height(), brect.width()); + int signal = 0; + + if(edge.dx() == 0) + { + signal = edge.dy()/fabs(edge.dy()) * (tab_idx == 0 ? 1 : -1); + pi.setY(pi.y() - (conn_rels_factors[tab_idx] * max_dim) * signal); + + // Adjusting the position of the interesection point to make is as close to the center of the edge as possible + pi.setY(pi.y() + (max_dim * 0.05) * signal); + } + + if(edge.dy() == 0) + { + signal = edge.dx()/fabs(edge.dx()) * (tab_idx == 0 ? 1 : -1); + pi.setX(pi.x() - (conn_rels_factors[tab_idx] * max_dim) * signal); + + // Adjusting the position of the interesection point to make is as close to the center of the edge as possible + pi.setX(pi.x() + (max_dim * 0.05) * signal); + } + } + + //Avoiding the line to be exposed in the rounded corners of the tables + if(edge.dx() == 0) + { + min_lim = brect.top() + border_factor; + max_lim = brect.bottom() - border_factor; + + if(pi.y() < min_lim) + pi.setY(min_lim); + else if(pi.y() > max_lim) + pi.setY(max_lim); + } + else + { + min_lim = brect.left() + border_factor; + max_lim = brect.right() - border_factor; + + if(pi.x() < min_lim) + pi.setX(min_lim); + else if(pi.x() > max_lim) + pi.setX(max_lim); + } + + conn_points[tab_idx] = p_central[tab_idx] = pi; + + if(edge.dx() == 0) + { + if(pi.x() < center.x()) + pi.setX(pi.x() - CONN_LINE_LENGTH * size_factor); + else + pi.setX(pi.x() + CONN_LINE_LENGTH * size_factor); + + conn_vert_sides[tab_idx] = true; + } + else + { + if(pi.y() < center.y()) + pi.setY(pi.y() - CONN_LINE_LENGTH * size_factor); + else + pi.setY(pi.y() + CONN_LINE_LENGTH * size_factor); + + conn_horiz_sides[tab_idx] = true; + } + + p_aux[tab_idx] = pi; + break; + } + else + { + p_aux[tab_idx] = p_central[tab_idx]; + } + } + } + + points.insert(points.begin(), p_central[0]); + points.insert(points.begin() + 1, p_aux[0]); + + points.push_back(p_aux[1]); + points.push_back(p_central[1]); + } //If the relationship is selected we do not change the lines colors if(this->isSelected() && !lines.empty()) @@ -751,12 +1008,9 @@ void RelationshipView::configureLine(void) } //For dependency relationships the line is dashed - if(base_rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_DEP) + if(rel_type==BaseRelationship::RELATIONSHIP_DEP) pen.setStyle(Qt::DashLine); - points.insert(points.begin(),p_central[0]); - points.push_back(p_central[1]); - /* For identifier relationships an additional point is created on the center of the line that supports the descriptor in order to modify the line thickness on the weak entity side */ @@ -806,9 +1060,9 @@ void RelationshipView::configureLine(void) //If the relationship is identifier or bidirectional, the line has its thickness modified if(rel && (rel->isIdentifier() && vet_idx==0)) - pen.setWidthF(1.75f); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.90f); else - pen.setWidthF(1.15f); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.45f); lin->setLine(QLineF(ref_pnt->at(i), ref_points[vet_idx])); lin->setPen(pen); @@ -842,10 +1096,10 @@ void RelationshipView::configureLine(void) lin=lines[i]; //If the relationship is identifier or bidirectional, the line has its thickness modified - if(bidirectional || (rel && (rel->isIdentifier() && i >= idx_lin_desc))) - pen.setWidthF(1.75f); + if(rel && (rel->isIdentifier() && i >= idx_lin_desc)) + pen.setWidthF(OBJ_BORDER_WIDTH * 1.90f); else - pen.setWidthF(1.15f); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.45f); lin->setLine(QLineF(points[i], points[i+1])); lin->setPen(pen); @@ -867,11 +1121,11 @@ void RelationshipView::configureLine(void) } //Exposing the line ending circles - if((!base_rel->isSelfRelationship() && line_conn_mode==CONNECT_CENTER_PNTS) || + if((!base_rel->isSelfRelationship() && line_conn_mode==CONNECT_CENTER_PNTS && !use_crows_foot) || (!base_rel->isSelfRelationship() && - ((base_rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_DEP) || - (base_rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_GEN) || - (base_rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_NN)))) + ((line_conn_mode != CONNECT_TABLE_EGDES && rel_type==BaseRelationship::RELATIONSHIP_DEP) || + (line_conn_mode != CONNECT_TABLE_EGDES && rel_type==BaseRelationship::RELATIONSHIP_GEN) || + (line_conn_mode != CONNECT_TABLE_EGDES && rel_type==BaseRelationship::RELATIONSHIP_NN && !use_crows_foot)))) { for(i=0; i < 2; i++) { @@ -891,6 +1145,7 @@ void RelationshipView::configureLine(void) if(use_curved_lines && !base_rel->isSelfRelationship()) { BezierCurveItem * curve = nullptr; + bool invert_cpoints = false, simple_curve = false; i = 0; for(auto &line : lines) @@ -906,10 +1161,21 @@ void RelationshipView::configureLine(void) curve = curves[i]; i++; - curve->setLine(line->line(), - conn_same_sides && lines.size() == 1, - base_rel->getRelationshipType()); + /* Creates simple a curved line in the following situations: + * 1) The crow's foot is not enabled but the relationship connects in the same sides on tables (conn_same_sides) + * 2) The crow's foot is enabled and one of the connection point is not in the horizontal edges of one of the tables (conn_horiz_sides) */ + + /* We invert the curve's bounding rect when crow's foot is enabled and the relationship connects + * at the top/bottom edges of both tables */ + simple_curve = (conn_same_sides && lines.size() == 1) || (conn_horiz_sides[0] != conn_horiz_sides[1] && lines.size() == 3); + + if(!simple_curve) + invert_cpoints = (conn_horiz_sides[0] && conn_horiz_sides[1] && lines.size() == 3); + else + invert_cpoints = (!conn_horiz_sides[0] && conn_horiz_sides[1] && conn_vert_sides[0] && !conn_vert_sides[1]); + + curve->setLine(line->line(), simple_curve, invert_cpoints); curve->setPen(line->pen()); line->setVisible(false); } @@ -944,14 +1210,18 @@ void RelationshipView::configureLine(void) } this->configureDescriptor(); + + this->configureCrowsFootDescriptors(); + this->configureLabels(); + this->configureProtectedIcon(); configuring_line=false; /* Making a little tweak on the foreign key type name. Despite being of class BaseRelationship, for semantics purposes shows the type of this relationship as "Relationship" unlike "Link" */ - if(base_rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_FK) + if(rel_type==BaseRelationship::RELATIONSHIP_FK) tool_tip=base_rel->getName(true) + QString(" (") + BaseObject::getTypeName(OBJ_RELATIONSHIP) + QString(")"); else @@ -1019,17 +1289,16 @@ void RelationshipView::configureDescriptor(void) else descriptor->setBrush(BaseObjectView::getFillStyle(ParsersAttributes::RELATIONSHIP)); - if(rel_type==BaseRelationship::RELATIONSHIP_DEP || rel_type==BaseRelationship::RELATIONSHIP_GEN) { - pol.append(QPointF(0,0)); pol.append(QPointF(21,13)); - pol.append(QPointF(0,26)); pol.append(QPointF(0,13)); + pol.append(QPointF(0,0)); pol.append(QPointF(18,10)); + pol.append(QPointF(0,20)); pol.append(QPointF(0,10)); } else { - pol.append(QPointF(13,0)); pol.append(QPointF(26,13)); - pol.append(QPointF(13,26)); pol.append(QPointF(0,13)); + pol.append(QPointF(11,0)); pol.append(QPointF(22,11)); + pol.append(QPointF(11,22)); pol.append(QPointF(0,11)); } //Resizes the polygon according the font factor @@ -1057,9 +1326,22 @@ void RelationshipView::configureDescriptor(void) } else { - double percent = path.percentAtLength(path.length()/2); - angle = -path.angleAtPercent(percent); - pnt = path.pointAtPercent(percent); + /* Workaround to avoid the inheritance / dependency relationship to get the descriptor rotated to the wrong side + * We create and auxiliary line with points from the position at 65% of the curve to the 45% and use the + * angle of that line instead of the angle at 50% of the curve */ + if((rel_type == BaseRelationship::RELATIONSHIP_DEP || rel_type == BaseRelationship::RELATIONSHIP_GEN) && + curve->isControlPointsInverted() && !curve->isSimpleCurve() && !curve->isStraightLine()) + { + QLineF lin_aux = QLineF(path.pointAtPercent(0.65), path.pointAtPercent(0.45)); + angle = -lin_aux.angle(); + pnt = path.pointAtPercent(0.5); + } + else + { + double percent = path.percentAtLength(path.length()/2); + angle = -path.angleAtPercent(percent); + pnt = path.pointAtPercent(percent); + } } } else @@ -1114,6 +1396,271 @@ void RelationshipView::configureDescriptor(void) this->configureAttributes(); this->configurePositionInfo(); + + /* If the crow's feet is enabled the relationship descriptor is hidden + * for 1:1, 1:n, n:n and fk relationship. For generalization and dependency + * relationships the descriptor is still displayed. */ + descriptor->setVisible(!use_crows_foot || + (use_crows_foot && ( + rel_type == BaseRelationship::RELATIONSHIP_DEP || + rel_type == BaseRelationship::RELATIONSHIP_GEN))); + obj_shadow->setVisible(descriptor->isVisible()); +} + +void RelationshipView::configureCrowsFootDescriptors(void) +{ + BaseRelationship * base_rel = dynamic_cast(this->getSourceObject()); + Relationship *rel=dynamic_cast(base_rel); + + //Hiding all descriptors related to crow's foot when the notation is not being used + if(!use_crows_foot && cf_descriptors[BaseRelationship::SRC_TABLE]) + { + for(unsigned tab_id = BaseRelationship::SRC_TABLE; tab_id <= BaseRelationship::DST_TABLE; tab_id++) + { + for(auto &item : cf_descriptors[tab_id]->childItems()) + { + cf_descriptors[tab_id]->setRotation(0); + cf_descriptors[tab_id]->removeFromGroup(item); + this->removeFromGroup(item); + item->setVisible(false); + cf_descriptors[tab_id]->setVisible(false); + } + } + } + else if(use_crows_foot && base_rel && + (base_rel->getRelationshipType() == BaseRelationship::RELATIONSHIP_11 || + base_rel->getRelationshipType() == BaseRelationship::RELATIONSHIP_1N || + base_rel->getRelationshipType() == BaseRelationship::RELATIONSHIP_NN || + base_rel->getRelationshipType() == BaseRelationship::RELATIONSHIP_FK)) + { + QGraphicsLineItem *line_item = nullptr; + QGraphicsEllipseItem *circle_item = nullptr; + unsigned rel_type = base_rel->getRelationshipType(); + double factor=(font_config[ParsersAttributes::GLOBAL].font().pointSizeF()/DEFAULT_FONT_SIZE) * BaseObjectView::getScreenDpiFactor(); + int signal = 1; + BaseTableView *tables[2] = { nullptr, nullptr }; + bool mandatory[2] = { false, false }; + + if(rel_type == BaseRelationship::RELATIONSHIP_NN || rel_type == BaseRelationship::RELATIONSHIP_FK) + { + tables[BaseRelationship::SRC_TABLE] = dynamic_cast(base_rel->getTable(BaseRelationship::SRC_TABLE)->getReceiverObject()); + tables[BaseRelationship::DST_TABLE] = dynamic_cast(base_rel->getTable(BaseRelationship::DST_TABLE)->getReceiverObject()); + mandatory[BaseRelationship::SRC_TABLE] = base_rel->isTableMandatory(BaseRelationship::SRC_TABLE); + mandatory[BaseRelationship::DST_TABLE] = base_rel->isTableMandatory(BaseRelationship::DST_TABLE); + } + else + { + tables[BaseRelationship::SRC_TABLE] = dynamic_cast(rel->getReferenceTable()->getReceiverObject()); + tables[BaseRelationship::DST_TABLE] = dynamic_cast(rel->getReceiverTable()->getReceiverObject()); + mandatory[BaseRelationship::SRC_TABLE] = rel->isReferenceTableMandatory(); + mandatory[BaseRelationship::DST_TABLE] = rel->isReceiverTableMandatory(); + + /* There's a special case for one-to-one relationships that will cause the crow's foot + * descriptors to be positioned in the oposite sides when compared to other relationships. + * This because pgModeler switches automatically the receiver table to be the destination one + * when the mandatory table of the relationship is the destination. So we use and auxiliary (signal inverter) + * variable to alter the descriptors position */ + if(mandatory[BaseRelationship::SRC_TABLE] && rel_type == BaseRelationship::RELATIONSHIP_11 && + rel->getTable(BaseRelationship::DST_TABLE) == rel->getReferenceTable()) + signal = -1; + } + + //Allocatting all objects related to the crow's foot descriptors + if(cf_descriptors[BaseRelationship::SRC_TABLE] == nullptr) + { + int src_zvalue = lines.front()->zValue() + 1, + dst_zvalue = lines.back()->zValue() + 1; + QGraphicsLineItem *line_item = nullptr; + + for(int idx = 0; idx < 2; idx++) + { + cf_descriptors[idx] = new QGraphicsItemGroup; + round_cf_descriptors[idx] = new QGraphicsEllipseItem; + this->addToGroup(cf_descriptors[idx]); + } + + for(int idx = 0; idx < 4; idx++) + { + line_item = new QGraphicsLineItem; + src_cf_lines.push_back(line_item); + cf_descriptors[BaseRelationship::SRC_TABLE]->setZValue(src_zvalue); + + line_item = new QGraphicsLineItem; + dst_cf_lines.push_back(line_item); + cf_descriptors[BaseRelationship::DST_TABLE]->setZValue(dst_zvalue); + } + } + else + { + cf_descriptors[BaseRelationship::SRC_TABLE]->setVisible(true); + cf_descriptors[BaseRelationship::DST_TABLE]->setVisible(true); + } + + QPointF pi; + QRectF brect; + QPen pen, pens[2] = { lines.front()->pen(), lines.back()->pen() }; + QLineF line, line1, edge, rel_lines[2] = {(signal < 0 ? lines.back()->line() : lines.front()->line()), + (signal < 0 ? lines.front()->line() : lines.back()->line())}; + QPolygonF pol; + vector *> cf_lines = { &src_cf_lines, &dst_cf_lines }; + unsigned lin_idx = 0; + double px = 0, py = 0, min_x = 0, max_x = 0, min_y = 0, max_y = 0; + + for(unsigned tab_id = BaseRelationship::SRC_TABLE; tab_id <= BaseRelationship::DST_TABLE; tab_id++) + { + cf_descriptors[tab_id]->setRotation(0); + + for(auto &line : *cf_lines[tab_id]) + { + cf_descriptors[tab_id]->removeFromGroup(line); + this->removeFromGroup(line); + line->setVisible(false); + } + + //Configuring the minimum cardinality descriptor + if((tab_id == BaseRelationship::SRC_TABLE && + rel_type != BaseRelationship::RELATIONSHIP_NN && rel_type != BaseRelationship::RELATIONSHIP_FK) || + + (tab_id == BaseRelationship::DST_TABLE && + (rel_type == BaseRelationship::RELATIONSHIP_11 || rel_type == BaseRelationship::RELATIONSHIP_FK))) + { + + line_item = cf_lines[tab_id]->at(lin_idx++); + cf_descriptors[tab_id]->addToGroup(line_item); + line_item->setVisible(true); + + line_item->setLine(QLineF(QPointF(0, -8 * factor), QPointF(0, 8 * factor))); + line_item->setPos((10 * signal) * (tab_id == BaseRelationship::DST_TABLE ? -1 : 1), 0); + line_item->setPen(pens[tab_id]); + + } + else + { + //Configuring the crow's foot descriptor + if(tab_id == BaseRelationship::SRC_TABLE) + { + px = 0; + line = QLineF(QPointF(14, 0), QPointF(0, - 10 * factor)); + line1 = QLineF(QPointF(14, 0), QPointF(0, 10 * factor)); + } + else + { + line = QLineF(QPointF(0, 0), QPointF(14, - 10 * factor)); + line1 = QLineF(QPointF(0, 0), QPointF(14, 10 * factor)); + px = -line.dx(); + } + + line_item = cf_lines[tab_id]->at(lin_idx++); + cf_descriptors[tab_id]->addToGroup(line_item); + line_item->setVisible(true); + line_item->setLine(line); + line_item->setPos(px, 0); + line_item->setPen(pens[tab_id]); + + line_item = cf_lines[tab_id]->at(lin_idx++); + cf_descriptors[tab_id]->addToGroup(line_item); + line_item->setVisible(true); + line_item->setLine(line1); + line_item->setPos(px, 0); + line_item->setPen(pens[tab_id]); + } + + + cf_descriptors[tab_id]->removeFromGroup(round_cf_descriptors[tab_id]); + this->removeFromGroup(round_cf_descriptors[tab_id]); + round_cf_descriptors[tab_id]->setVisible(false); + + //Configuring the maximum cardinality descriptor + if((tab_id == BaseRelationship::SRC_TABLE && mandatory[tab_id]) || rel_type == BaseRelationship::RELATIONSHIP_NN) + { + line_item = cf_lines[tab_id]->at(lin_idx++); + cf_descriptors[tab_id]->addToGroup(line_item); + line_item->setVisible(true); + + line_item->setLine(QLineF(QPointF(0, -8 * factor), QPointF(0, 8 * factor))); + line_item->setPos(15 * signal * (tab_id == BaseRelationship::DST_TABLE ? -1 : 1), 0); + line_item->setPen(pens[tab_id]); + } + else if(!mandatory[tab_id] && + ((rel_type != BaseRelationship::RELATIONSHIP_FK) || + (tab_id == BaseRelationship::SRC_TABLE && rel_type == BaseRelationship::RELATIONSHIP_FK))) + { + //Configuring the circle which describes the optional cardinality + circle_item = round_cf_descriptors[tab_id]; + cf_descriptors[tab_id]->addToGroup(circle_item); + circle_item->setVisible(true); + circle_item->setRect(QRectF(0, 0, GRAPHIC_PNT_RADIUS * 2.20 * factor, GRAPHIC_PNT_RADIUS * 2.20 * factor)); + + py = -(circle_item->boundingRect().height()/2.20); + + if(tab_id == BaseRelationship::SRC_TABLE) + { + if(base_rel->isSelfRelationship() || rel_type != BaseRelationship::RELATIONSHIP_NN) + px = 15; + else + px = 11; + } + else + { + if(rel_type == BaseRelationship::RELATIONSHIP_11) + { + if(signal < 0) + px = 15; + else + px = -13 - circle_item->boundingRect().width(); + } + else + px = -15 - circle_item->boundingRect().width(); + } + + pen = pens[tab_id]; + + if(rel_type == BaseRelationship::RELATIONSHIP_FK) + pen.setStyle(Qt::DashLine); + + circle_item->setPos(px, py); + circle_item->setPen(pen); + circle_item->setBrush(descriptor->brush()); + } + + lin_idx = 0; + brect = QRectF(tables[tab_id]->pos(), tables[tab_id]->boundingRect().size()); + pol = QPolygonF(brect); + + /* Configuring the position of the descriptor based upon the intersection + * point of the relationship line and the edge of the bounding rect of the table */ + cf_descriptors[tab_id]->setRotation(-rel_lines[tab_id].angle()); + + for(int idx = 0; idx < pol.size() - 1; idx++) + { + edge.setP1(pol.at(idx)); + edge.setP2(pol.at(idx + 1)); + + if(rel_lines[tab_id].intersect(edge, &pi)==QLineF::BoundedIntersection) + { + cf_descriptors[tab_id]->setPos(pi); + break; + } + else + { + /* There some cases in which the intersection point can't be determined in BoundedIntersection mode + * so as a fallback we check if one of the coordinates of the identified intersection point + * is between one of the coordinates of the relationship line used in the operation. + * + * If it matches we'll use the use one of the extremes of the relationship line in the matching coordinate */ + min_x = qMin(rel_lines[tab_id].p1().x(), rel_lines[tab_id].p2().x()), + max_x = qMax(rel_lines[tab_id].p1().x(), rel_lines[tab_id].p2().x()), + min_y = qMin(rel_lines[tab_id].p1().y(), rel_lines[tab_id].p2().y()), + max_y = qMax(rel_lines[tab_id].p1().y(), rel_lines[tab_id].p2().y()); + + if(pi.x() >= min_x && pi.x() <= max_x) + cf_descriptors[tab_id]->setPos(QPointF(pi.x(), (rel_lines[tab_id].dy() >= 0 ? max_y : min_y))); + else if(pi.y() >= min_y && pi.y() <= max_y) + cf_descriptors[tab_id]->setPos(QPointF((rel_lines[tab_id].dx() >= 0 ? max_x : min_x), pi.y())); + } + } + } + } } void RelationshipView::configureAttributes(void) @@ -1195,7 +1742,7 @@ void RelationshipView::configureAttributes(void) desc->setRect(rect); desc->setPen(BaseObjectView::getBorderStyle(ParsersAttributes::ATTRIBUTE)); desc->setBrush(BaseObjectView::getFillStyle(ParsersAttributes::ATTRIBUTE)); - lin->setPen(BaseObjectView::getBorderStyle(ParsersAttributes::RELATIONSHIP)); + lin->setPen(descriptor->pen()); text->setBrush(fmt.foreground()); text->setFont(font); sel_attrib->setPen(BaseObjectView::getBorderStyle(ParsersAttributes::OBJ_SELECTION)); @@ -1215,7 +1762,7 @@ void RelationshipView::configureAttributes(void) sel_attrib->setPolygon(pol); p_aux=this->mapToItem(attrib, descriptor->pos().x() + (descriptor->boundingRect().width()/2.0f), - descriptor->pos().y() + (descriptor->boundingRect().height()/2.0f)); + descriptor->pos().y() + (descriptor->boundingRect().height()/2.0f)); lin->setLine(QLineF(p_aux, desc->boundingRect().center())); py+=desc->boundingRect().height() + (2 * VERT_SPACING); @@ -1245,8 +1792,8 @@ void RelationshipView::configureLabels(void) pnt=descriptor->pos(); x=pnt.x() - - ((labels[BaseRelationship::REL_NAME_LABEL]->boundingRect().width() - - descriptor->boundingRect().width())/2.0f); + ((labels[BaseRelationship::REL_NAME_LABEL]->boundingRect().width() - + descriptor->boundingRect().width())/2.0f); if(base_rel->isSelfRelationship()) y=pnt.y() - labels[BaseRelationship::REL_NAME_LABEL]->boundingRect().height() - (2 * VERT_SPACING); @@ -1256,8 +1803,16 @@ void RelationshipView::configureLabels(void) labels[BaseRelationship::REL_NAME_LABEL]->setVisible(!hide_name_label); configureLabelPosition(BaseRelationship::REL_NAME_LABEL, x, y); - if(rel_type!=BaseRelationship::RELATIONSHIP_GEN && - rel_type!=BaseRelationship::RELATIONSHIP_DEP) + //Hides the cardinality labels when crow's feet is enabled + if(labels[BaseRelationship::SRC_CARD_LABEL] && labels[BaseRelationship::DST_CARD_LABEL]) + { + labels[BaseRelationship::SRC_CARD_LABEL]->setVisible(!use_crows_foot); + labels[BaseRelationship::DST_CARD_LABEL]->setVisible(!use_crows_foot); + } + + if(!use_crows_foot && + rel_type!=BaseRelationship::RELATIONSHIP_GEN && + rel_type!=BaseRelationship::RELATIONSHIP_DEP) { QPointF pi, pf, p_int, pos; unsigned idx, i1; @@ -1265,7 +1820,7 @@ void RelationshipView::configureLabels(void) QLineF lins[2], borders[2][4]; QRectF tab_rect, rect; unsigned label_ids[2]={ BaseRelationship::SRC_CARD_LABEL, - BaseRelationship::DST_CARD_LABEL }; + BaseRelationship::DST_CARD_LABEL }; if(!base_rel->isSelfRelationship() && line_conn_mode==CONNECT_FK_TO_PK && rel_type!=BaseRelationship::RELATIONSHIP_NN) @@ -1304,9 +1859,9 @@ void RelationshipView::configureLabels(void) borders[idx][0].setPoints(pos, QPointF(pos.x(), pos.y() + rect.height())); borders[idx][1].setPoints(QPointF(pos.x(), pos.y() + rect.height()), - QPointF(pos.x() + rect.width(), pos.y() + rect.height())); + QPointF(pos.x() + rect.width(), pos.y() + rect.height())); borders[idx][2].setPoints(QPointF(pos.x() + rect.width(), pos.y()), - QPointF(pos.x() + rect.width(), pos.y() + rect.height())); + QPointF(pos.x() + rect.width(), pos.y() + rect.height())); borders[idx][3].setPoints(pos, QPointF(pos.x() + rect.width(), pos.y())); } @@ -1437,7 +1992,7 @@ QRectF RelationshipView::__boundingRect(void) //Checks if some label is out of reference dimension for(i=0; i < 3; i++) { - if(labels[i]) + if(labels[i] && labels[i]->isVisible()) { rect.setTopLeft(labels[i]->scenePos()); rect.setSize(labels[i]->boundingRect().size()); diff --git a/libobjrenderer/src/relationshipview.h b/libobjrenderer/src/relationshipview.h index ff51bd4f0..624403c5d 100644 --- a/libobjrenderer/src/relationshipview.h +++ b/libobjrenderer/src/relationshipview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -46,6 +46,9 @@ class RelationshipView: public BaseObjectView { //! \brief Indicates that the relationship lines should be curved static bool use_curved_lines; + //! \brief Indicates that the relationship should be drawn in Crow's foot notation + static bool use_crows_foot; + /*! \brief Specify the type of connection used by the lines. The first (classical) is to connect the line to tables through their central points. The second (better semantics) makes the line start from the fk columns on receiver table and connecting to the pk columns on reference table */ @@ -100,6 +103,13 @@ class RelationshipView: public BaseObjectView { //! \brief Stores the curved lines representing the relationship vector curves; + //! \brief Stores the crow's foot notation descriptors + QGraphicsItemGroup * cf_descriptors[2]; + + vector src_cf_lines, dst_cf_lines; + + QGraphicsEllipseItem *round_cf_descriptors[2]; + //! \brief Stores the selected child object index int sel_object_idx; @@ -109,6 +119,9 @@ class RelationshipView: public BaseObjectView { //! \brief Configures the descriptor form and positioning void configureDescriptor(void); + //! \brief Configures the crow's feet descriptors form and positioning + void configureCrowsFootDescriptors(void); + //! \brief Configures the attributes positioning void configureAttributes(void); @@ -146,7 +159,8 @@ class RelationshipView: public BaseObjectView { public: static const unsigned CONNECT_CENTER_PNTS=0, - CONNECT_FK_TO_PK=1; + CONNECT_FK_TO_PK=1, + CONNECT_TABLE_EGDES=2; RelationshipView(BaseRelationship *rel); ~RelationshipView(void); @@ -169,6 +183,12 @@ class RelationshipView: public BaseObjectView { //! \brief Returns the current state of curved lines usage static bool isCurvedLines(void); + //! \brief Enables the usage of Crow's foot notation for all relationships + static void setCrowsFoot(bool value); + + //! \brief Returns the current state of Crow's foot notation usage + static bool isCrowsFoot(void); + /*! \brief Configures the mode in which the lines are connected on tables. The first one is the CONNECT_CENTER_PNTS (the classical one) which connects the two tables through the center points. The CONNECT_FK_TO_PK is the one with a better diff --git a/libobjrenderer/src/roundedrectitem.cpp b/libobjrenderer/src/roundedrectitem.cpp index 50a0001aa..538527b75 100644 --- a/libobjrenderer/src/roundedrectitem.cpp +++ b/libobjrenderer/src/roundedrectitem.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/roundedrectitem.h b/libobjrenderer/src/roundedrectitem.h index e5c3c51f5..7c51cf919 100644 --- a/libobjrenderer/src/roundedrectitem.h +++ b/libobjrenderer/src/roundedrectitem.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/schemaview.cpp b/libobjrenderer/src/schemaview.cpp index f0809d9ef..cc065fcc3 100644 --- a/libobjrenderer/src/schemaview.cpp +++ b/libobjrenderer/src/schemaview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -148,11 +148,21 @@ QList SchemaView::getChildren(void) void SchemaView::togglePlaceholder(bool visible) { - //BaseObjectView::togglePlaceholder(visible); for(auto &obj : getChildren()) obj->togglePlaceholder(visible); } +void SchemaView::moveTo(QPointF new_pos) +{ + double dx=new_pos.x() - pos().x(), + dy=new_pos.y() - pos().y(); + + this->setPos(new_pos); + + for(auto &child : children) + child->moveBy(dx, dy); +} + void SchemaView::configureObject(void) { Schema *schema=dynamic_cast(this->getSourceObject()); @@ -223,7 +233,7 @@ void SchemaView::configureObject(void) this->setFlag(ItemSendsGeometryChanges, true); color=schema->getFillColor(); - color.setAlpha(80); + color.setAlpha(OBJ_ALPHA_CHANNEL * 0.80); box->setBrush(color); color=QColor(color.red()/3,color.green()/3,color.blue()/3, 80); diff --git a/libobjrenderer/src/schemaview.h b/libobjrenderer/src/schemaview.h index 42c1a297f..f80b591a6 100644 --- a/libobjrenderer/src/schemaview.h +++ b/libobjrenderer/src/schemaview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -67,10 +67,13 @@ class SchemaView: public BaseObjectView void selectChildren(void); unsigned getChildrenCount(void); + QList getChildren(void); virtual void togglePlaceholder(bool visible); + void moveTo(QPointF new_pos); + public slots: void configureObject(void); }; diff --git a/libobjrenderer/src/styledtextboxview.h b/libobjrenderer/src/styledtextboxview.h index a2aa90435..c36848674 100644 --- a/libobjrenderer/src/styledtextboxview.h +++ b/libobjrenderer/src/styledtextboxview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/tableobjectview.cpp b/libobjrenderer/src/tableobjectview.cpp index 8f49e3169..383a499a8 100644 --- a/libobjrenderer/src/tableobjectview.cpp +++ b/libobjrenderer/src/tableobjectview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -58,6 +58,7 @@ void TableObjectView::configureDescriptor(ConstraintType constr_type) Column *column=dynamic_cast(this->getSourceObject()); bool ellipse_desc=false; double factor=(font_config[ParsersAttributes::GLOBAL].font().pointSizeF()/DEFAULT_FONT_SIZE) * BaseObjectView::getScreenDpiFactor(); + QPen pen; //Based upon the source object type the descriptor is allocated if(this->getSourceObject()) @@ -102,7 +103,10 @@ void TableObjectView::configureDescriptor(ConstraintType constr_type) attrib=ParsersAttributes::COLUMN; desc->setBrush(this->getFillStyle(attrib)); - desc->setPen(this->getBorderStyle(attrib)); + + pen = this->getBorderStyle(attrib); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.15f); + desc->setPen(pen); } else { @@ -140,7 +144,10 @@ void TableObjectView::configureDescriptor(ConstraintType constr_type) desc->setPolygon(pol); desc->setBrush(this->getFillStyle(attrib)); - desc->setPen(this->getBorderStyle(attrib)); + + pen = this->getBorderStyle(attrib); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.15f); + desc->setPen(pen); } } else if(obj_type==OBJ_INDEX || obj_type==OBJ_RULE || @@ -160,7 +167,10 @@ void TableObjectView::configureDescriptor(ConstraintType constr_type) desc->setPolygon(pol); desc->setBrush(this->getFillStyle(tab_obj->getSchemaName())); - desc->setPen(this->getBorderStyle(tab_obj->getSchemaName())); + + pen = this->getBorderStyle(tab_obj->getSchemaName()); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.15f); + desc->setPen(pen); } else { @@ -169,7 +179,10 @@ void TableObjectView::configureDescriptor(ConstraintType constr_type) desc->setRect(QRectF(QPointF(0,0), QSizeF(9.0f * factor, 9.0f * factor))); desc->setBrush(this->getFillStyle(ParsersAttributes::REFERENCE)); - desc->setPen(this->getBorderStyle(ParsersAttributes::REFERENCE)); + + pen = this->getBorderStyle(ParsersAttributes::REFERENCE); + pen.setWidthF(OBJ_BORDER_WIDTH * 1.15f); + desc->setPen(pen); } } diff --git a/libobjrenderer/src/tableobjectview.h b/libobjrenderer/src/tableobjectview.h index c5ce23cfa..c4838a520 100644 --- a/libobjrenderer/src/tableobjectview.h +++ b/libobjrenderer/src/tableobjectview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/tabletitleview.cpp b/libobjrenderer/src/tabletitleview.cpp index 08aa1136a..ed7e1c71d 100644 --- a/libobjrenderer/src/tabletitleview.cpp +++ b/libobjrenderer/src/tabletitleview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/tabletitleview.h b/libobjrenderer/src/tabletitleview.h index 810f5c299..dbcdb0051 100644 --- a/libobjrenderer/src/tabletitleview.h +++ b/libobjrenderer/src/tabletitleview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/tableview.cpp b/libobjrenderer/src/tableview.cpp index a7907c0c1..8385f31e2 100644 --- a/libobjrenderer/src/tableview.cpp +++ b/libobjrenderer/src/tableview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/tableview.h b/libobjrenderer/src/tableview.h index 4636e805d..3825896c1 100644 --- a/libobjrenderer/src/tableview.h +++ b/libobjrenderer/src/tableview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/textboxview.cpp b/libobjrenderer/src/textboxview.cpp index a6f9b1c63..4b707fa9f 100644 --- a/libobjrenderer/src/textboxview.cpp +++ b/libobjrenderer/src/textboxview.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libobjrenderer/src/textboxview.h b/libobjrenderer/src/textboxview.h index 767b2bd55..2cfa29d7c 100644 --- a/libobjrenderer/src/textboxview.h +++ b/libobjrenderer/src/textboxview.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libparsers/src/attribsmap.h b/libparsers/src/attribsmap.h index 7737af750..39c05b51a 100644 --- a/libparsers/src/attribsmap.h +++ b/libparsers/src/attribsmap.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libparsers/src/parsersattributes.cpp b/libparsers/src/parsersattributes.cpp index 0013a95e8..3a3068e96 100644 --- a/libparsers/src/parsersattributes.cpp +++ b/libparsers/src/parsersattributes.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -31,6 +31,7 @@ namespace ParsersAttributes { ALIGNMENT=QString("alignment"), ALIGN_OBJS_TO_GRID=QString("align-objs-to-grid"), ALTER_CMDS=QString("alter-cmds"), + ALLOW_CONNS=QString("allow-conns"), ANALYZE_FUNC=QString("analyze"), ANCESTOR_TABLE=QString("ancestor-table"), APPEND_AT_EOD=QString("append-at-eod"), @@ -57,6 +58,7 @@ namespace ParsersAttributes { BOTTOM=QString("bottom"), BUFFERING=QString("buffering"), BY_VALUE=QString("by-value"), + BYPASSRLS=QString("bypassrls"), CACHE=QString("cache"), CANONICAL_FUNC=QString("canonical"), CANVAS_CORNER_MOVE=QString("canvas-corner-move"), @@ -66,6 +68,7 @@ namespace ParsersAttributes { CATEGORY=QString("category"), CHANGE=QString("change"), CHANGELOG=QString("changelog"), + CHECK_EXP=QString("check-exp"), CHECK_UPDATE=QString("check-update"), CK_CONSTR=QString("ck-constr"), CLIENT_ENCODING=QString("client-encoding"), @@ -80,9 +83,11 @@ namespace ParsersAttributes { COLOR=QString("color"), COLORS=QString("colors"), COLS_COMMENT=QString("cols-comment"), + COL_IS_IDENTITY=QString("col-is-identity"), COLUMN_ALIAS=QString("column-alias"), COLUMN=QString("column"), COLUMNS=QString("columns"), + COMMAND=QString("command"), COMMANDS=QString("commands"), COMMENT=QString("comment"), COMMUTATOR_OP=QString("commutator-op"), @@ -97,6 +102,7 @@ namespace ParsersAttributes { CONN_LIMIT=QString("connlimit"), CONNECT_CENTER_PNTS=QString("center-pnts"), CONNECT_FK_TO_PK=QString("fk-to-pk"), + CONNECT_TABLE_EDGES=QString("table-edges"), CONNECT_PRIV=QString("connect"), CONNECTION=QString("connection"), CONNECTIONS=QString("connections"), @@ -115,6 +121,7 @@ namespace ParsersAttributes { CREATE=QString("create"), CREATEDB=QString("createdb"), CREATEROLE=QString("createrole"), + CROWS_FOOT=QString("crows-foot"), CTE_EXPRESSION=QString("cte-exp"), CUR_VERSION=QString("cur-version"), CUSTOM_COLOR=QString("custom-color"), @@ -123,6 +130,7 @@ namespace ParsersAttributes { CYCLE=QString("cycle"), DATA_DIRECTORY=QString("data-directory"), DATE=QString("date"), + DATABASE=QString("database"), DB_MODEL=QString("dbmodel"), DDL_END_TOKEN=QString("-- ddl-end --"), DECL_IN_TABLE=QString("decl-in-table"), @@ -136,7 +144,7 @@ namespace ParsersAttributes { DEFAULT=QString("default"), DEFER_TYPE=QString("defer-type"), DEFERRABLE=QString("deferrable"), - DEFINITION=QString("definition"), + DEFINITION=QString("definition"), DEL_ACTION=QString("del-action"), DEL_EVENT=QString("del-event"), DELETE_PRIV=QString("delete"), @@ -148,6 +156,7 @@ namespace ParsersAttributes { DIRECTORY=QString("directory"), DISABLE_SMOOTHNESS=QString("disable-smoothness"), DISPLAY_LINE_NUMBERS=QString("display-line-numbers"), + DOM_CONSTRAINT=QString("domconstraint"), DOCK_WIDGETS=QString("dock-widgets"), DROP_CMDS=QString("drop-cmds"), DROP=QString("drop"), @@ -160,6 +169,7 @@ namespace ParsersAttributes { DST_TABLE=QString("dst-table"), DYNAMIC_LIBRARY_PATH=QString("dynamic-library-path"), DYNAMIC_SHARED_MEMORY=QString("dynamic-shared-memory-type"), + END_EXP=QString("end-exp"), ELEMENT=QString("element"), ELEMENTS=QString("elements"), ENCODING=QString("encoding"), @@ -184,6 +194,7 @@ namespace ParsersAttributes { EXPRESSIONS=QString("expressions"), EXT_OBJ_OIDS=QString("ext-obj-oids"), FACTOR=QString("factor"), + FADEIN_OBJECTS=QString("fadein-objects"), FADED_OUT=QString("faded-out"), FAMILY=QString("family"), FAST_UPDATE=QString("fast-update"), @@ -219,12 +230,12 @@ namespace ParsersAttributes { HIDE_REL_NAME=QString("hide-rel-name"), HIDE_TABLE_TAGS=QString("hide-table-tags"), HIGHLIGHT_LINES=QString("highlight-lines"), - HIGHLIGHT_OBJECTS=QString("highlight-objects"), HIGHLIGHT_ORDER=QString("highlight-order"), HISTORY_MAX_LENGTH=QString("history-max-length"), ICON=QString("icon"), ID=QString("id"), IDENTIFIER=QString("identifier"), + IDENTITY_TYPE=QString("identity-type"), IDENT_FILE=QString("ident-file"), IGNORED_CHARS=QString("ignored-chars"), IMPLICIT=QString("implicit"), @@ -249,6 +260,7 @@ namespace ParsersAttributes { INTERNAL_LENGTH=QString("internal-length"), INTERVAL_TYPE=QString("interval-type"), INVERT_RANGESEL_TRIGGER=QString("invert-rangesel-trigger"), + IS_TEMPLATE=QString("is-template"), IO_CAST=QString("io-cast"), ITALIC=QString("italic"), JOIN_FUNC=QString("join"), @@ -293,6 +305,7 @@ namespace ParsersAttributes { NAMES=QString("names"), NEGATOR_OP=QString("negator-op"), NEW_NAME=QString("new-name"), + NEW_IDENTITY_TYPE=QString("new-identity-type"), NEW_VERSION=QString("new-version"), NN_COLUMN=QString("nn-column"), NO_INHERIT=QString("no-inherit"), @@ -340,6 +353,7 @@ namespace ParsersAttributes { PATTERNS=QString("patterns"), PER_ROW=QString("per-line"), PERMISSION=QString("permission"), + PERMISSIVE=QString("permissive"), PGMODELER_VERSION=QString("pgmodeler-ver"), PGSQL_BASE_TYPE=QString("basetype"), PGSQL_VERSION=QString("pgsql-ver"), @@ -379,6 +393,7 @@ namespace ParsersAttributes { REF_TYPE=QString("ref-type"), REFER=QString("refer"), REFERENCE=QString("reference"), + REFERENCE_FK=QString("reference-fk"), REFERENCES_PRIV=QString("references"), REFERENCES=QString("references"), REFERRERS=QString("referrers"), @@ -394,14 +409,20 @@ 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"), REVOKE=QString("revoke"), RIGHT_TYPE=QString("right-type"), RIGHT=QString("right"), + RLS_ENABLED=QString("rls-enabled"), + RLS_FORCED=QString("rls-forced"), ROLE_TYPE=QString("role-type"), ROLE=QString("role"), + ROLE_CURRENT_USER=QString("CURRENT_USER"), + ROLE_SESSION_USER=QString("SESSION_USER"), + ROLE_PUBLIC=QString("PUBLIC"), ROLES=QString("roles"), ROW_AMOUNT=QString("row-amount"), RULES=QString("rules"), @@ -411,6 +432,7 @@ namespace ParsersAttributes { SECURITY_TYPE=QString("security-type"), SELECT_EXP=QString("select-exp"), SELECT_PRIV=QString("select"), + SELECT_OBJECTS=QString("select-objects"), SEND_FUNC=QString("send"), SEQUENCE=QString("sequence"), SERVER_ENCODING=QString("server-encoding"), @@ -512,6 +534,7 @@ namespace ParsersAttributes { USE_PLACEHOLDERS=QString("use-placeholders"), USE_SORTING=QString("use-sorting"), USE_UNIQUE_NAMES=QString("use-unique-names"), + USING_EXP=QString("using-exp"), VALIDATOR_FUNC=QString("validator"), VALIDATOR=QString("validator"), VALIDITY=QString("validity"), diff --git a/libparsers/src/parsersattributes.h b/libparsers/src/parsersattributes.h index 0bcec7c19..c58b148a6 100644 --- a/libparsers/src/parsersattributes.h +++ b/libparsers/src/parsersattributes.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -46,6 +46,7 @@ namespace ParsersAttributes { ALIGNMENT, ALIGN_OBJS_TO_GRID, ALTER_CMDS, + ALLOW_CONNS, ANALYZE_FUNC, ANCESTOR_TABLE, APPEND_AT_EOD, @@ -72,6 +73,7 @@ namespace ParsersAttributes { BOTTOM, BUFFERING, BY_VALUE, + BYPASSRLS, CACHE, CANONICAL_FUNC, CANVAS_CORNER_MOVE, @@ -81,6 +83,7 @@ namespace ParsersAttributes { CATEGORY, CHANGE, CHANGELOG, + CHECK_EXP, CHECK_UPDATE, CK_CONSTR, CLIENT_ENCODING, @@ -95,9 +98,11 @@ namespace ParsersAttributes { COLOR, COLORS, COLS_COMMENT, + COL_IS_IDENTITY, COLUMN_ALIAS, COLUMN, COLUMNS, + COMMAND, COMMANDS, COMMENT, COMMUTATOR_OP, @@ -112,6 +117,7 @@ namespace ParsersAttributes { CONN_LIMIT, CONNECT_CENTER_PNTS, CONNECT_FK_TO_PK, + CONNECT_TABLE_EDGES, CONNECT_PRIV, CONNECTION, CONNECTIONS, @@ -130,12 +136,14 @@ namespace ParsersAttributes { CREATE, CREATEDB, CREATEROLE, + CROWS_FOOT, CTE_EXPRESSION, CUR_VERSION, CUSTOM_COLOR, CUSTOM_FILTER, CUSTOMIDXS, CYCLE, + DATABASE, DATA_DIRECTORY, DATE, DB_MODEL, @@ -163,6 +171,7 @@ namespace ParsersAttributes { DIRECTORY, DISABLE_SMOOTHNESS, DISPLAY_LINE_NUMBERS, + DOM_CONSTRAINT, DOCK_WIDGETS, DROP_CMDS, DROP, @@ -179,6 +188,7 @@ namespace ParsersAttributes { ELEMENTS, ENCODING, ENCRYPTED, + END_EXP, ENUM_TYPE, ENUMERATIONS, EVENT_TYPE, @@ -199,6 +209,7 @@ namespace ParsersAttributes { EXPRESSIONS, EXT_OBJ_OIDS, FACTOR, + FADEIN_OBJECTS, FADED_OUT, FAMILY, FAST_UPDATE, @@ -234,12 +245,12 @@ namespace ParsersAttributes { HIDE_REL_NAME, HIDE_TABLE_TAGS, HIGHLIGHT_LINES, - HIGHLIGHT_OBJECTS, HIGHLIGHT_ORDER, HISTORY_MAX_LENGTH, ICON, ID, IDENTIFIER, + IDENTITY_TYPE, IGNORED_CHARS, IMPLICIT, IMPORT, @@ -265,6 +276,7 @@ namespace ParsersAttributes { INTERVAL_TYPE, INVERT_RANGESEL_TRIGGER, IO_CAST, + IS_TEMPLATE, ITALIC, JOIN_FUNC, LABEL, @@ -308,6 +320,7 @@ namespace ParsersAttributes { NAMES, NEGATOR_OP, NEW_NAME, + NEW_IDENTITY_TYPE, NEW_VERSION, NN_COLUMN, NO_INHERIT, @@ -355,6 +368,7 @@ namespace ParsersAttributes { PATTERNS, PER_ROW, PERMISSION, + PERMISSIVE, PGMODELER_VERSION, PGSQL_BASE_TYPE, PGSQL_VERSION, @@ -394,6 +408,7 @@ namespace ParsersAttributes { REF_TYPE, REFER, REFERENCE, + REFERENCE_FK, REFERENCES_PRIV, REFERENCES, REFERRERS, @@ -408,6 +423,7 @@ namespace ParsersAttributes { RELATIONSHIP, RENAME, REPLICATION, + RESTART_SEQ, RESTRICTION_FUNC, RETURN_TABLE, RETURN_TYPE, @@ -415,6 +431,8 @@ namespace ParsersAttributes { REVOKE, RIGHT_TYPE, RIGHT, + RLS_ENABLED, + RLS_FORCED, ROLE_TYPE, ROLE, ROLES, @@ -426,6 +444,7 @@ namespace ParsersAttributes { SECURITY_TYPE, SELECT_EXP, SELECT_PRIV, + SELECT_OBJECTS, SEND_FUNC, SEQUENCE, SERVER_ENCODING, @@ -527,6 +546,7 @@ namespace ParsersAttributes { USE_PLACEHOLDERS, USE_SORTING, USE_UNIQUE_NAMES, + USING_EXP, VALIDATOR_FUNC, VALIDATOR, VALIDITY, diff --git a/libparsers/src/schemaparser.cpp b/libparsers/src/schemaparser.cpp index ba31c741c..3bb7248e9 100644 --- a/libparsers/src/schemaparser.cpp +++ b/libparsers/src/schemaparser.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libparsers/src/schemaparser.h b/libparsers/src/schemaparser.h index 0ef011392..13a2c1da9 100644 --- a/libparsers/src/schemaparser.h +++ b/libparsers/src/schemaparser.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libparsers/src/xmlparser.cpp b/libparsers/src/xmlparser.cpp index 76bf437a3..cb78d0f51 100644 --- a/libparsers/src/xmlparser.cpp +++ b/libparsers/src/xmlparser.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libparsers/src/xmlparser.h b/libparsers/src/xmlparser.h index 1a80c303e..fae743272 100644 --- a/libparsers/src/xmlparser.h +++ b/libparsers/src/xmlparser.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgconnector/src/catalog.cpp b/libpgconnector/src/catalog.cpp index b3e059f58..28b95fc86 100644 --- a/libpgconnector/src/catalog.cpp +++ b/libpgconnector/src/catalog.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -25,6 +25,7 @@ const QString Catalog::PGSQL_FALSE=QString("f"); const QString Catalog::BOOL_FIELD=QString("_bool"); const QString Catalog::ARRAY_PATTERN=QString("((\\[)[0-9]+(\\:)[0-9]+(\\])=)?(\\{)((.)+(,)*)*(\\})$"); const QString Catalog::GET_EXT_OBJS_SQL=QString("SELECT objid AS oid FROM pg_depend WHERE objid > 0 AND refobjid > 0 AND deptype='e'"); +const QString Catalog::PGMODELER_TEMP_DB_OBJ=QString("__pgmodeler_tmp"); bool Catalog::use_cached_queries=false; attribs_map Catalog::catalog_queries; @@ -37,15 +38,28 @@ map Catalog::oid_fields= {OBJ_CONVERSION, "cn.oid"}, {OBJ_CAST, "cs.oid"}, {OBJ_VIEW, "vw.oid"}, {OBJ_SEQUENCE, "sq.oid"}, {OBJ_DOMAIN, "dm.oid"}, {OBJ_TYPE, "tp.oid"}, {OBJ_TABLE, "tb.oid"}, {OBJ_COLUMN, "cl.oid"}, {OBJ_CONSTRAINT, "cs.oid"}, - {OBJ_RULE, "rl.oid"}, {OBJ_TRIGGER, "tg.oid"}, {OBJ_INDEX, "id.oid"}, - {OBJ_EVENT_TRIGGER, "et.oid"}, + {OBJ_RULE, "rl.oid"}, {OBJ_TRIGGER, "tg.oid"}, {OBJ_INDEX, "id.indexrelid"}, + {OBJ_EVENT_TRIGGER, "et.oid"}, {OBJ_POLICY, "pl.oid"} }; map Catalog::ext_oid_fields={ {OBJ_CONSTRAINT, "cs.conrelid"}, {OBJ_INDEX, "id.indexrelid"}, {OBJ_TRIGGER, "tg.tgrelid"}, - {OBJ_RULE, "rl.ev_class"} + {OBJ_RULE, "rl.ev_class"}, + {OBJ_POLICY, "pl.polrelid"} +}; + +map Catalog::name_fields= +{ {OBJ_DATABASE, "datname"}, {OBJ_ROLE, "rolname"}, {OBJ_SCHEMA,"nspname"}, + {OBJ_LANGUAGE, "lanname"}, {OBJ_TABLESPACE, "spcname"}, {OBJ_EXTENSION, "extname"}, + {OBJ_FUNCTION, "proname"}, {OBJ_AGGREGATE, "proname"}, {OBJ_OPERATOR, "oprname"}, + {OBJ_OPCLASS, "opcname"}, {OBJ_OPFAMILY, "opfname"}, {OBJ_COLLATION, "collname"}, + {OBJ_CONVERSION, "conname"}, {OBJ_CAST, ""}, {OBJ_VIEW, "relname"}, + {OBJ_SEQUENCE, "relname"}, {OBJ_DOMAIN, "typname"}, {OBJ_TYPE, "typname"}, + {OBJ_TABLE, "relname"}, {OBJ_COLUMN, "attname"}, {OBJ_CONSTRAINT, "conname"}, + {OBJ_RULE, "rulename"}, {OBJ_TRIGGER, "tgname"}, {OBJ_INDEX, "relname"}, + {OBJ_EVENT_TRIGGER, "evtname"}, {OBJ_POLICY, "polname"} }; Catalog::Catalog(void) @@ -131,6 +145,11 @@ unsigned Catalog::getLastSysObjectOID(void) return(last_sys_oid); } +bool Catalog::isSystemObject(unsigned oid) +{ + return(oid <= last_sys_oid); +} + bool Catalog::isExtensionObject(unsigned oid) { return(ext_obj_oids.contains(QString::number(oid))); @@ -161,6 +180,14 @@ QString Catalog::getCatalogQuery(const QString &qry_type, ObjectType obj_type, b { QString sql, custom_filter; + /* Escaping apostrophe (') in the attributes values to avoid SQL errors + * due to support to this char in the middle of objects' names */ + for(auto &attr : attribs) + { + if(attr.first != ParsersAttributes::CUSTOM_FILTER && attr.second.contains(QChar('\''))) + attr.second.replace(QChar('\''), QString("''")); + } + schparser.setPgSQLVersion(connection.getPgSQLVersion(true)); attribs[qry_type]=ParsersAttributes::_TRUE_; @@ -200,10 +227,15 @@ QString Catalog::getCatalogQuery(const QString &qry_type, ObjectType obj_type, b //Appeding the custom filter to the whole catalog query if(!custom_filter.isEmpty()) { + int order_by_idx = sql.indexOf(QString("ORDER BY"), 0, Qt::CaseInsensitive); + + if(order_by_idx < 0) + order_by_idx = sql.length(); + if(!sql.contains(QString("WHERE"), Qt::CaseInsensitive)) - sql+=QString(" WHERE "); + sql.insert(order_by_idx, QString(" WHERE ") + custom_filter); else - sql+=QString(" AND (%1)").arg(custom_filter); + sql.insert(order_by_idx, QString(" AND (%1) ").arg(custom_filter)); } //Append a LIMIT clause when the single_result is set @@ -446,12 +478,12 @@ vector Catalog::getMultipleAttributes(ObjectType obj_type, attribs_ QString Catalog::getCommentQuery(const QString &oid_field, bool is_shared_obj) { - QString query_id=QString("get") + ParsersAttributes::COMMENT; + QString query_id=ParsersAttributes::COMMENT; try { attribs_map attribs={{ParsersAttributes::OID, oid_field}, - {ParsersAttributes::SHARED_OBJ, (is_shared_obj ? ParsersAttributes::_TRUE_ : QString())}}; + {ParsersAttributes::SHARED_OBJ, (is_shared_obj ? ParsersAttributes::_TRUE_ : QString())}}; loadCatalogQuery(query_id); return(schparser.getCodeDefinition(attribs).simplified()); @@ -527,7 +559,7 @@ vector Catalog::getObjectsAttributes(ObjectType obj_type, const QSt try { bool is_shared_obj=(obj_type==OBJ_DATABASE || obj_type==OBJ_ROLE || obj_type==OBJ_TABLESPACE || - obj_type==OBJ_LANGUAGE || obj_type==OBJ_CAST); + obj_type==OBJ_LANGUAGE || obj_type==OBJ_CAST); extra_attribs[ParsersAttributes::SCHEMA]=schema; extra_attribs[ParsersAttributes::TABLE]=table; @@ -535,7 +567,8 @@ vector Catalog::getObjectsAttributes(ObjectType obj_type, const QSt if(!filter_oids.empty()) extra_attribs[ParsersAttributes::FILTER_OIDS]=createOidFilter(filter_oids); - if(!TableObject::isTableObject(obj_type)) + //Retrieve the comment catalog query. Only columns need to retreive comments in their own catalog query file + if(obj_type != OBJ_COLUMN) extra_attribs[ParsersAttributes::COMMENT]=getCommentQuery(oid_fields[obj_type], is_shared_obj); return(getMultipleAttributes(obj_type, extra_attribs)); @@ -561,6 +594,37 @@ attribs_map Catalog::getObjectAttributes(ObjectType obj_type, unsigned oid, cons } } +QString Catalog::getObjectOID(const QString &name, ObjectType obj_type, const QString &schema, const QString &table) +{ + try + { + attribs_map attribs; + ResultSet res; + + attribs[ParsersAttributes::CUSTOM_FILTER] = QString("%1 = E'%2'").arg(name_fields[obj_type]).arg(name); + attribs[ParsersAttributes::SCHEMA] = schema; + attribs[ParsersAttributes::TABLE] = table; + executeCatalogQuery(QUERY_LIST, obj_type, res, false, attribs); + + if(res.getTupleCount() > 1) + throw Exception(QApplication::translate("Catalog","The catalog query returned more than one OID!","", -1), + ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + else if(res.isEmpty()) + return("0"); + else + { + res.accessTuple(ResultSet::FIRST_TUPLE); + return(res.getColumnValue(ParsersAttributes::OID)); + } + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, + QApplication::translate("Catalog","Object type: %1","", -1).arg(BaseObject::getSchemaName(obj_type))); + } +} + attribs_map Catalog::getServerAttributes(void) { attribs_map attribs; diff --git a/libpgconnector/src/catalog.h b/libpgconnector/src/catalog.h index a33e4b74d..4b4501890 100644 --- a/libpgconnector/src/catalog.h +++ b/libpgconnector/src/catalog.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -57,6 +57,9 @@ class Catalog { composed by the pg_[OBJECT_TYPE] table alias. Refer to catalog query schema files for details */ static map oid_fields; + /*! \brief This map stores the name field for each object type. Refer to catalog query schema files for details */ + static map name_fields; + /*! \brief This map stores the oid field name that is used to check if the object (or its parent) is part of a extension (see getNotExtObjectQuery()). By default the attribute oid_fields is used instead for that purpose, but, for some objects, there are different fields that tells if the object (or its parent) is part of extension. */ @@ -125,6 +128,9 @@ class Catalog { Catalog(void); Catalog(const Catalog &catalog); + //! \brief Stores the prefix of any temp object (in pg_temp) created during catalog reading by pgModeler + static const QString PGMODELER_TEMP_DB_OBJ; + //! \brief Excludes the system objects from listing static const unsigned EXCL_SYSTEM_OBJS=1, @@ -155,6 +161,9 @@ class Catalog { //! \brief Returns the last system object oid registered on the database unsigned getLastSysObjectOID(void); + //! \brief Returns if the specified oid is amongst the system objects' oids + bool isSystemObject(unsigned oid); + //! \brief Returns if the specified oid is amongst the extension created objects' oids bool isExtensionObject(unsigned oid); @@ -187,6 +196,11 @@ class Catalog { //! \brief Returns the attributes for the object specified by its type and OID attribs_map getObjectAttributes(ObjectType obj_type, unsigned oid, const QString sch_name=QString(), const QString tab_name=QString(), attribs_map extra_attribs=attribs_map()); + /*! \brief Returns the OID of the named object. User can filter items by schema (if the object type is suitable to accept schema) + and by table name (only when retriving child objects for a specific table). The method will raise an exception if the catalog query + used returns more than one result. A zero OID is returned when no suitable object is found. */ + QString getObjectOID(const QString &name, ObjectType obj_type, const QString &schema = QString(), const QString &table = QString()); + //! brief This special method returns some server's attributes read from pg_settings attribs_map getServerAttributes(void); diff --git a/libpgconnector/src/connection.cpp b/libpgconnector/src/connection.cpp index 349d6c9db..c284c83ac 100644 --- a/libpgconnector/src/connection.cpp +++ b/libpgconnector/src/connection.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -120,36 +120,39 @@ void Connection::setAutoBrowseDB(bool value) void Connection::generateConnectionString(void) { - attribs_map::iterator itr; - QString value; - - itr=connection_params.begin(); + QString value, param_str = QString("%1=%2 "); //Scans the parameter map concatening the params (itr->first) / values (itr->second) - connection_str=QString(); - while(itr!=connection_params.end()) + connection_str.clear(); + + for(auto &itr : connection_params) { - if(itr->first!=PARAM_ALIAS) + if(itr.first!=PARAM_ALIAS) { - value=itr->second; + value=itr.second; value.replace("\\","\\\\"); value.replace("'","\\'"); - if(itr->first==PARAM_PASSWORD && (value.contains(' ') || value.isEmpty())) + if(itr.first==PARAM_PASSWORD && (value.contains(' ') || value.isEmpty())) value=QString("'%1'").arg(value); if(!value.isEmpty()) { - if(itr->first!=PARAM_OTHERS) - connection_str+=itr->first + "=" + value + " "; + if(itr.first==PARAM_DB_NAME) + connection_str.prepend(param_str.arg(itr.first).arg(value)); + else if(itr.first!=PARAM_OTHERS) + connection_str+=param_str.arg(itr.first).arg(value); else connection_str+=value; } } - - itr++; } + + if(!connection_str.contains(PARAM_DB_NAME) || + (!connection_str.contains(PARAM_SERVER_FQDN) && + !connection_str.contains(PARAM_SERVER_IP))) + connection_str.clear(); } void Connection::noticeProcessor(void *, const char *message) @@ -306,20 +309,26 @@ QString Connection::getConnectionString(void) QString Connection::getConnectionId(bool host_port_only, bool incl_db_name) { - QString addr, db_name; + QString addr, db_name, port; + + if(!isConfigured()) + return(QString()); if(!connection_params[PARAM_SERVER_FQDN].isEmpty()) addr=connection_params[PARAM_SERVER_FQDN]; else addr=connection_params[PARAM_SERVER_IP]; + if(!connection_params[PARAM_PORT].isEmpty()) + port = QString(":%1").arg(connection_params[PARAM_PORT]); + if(incl_db_name) db_name = QString("%1@").arg(connection_params[PARAM_DB_NAME]); if(host_port_only) - return(QString("%1%2:%3").arg(db_name, addr, connection_params[PARAM_PORT])); + return(QString("%1%2%3").arg(db_name, addr, port)); else - return(QString("%1%2 (%3:%4)").arg(db_name, connection_params[PARAM_ALIAS], addr, connection_params[PARAM_PORT])); + return(QString("%1%2 (%3%4)").arg(db_name, connection_params[PARAM_ALIAS], addr, port)); } bool Connection::isStablished(void) @@ -327,6 +336,11 @@ bool Connection::isStablished(void) return(connection!=nullptr); } +bool Connection::isConfigured(void) +{ + return(!connection_str.isEmpty()); +} + bool Connection::isAutoBrowseDB(void) { return(auto_browse_db); @@ -344,12 +358,13 @@ QString Connection::getPgSQLVersion(bool major_only) //If the version is 10+ if(raw_ver.contains(QRegExp("^((1)[0-9])(.)+"))) { + //New PostgreSQL 10+ versioning: 100001 means 10.1 (Major.Minor) fmt_ver=QString("%1.%2") .arg(raw_ver.mid(0,2)) - .arg(raw_ver.mid(2,2).toInt()/10); + .arg(raw_ver.mid(3,1).toInt()); if(!major_only) - return(QString("%1.%2").arg(fmt_ver).arg(raw_ver.mid(5,1))); + return(QString("%1.%2").arg(raw_ver.mid(0,2)).arg(raw_ver.mid(4,2).toInt())); } //For versions below or equal to 9.6 else diff --git a/libpgconnector/src/connection.h b/libpgconnector/src/connection.h index 019922ce7..40016e235 100644 --- a/libpgconnector/src/connection.h +++ b/libpgconnector/src/connection.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -208,9 +208,12 @@ class Connection { raise an exception and switch back to the previous database. */ void switchToDatabase(const QString &dbname); - //! \brief Returns if the connections is stablished + //! \brief Returns if the connection is stablished bool isStablished(void); + //! \brief Returns if the connection is configured (has some attributes set) + bool isConfigured(void); + //! \brief Returns if the db configured in the connection can be automatically browsed in SQLTool bool isAutoBrowseDB(void); diff --git a/libpgconnector/src/resultset.cpp b/libpgconnector/src/resultset.cpp index 6f64940ee..81dac934c 100644 --- a/libpgconnector/src/resultset.cpp +++ b/libpgconnector/src/resultset.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -119,10 +119,8 @@ int ResultSet::getColumnIndex(const QString &column_name) return(col_idx); } -char *ResultSet::getColumnValue(const QString &column_name) +int ResultSet::validateColumnName(const QString &column_name) { - int col_idx=-1; - try { /* Raises an error if the user try to get the value of a column in @@ -134,19 +132,22 @@ char *ResultSet::getColumnValue(const QString &column_name) throw Exception(ERR_REF_INV_TUPLE_COLUMN, __PRETTY_FUNCTION__, __FILE__, __LINE__); //Get the column index through its name - col_idx=getColumnIndex(column_name); + return (getColumnIndex(column_name)); } catch(Exception &e) { //Capture and redirect any generated exception throw Exception(e.getErrorMessage(), e.getErrorType(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); } +} +char *ResultSet::getColumnValue(const QString &column_name) +{ //Returns the column value on the current tuple - return(PQgetvalue(sql_result, current_tuple, col_idx)); + return(PQgetvalue(sql_result, current_tuple, validateColumnName(column_name))); } -char *ResultSet::getColumnValue(int column_idx) +void ResultSet::validateColumnIndex(int column_idx) { //Raise an error in case the column index is invalid if(column_idx < 0 || column_idx >= getColumnCount()) @@ -158,36 +159,34 @@ char *ResultSet::getColumnValue(int column_idx) throw Exception(ERR_REF_TUPLE_INEXISTENT, __PRETTY_FUNCTION__, __FILE__, __LINE__); else if(current_tuple < 0 || current_tuple >= getTupleCount()) throw Exception(ERR_REF_INV_TUPLE_COLUMN, __PRETTY_FUNCTION__, __FILE__, __LINE__); +} + +char *ResultSet::getColumnValue(int column_idx) +{ + validateColumnIndex(column_idx); //Returns the column value on the current tuple return(PQgetvalue(sql_result, current_tuple, column_idx)); } -int ResultSet::getColumnSize(const QString &column_name) +bool ResultSet::isColumnValueNull(int column_idx) { - int col_idx=-1; + validateColumnIndex(column_idx); - try - { - /* Raises an error if the user try to get the value of a column in - a tuple of an empty result or generated from an INSERT, DELETE, UPDATE, - that is, which command do not return lines but only do updates or removal */ - if(getTupleCount()==0 || empty_result) - throw Exception(ERR_REF_TUPLE_INEXISTENT, __PRETTY_FUNCTION__, __FILE__, __LINE__); - else if(current_tuple < 0 || current_tuple >= getTupleCount()) - throw Exception(ERR_REF_INV_TUPLE_COLUMN, __PRETTY_FUNCTION__, __FILE__, __LINE__); + //Returns the null state of the column on the current tuple + return(PQgetisnull(sql_result, current_tuple, column_idx)); +} - //Get the column index wich length must be detected - col_idx=getColumnIndex(column_name); - } - catch(Exception &e) - { - //Capture and redirect any generated exception - throw Exception(e.getErrorMessage(), e.getErrorType(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); - } +bool ResultSet::isColumnValueNull(const QString &column_name) +{ + //Returns the null state of the column on the current tuple + return(PQgetisnull(sql_result, current_tuple, validateColumnName(column_name))); +} +int ResultSet::getColumnSize(const QString &column_name) +{ //Returns the column value length on the current tuple - return(PQgetlength(sql_result, current_tuple, col_idx)); + return(PQgetlength(sql_result, current_tuple, validateColumnName(column_name))); } int ResultSet::getColumnSize(int column_idx) diff --git a/libpgconnector/src/resultset.h b/libpgconnector/src/resultset.h index dfe2b308b..d07ad541e 100644 --- a/libpgconnector/src/resultset.h +++ b/libpgconnector/src/resultset.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -48,6 +48,10 @@ class ResultSet { void destroyResultSet(void); + void validateColumnIndex(int column_idx); + + int validateColumnName(const QString &column_name); + protected: //! \brief Stores the current tuple index, just for navigation int current_tuple; @@ -108,6 +112,10 @@ class ResultSet { bool isColumnBinaryFormat(const QString &column_name); bool isColumnBinaryFormat(int column_idx); + //! \brief Informs if the column has a null value. In PostgreSQL null =/= empty + bool isColumnValueNull(int column_idx); + bool isColumnValueNull(const QString &column_name); + //! \brief Access on tuple on result set via navigation constants bool accessTuple(unsigned tuple_type); diff --git a/libpgmodeler/libpgmodeler.pro b/libpgmodeler/libpgmodeler.pro index 07aea9828..96a255a38 100644 --- a/libpgmodeler/libpgmodeler.pro +++ b/libpgmodeler/libpgmodeler.pro @@ -59,7 +59,8 @@ HEADERS += src/textbox.h \ src/pgmodelerns.h \ src/tag.h \ src/eventtrigger.h \ - src/genericsql.h + src/genericsql.h \ + src/policy.h SOURCES += src/textbox.cpp \ src/domain.cpp \ @@ -107,7 +108,8 @@ SOURCES += src/textbox.cpp \ src/tag.cpp \ src/eventtrigger.cpp \ src/operation.cpp \ - src/genericsql.cpp + src/genericsql.cpp \ + src/policy.cpp unix|windows: LIBS += -L$$OUT_PWD/../libparsers/ -lparsers \ -L$$OUT_PWD/../libutils/ -lutils diff --git a/libpgmodeler/src/aggregate.cpp b/libpgmodeler/src/aggregate.cpp index 2f7ebc097..6f8112037 100644 --- a/libpgmodeler/src/aggregate.cpp +++ b/libpgmodeler/src/aggregate.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -153,7 +153,7 @@ void Aggregate::setTypesAttribute(unsigned def_type) /* Case none data type is specified for the aggregate creates an aggregate that accepts any possible data '*' e.g. function(*) */ - if(str_types.isEmpty()) str_types='*'; + if(def_type == SchemaParser::SQL_DEFINITION && str_types.isEmpty()) str_types='*'; attributes[ParsersAttributes::TYPES]=str_types; } diff --git a/libpgmodeler/src/aggregate.h b/libpgmodeler/src/aggregate.h index ceaade596..3bb5b59a1 100644 --- a/libpgmodeler/src/aggregate.h +++ b/libpgmodeler/src/aggregate.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/basegraphicobject.cpp b/libpgmodeler/src/basegraphicobject.cpp index 5758ca50c..ca626a5a3 100644 --- a/libpgmodeler/src/basegraphicobject.cpp +++ b/libpgmodeler/src/basegraphicobject.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/basegraphicobject.h b/libpgmodeler/src/basegraphicobject.h index 671b1d98a..f0d9440fb 100644 --- a/libpgmodeler/src/basegraphicobject.h +++ b/libpgmodeler/src/basegraphicobject.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/baseobject.cpp b/libpgmodeler/src/baseobject.cpp index e89deadba..62b1aa10d 100644 --- a/libpgmodeler/src/baseobject.cpp +++ b/libpgmodeler/src/baseobject.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -20,6 +20,8 @@ #include "pgmodelerns.h" #include +const QByteArray BaseObject::special_chars = QByteArray("'_-.@ $:()/<>+*\\=~!#%^&|?{}[]`;"); + /* CAUTION: If both amount and order of the enumerations are modified then the order and amount of the elements of this vector must also be modified */ @@ -30,7 +32,7 @@ QString BaseObject::objs_schemas[OBJECT_TYPE_COUNT]={ "sequence", "role", "conversion", "cast", "language", "usertype", "tablespace", "opfamily", "opclass", "database","collation", - "extension", "eventtrigger", "relationship", + "extension", "eventtrigger", "policy", "relationship", "textbox", "permission", "parameter", "typeattribute", "tag", "genericsql", "relationship" }; @@ -44,9 +46,9 @@ QString BaseObject::obj_type_names[OBJECT_TYPE_COUNT]={ QT_TR_NOOP("Cast"), QT_TR_NOOP("Language"), QT_TR_NOOP("Type"), QT_TR_NOOP("Tablespace"), QT_TR_NOOP("Operator Family"), QT_TR_NOOP("Operator Class"), QT_TR_NOOP("Database"), QT_TR_NOOP("Collation"), QT_TR_NOOP("Extension"), - QT_TR_NOOP("Event Trigger"), QT_TR_NOOP("Relationship"), QT_TR_NOOP("Textbox"), - QT_TR_NOOP("Permission"), QT_TR_NOOP("Parameter"), QT_TR_NOOP("Type Attribute"), - QT_TR_NOOP("Tag"), QT_TR_NOOP("Generic SQL"), QT_TR_NOOP("Basic Relationship") + QT_TR_NOOP("Event Trigger"), QT_TR_NOOP("Policy"), QT_TR_NOOP("Relationship"), + QT_TR_NOOP("Textbox"), QT_TR_NOOP("Permission"), QT_TR_NOOP("Parameter"), QT_TR_NOOP("Type Attribute"), + QT_TR_NOOP("Tag"), QT_TR_NOOP("Generic SQL"), QT_TR_NOOP("Basic Relationship") }; QString BaseObject::objs_sql[OBJECT_TYPE_COUNT]={ @@ -56,7 +58,7 @@ QString BaseObject::objs_sql[OBJECT_TYPE_COUNT]={ QString("OPERATOR"), QString("SEQUENCE"), QString("ROLE"), QString("CONVERSION"), QString("CAST"), QString("LANGUAGE"), QString("TYPE"), QString("TABLESPACE"), QString("OPERATOR FAMILY"), QString("OPERATOR CLASS"), QString("DATABASE"), - QString("COLLATION"), QString("EXTENSION"), QString("EVENT TRIGGER") + QString("COLLATION"), QString("EXTENSION"), QString("EVENT TRIGGER"), QString("POLICY") }; /* Initializes the global id which is shared between instances @@ -159,26 +161,18 @@ QString BaseObject::formatName(const QString &name, bool is_operator) if(!is_formated && (is_operator || isValidName(name))) { bool needs_fmt=false; - unsigned i, qtd; + unsigned i = 0, qtd = 0; raw_name.append(name); /* Checks if the name has some upper case letter. If its the case the name will be enclosed in quotes */ - qtd=name.size(); - needs_fmt=(!is_operator && - (name.indexOf('-')>=0 || - name.indexOf('.')>=0 || - name.indexOf('@')>=0 || - name.indexOf(' ')>=0 || - name.indexOf('$')>=0 || - name.indexOf(':')>=0 || - name.indexOf('(')>=0 || - name.indexOf(')')>=0 || - name.indexOf('/')>=0 || - name.indexOf('\\')>=0 || - name.contains(QRegExp("^[0-9]+")))); + needs_fmt = (!is_operator && name.contains(QRegExp("^[0-9]+"))); + for(int idx = 0; idx < special_chars.size() && !needs_fmt; idx++) + needs_fmt = (!is_operator && special_chars.at(idx) != '_' && name.indexOf(special_chars.at(idx)) >= 0); + + qtd=name.size(); i=0; while(i < qtd && !needs_fmt) { @@ -234,7 +228,6 @@ QString BaseObject::formatName(const QString &name, bool is_operator) bool BaseObject::isValidName(const QString &name) { QString aux_name=name; - QByteArray special_chars=QByteArray("_-.@ $:()/\\"); if(aux_name.contains(QRegExp("^(\")(.)+(\")$"))) { @@ -275,7 +268,7 @@ bool BaseObject::isValidName(const QString &name) chr=raw_name[i]; /* Validation of simple ASCI characters. - Checks if the name has the characters in the set [ a-z A-Z 0-9 _ . @ $ - : space ()] */ + Checks if the name has the characters in the set [ a-z A-Z 0-9 _ . @ $ - : space () <>] */ if((chr >= 'a' && chr <='z') || (chr >= 'A' && chr <='Z') || (chr >= '0' && chr <='9') || special_chars.contains(chr)) { @@ -450,7 +443,7 @@ bool BaseObject::acceptsAlterCommand(ObjectType obj_type) obj_type==OBJ_INDEX || obj_type==OBJ_ROLE || obj_type==OBJ_SCHEMA || obj_type==OBJ_SEQUENCE || obj_type==OBJ_TABLE || obj_type==OBJ_TABLESPACE || - obj_type==OBJ_TYPE); + obj_type==OBJ_TYPE || obj_type==OBJ_POLICY); } bool BaseObject::acceptsDropCommand(ObjectType obj_type) @@ -753,16 +746,10 @@ QString BaseObject::getCodeDefinition(unsigned def_type, bool reduced_form) else attributes[ParsersAttributes::COMMENT]=comment; - if((def_type==SchemaParser::SQL_DEFINITION && - obj_type!=OBJ_TABLESPACE && - obj_type!=OBJ_DATABASE) || - def_type==SchemaParser::XML_DEFINITION) - { - schparser.ignoreUnkownAttributes(true); + schparser.ignoreUnkownAttributes(true); - attributes[ParsersAttributes::COMMENT]= - schparser.getCodeDefinition(ParsersAttributes::COMMENT, attributes, def_type); - } + attributes[ParsersAttributes::COMMENT]= + schparser.getCodeDefinition(ParsersAttributes::COMMENT, attributes, def_type); } if(!appended_sql.isEmpty()) @@ -937,6 +924,7 @@ vector BaseObject::getObjectTypes(bool inc_table_objs, vector BaseObject::getObjectTypes(bool inc_table_objs, vector BaseObject::getChildObjectTypes(ObjectType obj_type) { if(obj_type==OBJ_DATABASE) - return(vector()={OBJ_CAST, OBJ_ROLE, OBJ_LANGUAGE, OBJ_TABLESPACE, OBJ_SCHEMA, OBJ_EVENT_TRIGGER}); + return(vector()={OBJ_CAST, OBJ_ROLE, OBJ_LANGUAGE, OBJ_TABLESPACE, OBJ_SCHEMA, OBJ_EXTENSION, OBJ_EVENT_TRIGGER}); else if(obj_type==OBJ_SCHEMA) - return(vector()={OBJ_AGGREGATE, OBJ_CONVERSION, OBJ_COLLATION, OBJ_DOMAIN, OBJ_EXTENSION, OBJ_FUNCTION, + return(vector()={OBJ_AGGREGATE, OBJ_CONVERSION, OBJ_COLLATION, OBJ_DOMAIN, OBJ_FUNCTION, OBJ_OPCLASS, OBJ_OPERATOR, OBJ_OPFAMILY, OBJ_SEQUENCE, OBJ_TYPE, OBJ_TABLE, OBJ_VIEW}); else if(obj_type==OBJ_TABLE) - return(vector()={OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_RULE, OBJ_TRIGGER, OBJ_INDEX}); + return(vector()={OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_RULE, OBJ_TRIGGER, OBJ_INDEX, OBJ_POLICY}); else if(obj_type==OBJ_VIEW) return(vector()={OBJ_RULE, OBJ_TRIGGER, OBJ_INDEX}); else diff --git a/libpgmodeler/src/baseobject.h b/libpgmodeler/src/baseobject.h index c51ed4bf0..910fcde30 100644 --- a/libpgmodeler/src/baseobject.h +++ b/libpgmodeler/src/baseobject.h @@ -1,6 +1,6 @@ /* # PostgreSQL Database Modeler (pgModeler) -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -61,6 +61,7 @@ enum ObjectType { OBJ_COLLATION, OBJ_EXTENSION, OBJ_EVENT_TRIGGER, + OBJ_POLICY, OBJ_RELATIONSHIP, OBJ_TEXTBOX, OBJ_PERMISSION, @@ -84,6 +85,9 @@ class BaseObject { //! \brief Stores the database wich the object belongs BaseObject *database; + //! \brief Stores the set of special (valid) chars that forces the object's name quoting + static const QByteArray special_chars; + protected: SchemaParser schparser; @@ -101,7 +105,7 @@ class BaseObject { unsigned object_id; //! \brief Objects type count declared on enum ObjectType - static const int OBJECT_TYPE_COUNT=36; + static const int OBJECT_TYPE_COUNT=37; /*! \brief Indicates whether the object is protected or not. A protected object indicates that it can not suffer changes in position diff --git a/libpgmodeler/src/baserelationship.cpp b/libpgmodeler/src/baserelationship.cpp index fcf33612f..45d88161f 100644 --- a/libpgmodeler/src/baserelationship.cpp +++ b/libpgmodeler/src/baserelationship.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -32,10 +32,10 @@ BaseRelationship::BaseRelationship(BaseRelationship *rel) (*(this))=(*rel); custom_color=QColor(Qt::transparent); + reference_fk = nullptr; } -BaseRelationship::BaseRelationship(unsigned rel_type, BaseTable *src_tab, BaseTable *dst_tab, - bool src_mandatory, bool dst_mandatory) +BaseRelationship::BaseRelationship(unsigned rel_type, BaseTable *src_tab, BaseTable *dst_tab, bool src_mandatory, bool dst_mandatory) { try @@ -49,6 +49,7 @@ BaseRelationship::BaseRelationship(unsigned rel_type, BaseTable *src_tab, BaseTa this->dst_table=dst_tab; this->rel_type=rel_type; this->custom_color=QColor(Qt::transparent); + this->reference_fk=nullptr; for(unsigned i=0; i < 3; i++) { @@ -112,6 +113,7 @@ void BaseRelationship::configureRelationship(void) attributes[ParsersAttributes::UPD_ACTION]=QString(); attributes[ParsersAttributes::DEL_ACTION]=QString(); attributes[ParsersAttributes::CUSTOM_COLOR]=QString(); + attributes[ParsersAttributes::REFERENCE_FK]=QString(); //Check if the relationship type is valid if(rel_type <= RELATIONSHIP_FK) @@ -224,20 +226,13 @@ void BaseRelationship::setMandatoryTable(unsigned table_id, bool value) } else if(rel_type==RELATIONSHIP_FK) { - /* If the relationship isn't bidirectinal is necessary to check where to put - the 'n' descriptor. The 'n' label is put on the table where the foreign key resides. */ - if(!isBidirectional()) - { - if((table_id==SRC_TABLE && dynamic_cast
(src_table)->isReferTableOnForeignKey(dynamic_cast
(dst_table))) || - (!isSelfRelationship() && table_id==DST_TABLE && dynamic_cast
(dst_table)->isReferTableOnForeignKey(dynamic_cast
(src_table)))) - aux=QString("n"); - else - aux=QString("1"); - - lables[label_id]->setComment(aux); - } + if((table_id==SRC_TABLE && dynamic_cast
(src_table)->isReferTableOnForeignKey(dynamic_cast
(dst_table))) || + (!isSelfRelationship() && table_id==DST_TABLE && dynamic_cast
(dst_table)->isReferTableOnForeignKey(dynamic_cast
(src_table)))) + aux=QString("n"); else - lables[label_id]->setComment(QString("1:n")); + aux=QString("1"); + + lables[label_id]->setComment(aux); } else if(rel_type==RELATIONSHIP_NN) lables[label_id]->setComment(QString("n")); @@ -323,20 +318,6 @@ bool BaseRelationship::isSelfRelationship(void) return(dst_table==src_table); } -bool BaseRelationship::isBidirectional(void) -{ - if(rel_type!=RELATIONSHIP_FK || isSelfRelationship()) - return(false); - else - { - Table *src_tab=dynamic_cast
(src_table), - *dst_tab=dynamic_cast
(dst_table); - - return(src_tab->isReferTableOnForeignKey(dst_tab) && - dst_tab->isReferTableOnForeignKey(src_tab)); - } -} - void BaseRelationship::setRelationshipAttributes(void) { unsigned count, i; @@ -381,6 +362,7 @@ void BaseRelationship::setRelationshipAttributes(void) attributes[ParsersAttributes::LABELS_POS]=str_aux; attributes[ParsersAttributes::CUSTOM_COLOR]=(custom_color!=Qt::transparent ? custom_color.name() : QString()); + attributes[ParsersAttributes::REFERENCE_FK]=(reference_fk ? reference_fk->getName() : QString()); setFadedOutAttribute(); } @@ -399,6 +381,19 @@ QString BaseRelationship::getCachedCode(unsigned def_type) return(QString()); } +void BaseRelationship::setReferenceForeignKey(Constraint *ref_fk) +{ + //if(ref_fk && rel_type != RELATIONSHIP_FK) + //Throw error... + + this->reference_fk = ref_fk; +} + +Constraint *BaseRelationship::getReferenceForeignKey(void) +{ + return(reference_fk); +} + QString BaseRelationship::getCodeDefinition(unsigned def_type) { QString code_def=getCachedCode(def_type); @@ -410,19 +405,8 @@ QString BaseRelationship::getCodeDefinition(unsigned def_type) return(QString()); else { - QString sql_code; - vector fks; - - dynamic_cast
(src_table)->getForeignKeys(fks, false, dynamic_cast
(dst_table)); - - while(!fks.empty()) - { - sql_code+=fks.back()->getCodeDefinition(SchemaParser::SQL_DEFINITION); - fks.pop_back(); - } - - cached_code[def_type]=sql_code; - return(sql_code); + cached_code[def_type] = reference_fk->getCodeDefinition(SchemaParser::SQL_DEFINITION); + return(cached_code[def_type]); } } else diff --git a/libpgmodeler/src/baserelationship.h b/libpgmodeler/src/baserelationship.h index c8fc75145..d26cee1e7 100644 --- a/libpgmodeler/src/baserelationship.h +++ b/libpgmodeler/src/baserelationship.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,6 +34,9 @@ class BaseRelationship: public BaseGraphicObject { protected: + //! \brief This attribute stores the foreign key used to generate the relationship (only for FK relationships) + Constraint *reference_fk; + //! \brief This attribute overrides the default color configuration for relationship line and descriptor QColor custom_color; @@ -85,6 +88,10 @@ class BaseRelationship: public BaseGraphicObject { virtual QString getDropDefinition(bool) final { return(""); } + protected: + void setReferenceForeignKey(Constraint *reference_fk); + Constraint *getReferenceForeignKey(void); + public: //! \brief Constants used to assign the type to relationship static const unsigned RELATIONSHIP_11=10, //! \brief One to one @@ -105,8 +112,7 @@ class BaseRelationship: public BaseGraphicObject { BaseRelationship(BaseRelationship *rel); - BaseRelationship(unsigned rel_type, BaseTable *src_tab, BaseTable *dst_tab, - bool dst_mandatory, bool src_mandatory); + BaseRelationship(unsigned rel_type, BaseTable *src_tab, BaseTable *dst_tab, bool dst_mandatory, bool src_mandatory); ~BaseRelationship(void); @@ -138,10 +144,6 @@ class BaseRelationship: public BaseGraphicObject { //! \brief Returns whether the table is linked to itself via relationship (self-relationship) bool isSelfRelationship(void); - /*! \brief Returns whether the envolved tables references each other. This method can return - true only for FK relationships, for the other types this method always returns false */ - bool isBidirectional(void); - //! \brief Stores the points that defines the custom relationship line void setPoints(const vector &points); @@ -170,6 +172,8 @@ class BaseRelationship: public BaseGraphicObject { virtual QString getAlterDefinition(BaseObject *) { return(""); } friend class DatabaseModel; + friend class RelationshipWidget; + friend class ModelWidget; }; #endif diff --git a/libpgmodeler/src/basetable.cpp b/libpgmodeler/src/basetable.cpp index 1b1bb28ec..4a796acf7 100644 --- a/libpgmodeler/src/basetable.cpp +++ b/libpgmodeler/src/basetable.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/basetable.h b/libpgmodeler/src/basetable.h index 991836142..7f4a46515 100644 --- a/libpgmodeler/src/basetable.h +++ b/libpgmodeler/src/basetable.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/cast.cpp b/libpgmodeler/src/cast.cpp index 313c13f04..906c35092 100644 --- a/libpgmodeler/src/cast.cpp +++ b/libpgmodeler/src/cast.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/cast.h b/libpgmodeler/src/cast.h index 75c2b3368..7658f8214 100644 --- a/libpgmodeler/src/cast.h +++ b/libpgmodeler/src/cast.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/collation.cpp b/libpgmodeler/src/collation.cpp index a2a31c234..fe1870fb2 100644 --- a/libpgmodeler/src/collation.cpp +++ b/libpgmodeler/src/collation.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/collation.h b/libpgmodeler/src/collation.h index a0d4355f0..3551a12c6 100644 --- a/libpgmodeler/src/collation.h +++ b/libpgmodeler/src/collation.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/column.cpp b/libpgmodeler/src/column.cpp index 854ecf4bb..dc2a7defe 100644 --- a/libpgmodeler/src/column.cpp +++ b/libpgmodeler/src/column.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -28,7 +28,9 @@ Column::Column(void) attributes[ParsersAttributes::TABLE]=QString(); attributes[ParsersAttributes::SEQUENCE]=QString(); attributes[ParsersAttributes::DECL_IN_TABLE]=QString(); + attributes[ParsersAttributes::IDENTITY_TYPE]=QString(); parent_rel=sequence=nullptr; + identity_type=BaseType::null; } void Column::setName(const QString &name) @@ -58,16 +60,40 @@ void Column::setType(PgSQLType type) //An error is raised if the column receive a pseudo-type as data type. if(type.isPseudoType()) throw Exception(ERR_ASG_PSDTYPE_COLUMN,__PRETTY_FUNCTION__,__FILE__,__LINE__); + else if(this->identity_type != BaseType::null && !type.isIntegerType()) + { + throw Exception(Exception::getErrorMessage(ERR_INV_IDENTITY_COLUMN).arg(getSignature()), + ERR_INV_IDENTITY_COLUMN, __PRETTY_FUNCTION__, __FILE__, __LINE__); + } setCodeInvalidated(this->type != type); this->type=type; } +void Column::setIdentityType(IdentityType id_type) +{ + if(id_type != BaseType::null && !type.isIntegerType()) + { + throw Exception(Exception::getErrorMessage(ERR_INV_IDENTITY_COLUMN).arg(getSignature()), + ERR_INV_IDENTITY_COLUMN, __PRETTY_FUNCTION__, __FILE__, __LINE__); + } + + setCodeInvalidated(identity_type != id_type); + identity_type = id_type; + default_value.clear(); + sequence = nullptr; + + //Identity column implies NOT NULL constraint + if(id_type != BaseType::null) + setNotNull(true); +} + void Column::setDefaultValue(const QString &value) { setCodeInvalidated(default_value != value); default_value=value.trimmed(); sequence=nullptr; + identity_type=BaseType::null; } void Column::setNotNull(bool value) @@ -81,11 +107,21 @@ PgSQLType Column::getType(void) return(type); } +IdentityType Column::getIdentityType(void) +{ + return(identity_type); +} + bool Column::isNotNull(void) { return(not_null); } +bool Column::isIdentity(void) +{ + return(identity_type != BaseType::null); +} + QString Column::getTypeReference(void) { if(getParentTable()) @@ -129,7 +165,7 @@ void Column::setSequence(BaseObject *seq) .arg(this->obj_name) .arg(this->getTypeName()) .arg(BaseObject::getTypeName(OBJ_SEQUENCE)), - ERR_INCOMP_COL_TYPE_FOR_SEQ,__PRETTY_FUNCTION__,__FILE__,__LINE__); + ERR_ASG_INV_OBJECT_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); else if(!type.isIntegerType()) throw Exception(Exception::getErrorMessage(ERR_INCOMP_COL_TYPE_FOR_SEQ) .arg(seq->getName(true)) @@ -137,6 +173,7 @@ void Column::setSequence(BaseObject *seq) ERR_INCOMP_COL_TYPE_FOR_SEQ,__PRETTY_FUNCTION__,__FILE__,__LINE__); default_value=QString(); + identity_type=BaseType::null; } setCodeInvalidated(sequence != seq); @@ -156,19 +193,24 @@ QString Column::getCodeDefinition(unsigned def_type) if(getParentTable()) attributes[ParsersAttributes::TABLE]=getParentTable()->getName(true); - attributes[ParsersAttributes::TYPE]=type.getCodeDefinition(def_type); - + attributes[ParsersAttributes::TYPE]=type.getCodeDefinition(def_type); attributes[ParsersAttributes::DEFAULT_VALUE]=QString(); + attributes[ParsersAttributes::IDENTITY_TYPE]=QString(); - if(!sequence) - attributes[ParsersAttributes::DEFAULT_VALUE]=default_value; + if(identity_type != BaseType::null) + attributes[ParsersAttributes::IDENTITY_TYPE] = ~identity_type; else { - //Configuring the default value of the column to get the next value of the sequence - if(def_type==SchemaParser::SQL_DEFINITION) - attributes[ParsersAttributes::DEFAULT_VALUE]=QString("nextval('%1'::regclass)").arg(sequence->getSignature());//.remove("\"")); + if(!sequence) + attributes[ParsersAttributes::DEFAULT_VALUE]=default_value; + else + { + //Configuring the default value of the column to get the next value of the sequence + if(def_type==SchemaParser::SQL_DEFINITION) + attributes[ParsersAttributes::DEFAULT_VALUE]=QString("nextval('%1'::regclass)").arg(sequence->getSignature());//.remove("\"")); - attributes[ParsersAttributes::SEQUENCE]=sequence->getName(true); + attributes[ParsersAttributes::SEQUENCE]=sequence->getName(true); + } } attributes[ParsersAttributes::NOT_NULL]=(!not_null ? QString() : ParsersAttributes::_TRUE_); @@ -211,6 +253,16 @@ QString Column::getAlterDefinition(BaseObject *object) if(this->not_null!=col->not_null) attribs[ParsersAttributes::NOT_NULL]=(!col->not_null ? ParsersAttributes::UNSET : ParsersAttributes::_TRUE_); + attribs[ParsersAttributes::NEW_IDENTITY_TYPE] = QString(); + + if(this->identity_type == BaseType::null && col->identity_type != BaseType::null) + attribs[ParsersAttributes::IDENTITY_TYPE] = ~col->identity_type; + else if(this->identity_type != BaseType::null && col->identity_type == BaseType::null) + attribs[ParsersAttributes::IDENTITY_TYPE] = ParsersAttributes::UNSET; + else if(this->identity_type != BaseType::null && col->identity_type != BaseType::null && + this->identity_type != col->identity_type) + attribs[ParsersAttributes::NEW_IDENTITY_TYPE] = ~col->identity_type; + copyAttributes(attribs); return(BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, true)); } @@ -234,6 +286,7 @@ void Column::operator = (Column &col) this->not_null=col.not_null; this->parent_rel=col.parent_rel; this->sequence=col.sequence; + this->identity_type=col.identity_type; this->setParentTable(col.getParentTable()); this->setAddedByCopy(false); diff --git a/libpgmodeler/src/column.h b/libpgmodeler/src/column.h index 54d6f9ed0..e68e9402a 100644 --- a/libpgmodeler/src/column.h +++ b/libpgmodeler/src/column.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -55,6 +55,9 @@ class Column: public TableObject{ This attribute is used only the data type is integer, smallint or bigint */ BaseObject *sequence; + //! \brief Identity type of the column (GENERATED BY DEFAULT | ALWAYS) + IdentityType identity_type; + public: Column(void); @@ -64,6 +67,9 @@ class Column: public TableObject{ //! \brief Defines the column data type void setType(PgSQLType type); + //! \brief Defines the identity mode of the column + void setIdentityType(IdentityType id_type); + /*! \brief Sets the default value of the column. Must be informed together with the value the particularities of each type, such as quotation marks, hyphens, etc. */ void setDefaultValue(const QString &value); @@ -76,9 +82,15 @@ class Column: public TableObject{ //! \brief Returns the not null state of the column bool isNotNull(void); + //! \brief Returns wheter the column is identity or not (GENERATED BY DEFAULT | ALWAYS) + bool isIdentity(void); + //! \brief Returns the data type of the column PgSQLType getType(void); + //! \brief Returns the identity mode of the column + IdentityType getIdentityType(void); + //! \brief Returns the default value of the column QString getDefaultValue(void); diff --git a/libpgmodeler/src/constraint.cpp b/libpgmodeler/src/constraint.cpp index 91a729054..8bb2818b9 100644 --- a/libpgmodeler/src/constraint.cpp +++ b/libpgmodeler/src/constraint.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -593,8 +593,8 @@ void Constraint::setColumnsNotNull(bool value) { for(auto &col : columns) { - if(!col->isAddedByRelationship()) - col->setNotNull(value); + //if(!col->isAddedByRelationship()) + col->setNotNull(value); } } } diff --git a/libpgmodeler/src/constraint.h b/libpgmodeler/src/constraint.h index 4aa6d9a31..b0c335931 100644 --- a/libpgmodeler/src/constraint.h +++ b/libpgmodeler/src/constraint.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/conversion.cpp b/libpgmodeler/src/conversion.cpp index 92f01dab4..3b8d3bae9 100644 --- a/libpgmodeler/src/conversion.cpp +++ b/libpgmodeler/src/conversion.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/conversion.h b/libpgmodeler/src/conversion.h index 796b0b072..e67e2f7c4 100644 --- a/libpgmodeler/src/conversion.h +++ b/libpgmodeler/src/conversion.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/copyoptions.cpp b/libpgmodeler/src/copyoptions.cpp index 11edc5d69..cfb06271a 100644 --- a/libpgmodeler/src/copyoptions.cpp +++ b/libpgmodeler/src/copyoptions.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/copyoptions.h b/libpgmodeler/src/copyoptions.h index 4962d8e41..16107d807 100644 --- a/libpgmodeler/src/copyoptions.h +++ b/libpgmodeler/src/copyoptions.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/databasemodel.cpp b/libpgmodeler/src/databasemodel.cpp index dd91021ae..898d38e56 100644 --- a/libpgmodeler/src/databasemodel.cpp +++ b/libpgmodeler/src/databasemodel.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,6 +27,9 @@ DatabaseModel::DatabaseModel(void) object_id=DatabaseModel::dbmodel_id++; obj_type=OBJ_DATABASE; + is_template = false; + allow_conns = true; + encoding=BaseType::null; BaseObject::setName(QObject::trUtf8("new_database").toUtf8()); @@ -45,6 +48,8 @@ DatabaseModel::DatabaseModel(void) attributes[ParsersAttributes::_LC_CTYPE_]=QString(); attributes[ParsersAttributes::APPEND_AT_EOD]=QString(); attributes[ParsersAttributes::PREPEND_AT_BOD]=QString(); + attributes[ParsersAttributes::ALLOW_CONNS]=QString(); + attributes[ParsersAttributes::IS_TEMPLATE]=QString(); } DatabaseModel::DatabaseModel(ModelWidget *model_wgt):DatabaseModel() @@ -405,15 +410,16 @@ void DatabaseModel::__addObject(BaseObject *object, int obj_idx) Special cases are for: functions/operator that are search by signature and views that are search on tables and views list */ if((obj_type==OBJ_VIEW && (getObject(object->getName(true), obj_type, idx) || - getObject(object->getName(true), OBJ_TABLE, idx))) || + getObject(object->getName(true), OBJ_TABLE, idx))) || (obj_type==OBJ_TABLE && (getObject(object->getName(true), obj_type, idx) || - getObject(object->getName(true), OBJ_VIEW, idx))) || + getObject(object->getName(true), OBJ_VIEW, idx))) || + (obj_type==OBJ_EXTENSION && (getObject(object->getName(false), obj_type, idx))) || (getObject(object->getSignature(), obj_type, idx))) { QString str_aux; str_aux=QString(Exception::getErrorMessage(ERR_ASG_DUPLIC_OBJECT)) - .arg(object->getName(true)) + .arg(object->getName(obj_type != OBJ_EXTENSION)) .arg(object->getTypeName()) .arg(this->getName(true)) .arg(this->getTypeName()); @@ -561,7 +567,7 @@ vector DatabaseModel::getObjects(BaseObject *schema) vector::iterator itr, itr_end; ObjectType types[]={ OBJ_FUNCTION, OBJ_TABLE, OBJ_VIEW, OBJ_DOMAIN, OBJ_AGGREGATE, OBJ_OPERATOR, OBJ_SEQUENCE, OBJ_CONVERSION, - OBJ_TYPE, OBJ_OPCLASS, OBJ_OPFAMILY, OBJ_COLLATION, OBJ_EXTENSION }; + OBJ_TYPE, OBJ_OPCLASS, OBJ_OPFAMILY, OBJ_COLLATION }; unsigned i, count=sizeof(types)/sizeof(ObjectType); for(i=0; i < count; i++) @@ -648,18 +654,17 @@ unsigned DatabaseModel::getObjectCount(ObjectType obj_type) unsigned DatabaseModel::getObjectCount(void) { - ObjectType types[20]={ + vector types={ BASE_RELATIONSHIP,OBJ_RELATIONSHIP, OBJ_TABLE, OBJ_VIEW, - OBJ_AGGREGATE, OBJ_OPERATOR, - OBJ_SEQUENCE, OBJ_CONVERSION, - OBJ_CAST, OBJ_OPFAMILY, OBJ_OPCLASS, - BASE_RELATIONSHIP, OBJ_TEXTBOX, - OBJ_DOMAIN, OBJ_TYPE, OBJ_FUNCTION, OBJ_SCHEMA, - OBJ_LANGUAGE, OBJ_TABLESPACE, OBJ_ROLE }; - unsigned count=0, i; + OBJ_AGGREGATE, OBJ_OPERATOR, OBJ_SEQUENCE, OBJ_CONVERSION, + OBJ_CAST, OBJ_OPFAMILY, OBJ_OPCLASS, OBJ_TEXTBOX, OBJ_DOMAIN, + OBJ_TYPE, OBJ_FUNCTION, OBJ_SCHEMA, OBJ_LANGUAGE, OBJ_TABLESPACE, + OBJ_ROLE, OBJ_PERMISSION, OBJ_COLLATION, OBJ_EXTENSION, OBJ_TAG, + OBJ_EVENT_TRIGGER, OBJ_GENERIC_SQL}; + unsigned count=0; - for(i=0; i < 20; i++) - count+=getObjectList(types[i])->size(); + for(auto &type : types) + count+=getObjectList(type)->size(); return(count); } @@ -702,30 +707,22 @@ QString DatabaseModel::getAuthor(void) void DatabaseModel::setProtected(bool value) { - ObjectType types[19]={ - OBJ_RELATIONSHIP, OBJ_TABLE, OBJ_VIEW, + vector types = { + BASE_RELATIONSHIP,OBJ_RELATIONSHIP, OBJ_TABLE, OBJ_VIEW, OBJ_AGGREGATE, OBJ_OPERATOR, OBJ_SEQUENCE, OBJ_CONVERSION, OBJ_CAST, OBJ_OPFAMILY, OBJ_OPCLASS, BASE_RELATIONSHIP, OBJ_TEXTBOX, - OBJ_DOMAIN, OBJ_TYPE, OBJ_FUNCTION, OBJ_SCHEMA, - OBJ_LANGUAGE, OBJ_TABLESPACE, OBJ_ROLE }; - vector *lista=nullptr; - vector::iterator itr, itr_end; - BaseObject *objeto=nullptr; - unsigned i; + OBJ_DOMAIN, OBJ_TYPE, OBJ_FUNCTION, + OBJ_LANGUAGE, OBJ_TABLESPACE, OBJ_ROLE, OBJ_COLLATION, + OBJ_EXTENSION, OBJ_SCHEMA, OBJ_PERMISSION, OBJ_TAG, OBJ_GENERIC_SQL + }; - for(i=0; i < 19; i++) + for(auto &type : types) { - lista=getObjectList(types[i]); - itr=lista->begin(); - itr_end=lista->end(); - - while(itr!=itr_end) + for(auto &object : *getObjectList(type)) { - objeto=(*itr); - objeto->setProtected(value); - itr++; + object->setProtected(value); } } @@ -1118,15 +1115,14 @@ void DatabaseModel::updateTableFKRelationships(Table *table) (rel->getTable(BaseRelationship::SRC_TABLE)==table || rel->getTable(BaseRelationship::DST_TABLE)==table)) { + Constraint *fk = rel->getReferenceForeignKey(); if(rel->getTable(BaseRelationship::SRC_TABLE)==table) ref_tab=dynamic_cast
(rel->getTable(BaseRelationship::DST_TABLE)); else ref_tab=dynamic_cast
(rel->getTable(BaseRelationship::SRC_TABLE)); //Removes the relationship if the table does'nt references the 'ref_tab' - if(!table->isReferTableOnForeignKey(ref_tab) && - (rel->isSelfRelationship() || - (!rel->isSelfRelationship() && !ref_tab->isReferTableOnForeignKey(table)))) + if(fk->getReferencedTable() == ref_tab && table->getObjectIndex(fk) < 0) { removeRelationship(rel); itr1=base_relationships.begin() + idx; @@ -1134,9 +1130,7 @@ void DatabaseModel::updateTableFKRelationships(Table *table) } else { - if(!rel->isSelfRelationship() && ref_tab->isReferTableOnForeignKey(table)) - rel->setModified(true); - + rel->setModified(true); itr1++; idx++; } } @@ -1154,11 +1148,12 @@ void DatabaseModel::updateTableFKRelationships(Table *table) itr++; //Only creates the relationship if does'nt exist one between the tables - rel=getRelationship(table, ref_tab); + rel=getRelationship(table, ref_tab, fk); if(!rel && ref_tab->getDatabase()==this) { rel=new BaseRelationship(BaseRelationship::RELATIONSHIP_FK, table, ref_tab, false, false); + rel->setReferenceForeignKey(fk); rel->setCustomColor(Qt::transparent); /* Workaround: In some cases the combination of the two tablenames can generate a duplicated relationship @@ -1169,10 +1164,7 @@ void DatabaseModel::updateTableFKRelationships(Table *table) addRelationship(rel); } - else if(rel && rel->isBidirectional()) - rel->setModified(true); } - } } @@ -1932,7 +1924,10 @@ void DatabaseModel::addRelationship(BaseRelationship *rel, int obj_idx) tab2=rel->getTable(BaseRelationship::DST_TABLE); //Raises an error if already exists an relationship between the tables - if(getRelationship(tab1,tab2)) + if(rel->getRelationshipType() != Relationship::RELATIONSHIP_1N && + rel->getRelationshipType() != Relationship::RELATIONSHIP_NN && + rel->getRelationshipType() != Relationship::RELATIONSHIP_FK && + getRelationship(tab1,tab2)) { msg=Exception::getErrorMessage(ERR_DUPLIC_RELATIONSHIP) .arg(tab1->getName(true)) @@ -2023,7 +2018,7 @@ BaseRelationship *DatabaseModel::getRelationship(const QString &name) return(rel); } -BaseRelationship *DatabaseModel::getRelationship(BaseTable *src_tab, BaseTable *dst_tab) +BaseRelationship *DatabaseModel::getRelationship(BaseTable *src_tab, BaseTable *dst_tab, Constraint *ref_fk) { vector::iterator itr, itr_end; vector rel_list; @@ -2039,9 +2034,7 @@ BaseRelationship *DatabaseModel::getRelationship(BaseTable *src_tab, BaseTable * search_uniq_tab=true; } - - if(src_tab->getObjectType()==OBJ_VIEW || - dst_tab->getObjectType()==OBJ_VIEW) + if(ref_fk || src_tab->getObjectType()==OBJ_VIEW || dst_tab->getObjectType()==OBJ_VIEW) { itr=base_relationships.begin(); itr_end=base_relationships.end(); @@ -2060,9 +2053,10 @@ BaseRelationship *DatabaseModel::getRelationship(BaseTable *src_tab, BaseTable * tab1=rel->getTable(BaseRelationship::SRC_TABLE); tab2=rel->getTable(BaseRelationship::DST_TABLE); - found=((tab1==src_tab && tab2==dst_tab) || - (tab2==src_tab && tab1==dst_tab) || - (search_uniq_tab && (tab1==src_tab || tab2==src_tab))); + found=((!ref_fk || (ref_fk && rel->getReferenceForeignKey() == ref_fk)) && + ((tab1==src_tab && tab2==dst_tab) || + (tab2==src_tab && tab1==dst_tab) || + (search_uniq_tab && (tab1==src_tab || tab2==src_tab)))); if(!found) { rel=nullptr; itr++; } @@ -2086,7 +2080,7 @@ vector DatabaseModel::getRelationships(BaseTable *tab) base_rel=dynamic_cast(obj); if(base_rel->getTable(BaseRelationship::SRC_TABLE)==tab || - base_rel->getTable(BaseRelationship::DST_TABLE)==tab) + base_rel->getTable(BaseRelationship::DST_TABLE)==tab) aux_rels.push_back(base_rel); } @@ -2699,7 +2693,7 @@ void DatabaseModel::addPermission(Permission *perm) .arg(perm->getObject()->getTypeName()) .arg(perm->getObject()->getName()) .arg(perm->getObject()->getTypeName()), - ERR_ASG_DUPLIC_PERMISSION,__PRETTY_FUNCTION__,__FILE__,__LINE__); + ERR_REF_OBJ_INEXISTS_MODEL,__PRETTY_FUNCTION__,__FILE__,__LINE__); permissions.push_back(perm); perm->setDatabase(this); @@ -2907,7 +2901,8 @@ void DatabaseModel::configureDatabase(attribs_map &attribs) localizations[1]=attribs[ParsersAttributes::_LC_COLLATE_]; append_at_eod=attribs[ParsersAttributes::APPEND_AT_EOD]==ParsersAttributes::_TRUE_; prepend_at_bod=attribs[ParsersAttributes::PREPEND_AT_BOD]==ParsersAttributes::_TRUE_; - + is_template=attribs[ParsersAttributes::IS_TEMPLATE]==ParsersAttributes::_TRUE_; + allow_conns=attribs[ParsersAttributes::ALLOW_CONNS] != ParsersAttributes::_FALSE_; if(!attribs[ParsersAttributes::CONN_LIMIT].isEmpty()) conn_limit=attribs[ParsersAttributes::CONN_LIMIT].toInt(); @@ -2961,6 +2956,10 @@ void DatabaseModel::loadModel(const QString &filename) this->last_zoom=attribs[ParsersAttributes::LAST_ZOOM].toDouble(); if(this->last_zoom <= 0) this->last_zoom=1; + this->is_template = attribs[ParsersAttributes::IS_TEMPLATE] == ParsersAttributes::_TRUE_; + this->allow_conns = (attribs[ParsersAttributes::ALLOW_CONNS].isEmpty() || + attribs[ParsersAttributes::ALLOW_CONNS] == ParsersAttributes::_TRUE_); + protected_model=(attribs[ParsersAttributes::PROTECTED]==ParsersAttributes::_TRUE_); def_objs[OBJ_SCHEMA]=attribs[ParsersAttributes::DEFAULT_SCHEMA]; @@ -3151,6 +3150,8 @@ BaseObject *DatabaseModel::createObject(ObjectType obj_type) object=createEventTrigger(); else if(obj_type==OBJ_GENERIC_SQL) object=createGenericSQL(); + else if(obj_type==OBJ_POLICY) + object=createPolicy(); } return(object); @@ -3339,12 +3340,12 @@ Role *DatabaseModel::createRole(void) QString op_attribs[]={ ParsersAttributes::SUPERUSER, ParsersAttributes::CREATEDB, ParsersAttributes::CREATEROLE, ParsersAttributes::INHERIT, ParsersAttributes::LOGIN, ParsersAttributes::ENCRYPTED, - ParsersAttributes::REPLICATION }; + ParsersAttributes::REPLICATION, ParsersAttributes::BYPASSRLS }; unsigned op_vect[]={ Role::OP_SUPERUSER, Role::OP_CREATEDB, Role::OP_CREATEROLE, Role::OP_INHERIT, Role::OP_LOGIN, Role::OP_ENCRYPTED, - Role::OP_REPLICATION }; + Role::OP_REPLICATION, Role::OP_BYPASSRLS }; try { @@ -3361,7 +3362,7 @@ Role *DatabaseModel::createRole(void) role->setConnectionLimit(attribs[ParsersAttributes::CONN_LIMIT].toInt()); //Setting up the role options according to the configured on the XML - for(i=0; i < 7; i++) + for(i=0; i < 8; i++) { marked=attribs[op_attribs[i]]==ParsersAttributes::_TRUE_; role->setOption(op_vect[i], marked); @@ -4060,14 +4061,10 @@ Domain *DatabaseModel::createDomain(void) setBasicAttributes(domain); xmlparser.getElementAttributes(attribs); - if(!attribs[ParsersAttributes::CONSTRAINT].isEmpty()) - domain->setConstraintName(attribs[ParsersAttributes::CONSTRAINT]); - if(!attribs[ParsersAttributes::DEFAULT_VALUE].isEmpty()) domain->setDefaultValue(attribs[ParsersAttributes::DEFAULT_VALUE]); - domain->setNotNull(attribs[ParsersAttributes::NOT_NULL]== - ParsersAttributes::_TRUE_); + domain->setNotNull(attribs[ParsersAttributes::NOT_NULL]==ParsersAttributes::_TRUE_); if(xmlparser.accessElement(XMLParser::CHILD_ELEMENT)) { @@ -4082,11 +4079,13 @@ Domain *DatabaseModel::createDomain(void) { domain->setType(createPgSQLType()); } - else if(elem==ParsersAttributes::EXPRESSION) + else if(elem==ParsersAttributes::CONSTRAINT) { xmlparser.savePosition(); + xmlparser.getElementAttributes(attribs); + xmlparser.accessElement(XMLParser::CHILD_ELEMENT); xmlparser.accessElement(XMLParser::CHILD_ELEMENT); - domain->setExpression(xmlparser.getElementContent()); + domain->addCheckConstraint(attribs[ParsersAttributes::NAME], xmlparser.getElementContent()); xmlparser.restorePosition(); } } @@ -4557,6 +4556,8 @@ Table *DatabaseModel::createTable(void) table->setWithOIDs(attribs[ParsersAttributes::OIDS]==ParsersAttributes::_TRUE_); table->setUnlogged(attribs[ParsersAttributes::UNLOGGED]==ParsersAttributes::_TRUE_); + table->setRLSEnabled(attribs[ParsersAttributes::RLS_ENABLED]==ParsersAttributes::_TRUE_); + table->setRLSForced(attribs[ParsersAttributes::RLS_FORCED]==ParsersAttributes::_TRUE_); table->setGenerateAlterCmds(attribs[ParsersAttributes::GEN_ALTER_CMDS]==ParsersAttributes::_TRUE_); table->setExtAttribsHidden(attribs[ParsersAttributes::HIDE_EXT_ATTRIBS]==ParsersAttributes::_TRUE_); table->setFadedOut(attribs[ParsersAttributes::FADED_OUT]==ParsersAttributes::_TRUE_); @@ -4674,6 +4675,9 @@ Column *DatabaseModel::createColumn(void) column->setNotNull(attribs[ParsersAttributes::NOT_NULL]==ParsersAttributes::_TRUE_); column->setDefaultValue(attribs[ParsersAttributes::DEFAULT_VALUE]); + if(!attribs[ParsersAttributes::IDENTITY_TYPE].isEmpty()) + column->setIdentityType(IdentityType(attribs[ParsersAttributes::IDENTITY_TYPE])); + if(!attribs[ParsersAttributes::SEQUENCE].isEmpty()) { seq=getObject(attribs[ParsersAttributes::SEQUENCE], OBJ_SEQUENCE); @@ -5072,13 +5076,23 @@ QString DatabaseModel::getAlterDefinition(BaseObject *object) try { - QString alter_def=BaseObject::getAlterDefinition(object); + QString alter_def; + attribs_map aux_attribs; + + aux_attribs[ParsersAttributes::SIGNATURE] = this->getSignature(); + aux_attribs[ParsersAttributes::SQL_OBJECT] = this->getSQLName(); if(this->conn_limit!=db_aux->conn_limit) - { - attributes[ParsersAttributes::CONN_LIMIT]=QString::number(db_aux->conn_limit); - alter_def+=BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, false); - } + aux_attribs[ParsersAttributes::CONN_LIMIT]=QString::number(db_aux->conn_limit); + + if(this->is_template != db_aux->is_template) + aux_attribs[ParsersAttributes::IS_TEMPLATE] = (db_aux->is_template ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); + + if(this->allow_conns != db_aux->allow_conns) + aux_attribs[ParsersAttributes::ALLOW_CONNS] = (db_aux->allow_conns ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); + + alter_def+=BaseObject::getAlterDefinition(this->getSchemaName(), aux_attribs, true, false); + alter_def+=BaseObject::getAlterDefinition(object); return(alter_def); } @@ -5401,6 +5415,98 @@ Trigger *DatabaseModel::createTrigger(void) return(trigger); } +Policy *DatabaseModel::createPolicy(void) +{ + attribs_map attribs; + Policy *policy=nullptr; + QString elem; + BaseTable *table=nullptr; + + try + { + policy=new Policy; + setBasicAttributes(policy); + + xmlparser.getElementAttributes(attribs); + + table=dynamic_cast(getObject(attribs[ParsersAttributes::TABLE], OBJ_TABLE)); + + if(!table) + throw Exception(QString(Exception::getErrorMessage(ERR_REF_OBJ_INEXISTS_MODEL)) + .arg(attribs[ParsersAttributes::NAME]) + .arg(BaseObject::getTypeName(OBJ_POLICY)) + .arg(attribs[ParsersAttributes::TABLE]) + .arg(BaseObject::getTypeName(OBJ_TABLE)), + ERR_REF_OBJ_INEXISTS_MODEL,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + policy->setPermissive(attribs[ParsersAttributes::PERMISSIVE] == ParsersAttributes::_TRUE_); + policy->setPolicyCommand(PolicyCmdType(attribs[ParsersAttributes::COMMAND])); + + if(xmlparser.accessElement(XMLParser::CHILD_ELEMENT)) + { + do + { + if(xmlparser.getElementType()==XML_ELEMENT_NODE) + { + elem=xmlparser.getElementName(); + + if(elem==ParsersAttributes::EXPRESSION) + { + xmlparser.getElementAttributes(attribs); + xmlparser.savePosition(); + xmlparser.accessElement(XMLParser::CHILD_ELEMENT); + + if(attribs[ParsersAttributes::TYPE] == ParsersAttributes::USING_EXP) + policy->setUsingExpression(xmlparser.getElementContent()); + else if(attribs[ParsersAttributes::TYPE] == ParsersAttributes::CHECK_EXP) + policy->setCheckExpression(xmlparser.getElementContent()); + + xmlparser.restorePosition(); + } + else if(xmlparser.getElementName()==ParsersAttributes::ROLES) + { + QStringList rol_names; + Role *role = nullptr; + + xmlparser.getElementAttributes(attribs); + + rol_names = attribs[ParsersAttributes::NAMES].split(','); + + for(auto &name : rol_names) + { + role=dynamic_cast(getObject(name.trimmed(), OBJ_ROLE)); + + //Raises an error if the referenced role doesn't exists + if(!role) + { + throw Exception(Exception::getErrorMessage(ERR_REF_OBJ_INEXISTS_MODEL) + .arg(policy->getName()) + .arg(policy->getTypeName()) + .arg(name) + .arg(BaseObject::getTypeName(OBJ_ROLE)), + ERR_REF_OBJ_INEXISTS_MODEL,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + + policy->addRole(role); + } + } + } + } + while(xmlparser.accessElement(XMLParser::NEXT_ELEMENT)); + } + + table->addObject(policy); + table->setModified(true); + } + catch(Exception &e) + { + if(policy) delete(policy); + throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e, getErrorExtraInfo()); + } + + return(policy); +} + EventTrigger *DatabaseModel::createEventTrigger(void) { attribs_map attribs; @@ -5675,9 +5781,10 @@ View *DatabaseModel::createView(void) type=Reference::SQL_REFER_SELECT; else if(attribs[ParsersAttributes::TYPE]==ParsersAttributes::FROM_EXP) type=Reference::SQL_REFER_FROM; - else + else if(attribs[ParsersAttributes::TYPE]==ParsersAttributes::SIMPLE_EXP) type=Reference::SQL_REFER_WHERE; - + else + type=Reference::SQL_REFER_END_EXPR; list_aux=xmlparser.getElementContent().split(','); count=list_aux.size(); @@ -5965,7 +6072,7 @@ BaseRelationship *DatabaseModel::createRelationship(void) /* Creates the fk relationship if it not exists. This generally happens when a foreign key is added to the table after its creation. */ - if(!base_rel && attribs[ParsersAttributes::TYPE]==ParsersAttributes::RELATIONSHIP_FK) + if(/*!base_rel &&*/ attribs[ParsersAttributes::TYPE]==ParsersAttributes::RELATIONSHIP_FK) { vector fks; dynamic_cast
(tables[0])->getForeignKeys(fks, false, dynamic_cast
(tables[1])); @@ -6142,9 +6249,31 @@ BaseRelationship *DatabaseModel::createRelationship(void) base_rel->setProtected(protect); base_rel->setCustomColor(custom_color); + /* If the FK relationship does not reference a foreign key (models generated in older versions) + * we need to assign them to the respective relationships */ if(base_rel && base_rel->getObjectType()==BASE_RELATIONSHIP) base_rel->connectRelationship(); + if(base_rel && + base_rel->getRelationshipType() == BaseRelationship::RELATIONSHIP_FK && + !base_rel->getReferenceForeignKey()) + { + Table *src_tab = dynamic_cast
(base_rel->getTable(BaseRelationship::SRC_TABLE)), + *dst_tab = dynamic_cast
(base_rel->getTable(BaseRelationship::DST_TABLE)); + vector fks; + + src_tab->getForeignKeys(fks, false, dst_tab); + + for(auto fk : fks) + { + if(!getRelationship(src_tab, dst_tab, fk)) + { + base_rel->setReferenceForeignKey(fk); + break; + } + } + } + return(base_rel); } @@ -6380,7 +6509,6 @@ QString DatabaseModel::__getCodeDefinition(unsigned def_type) attributes[loc_attribs[i]]=QString("'%1'").arg(localizations[i]); } } - } else { @@ -6391,6 +6519,8 @@ QString DatabaseModel::__getCodeDefinition(unsigned def_type) attributes[ParsersAttributes::PREPEND_AT_BOD]=(prepend_at_bod ? ParsersAttributes::_TRUE_ : QString()); } + attributes[ParsersAttributes::IS_TEMPLATE]=(is_template ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); + attributes[ParsersAttributes::ALLOW_CONNS]=(allow_conns ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); attributes[ParsersAttributes::TEMPLATE_DB]=template_db; if(def_type==SchemaParser::SQL_DEFINITION && append_at_eod) @@ -6437,7 +6567,7 @@ QString DatabaseModel::getCodeDefinition(unsigned def_type, bool export_file) bool sql_disabled=false; BaseObject *object=nullptr; QString def, search_path=QString("pg_catalog,public"), - msg=trUtf8("Generating %1 of the object `%2' (%3)"), + msg=trUtf8("Generating %1 code: `%2' (%3)"), attrib=ParsersAttributes::OBJECTS, attrib_aux, def_type_str=(def_type==SchemaParser::SQL_DEFINITION ? QString("SQL") : QString("XML")); Type *usr_type=nullptr; @@ -6447,7 +6577,7 @@ QString DatabaseModel::getCodeDefinition(unsigned def_type, bool export_file) try { objects_map=getCreationOrder(def_type); - general_obj_cnt=this->getObjectCount(); + general_obj_cnt=objects_map.size(); gen_defs_count=0; attribs_aux[ParsersAttributes::SHELL_TYPES]=QString(); @@ -6560,7 +6690,7 @@ QString DatabaseModel::getCodeDefinition(unsigned def_type, bool export_file) if((def_type==SchemaParser::SQL_DEFINITION && !object->isSQLDisabled()) || (def_type==SchemaParser::XML_DEFINITION && !object->isSystemObject())) { - emit s_objectLoaded((gen_defs_count/static_cast(general_obj_cnt)) * 100, + emit s_objectLoaded((gen_defs_count/static_cast(general_obj_cnt)) * 100, msg.arg(def_type_str) .arg(object->getName()) .arg(object->getTypeName()), @@ -6633,10 +6763,7 @@ map DatabaseModel::getCreationOrder(unsigned def_type, b vector::iterator itr, itr_end; map objects_map; Table *table=nullptr; - Index *index=nullptr; - Trigger *trigger=nullptr; Constraint *constr=nullptr; - Rule *rule=nullptr; View *view=nullptr; Relationship *rel=nullptr; ObjectType aux_obj_types[]={ OBJ_ROLE, OBJ_TABLESPACE, OBJ_SCHEMA, OBJ_TAG }, @@ -6721,26 +6848,8 @@ map DatabaseModel::getCreationOrder(unsigned def_type, b fkeys.push_back(constr); } - count=table->getTriggerCount(); - for(i=0; i < count; i++) - { - trigger=table->getTrigger(i); - objects_map[trigger->getObjectId()]=trigger; - } - - count=table->getIndexCount(); - for(i=0; i < count; i++) - { - index=table->getIndex(i); - objects_map[index->getObjectId()]=index; - } - - count=table->getRuleCount(); - for(i=0; i < count; i++) - { - rule=table->getRule(i); - objects_map[rule->getObjectId()]=rule; - } + for(auto obj : table->getObjects(true)) + objects_map[obj->getObjectId()]=obj; } /* Getting and storing the special objects (which reference columns of tables added for relationships) @@ -6749,26 +6858,8 @@ map DatabaseModel::getCreationOrder(unsigned def_type, b { view=dynamic_cast(obj); - count=view->getTriggerCount(); - for(i=0; i < count; i++) - { - trigger=view->getTrigger(i); - objects_map[trigger->getObjectId()]=trigger; - } - - count=view->getRuleCount(); - for(i=0; i < count; i++) - { - rule=view->getRule(i); - objects_map[rule->getObjectId()]=rule; - } - - count=view->getIndexCount(); - for(i=0; i < count; i++) - { - index=view->getIndex(i); - objects_map[index->getObjectId()]=index; - } + for(auto obj : view->getObjects()) + objects_map[obj->getObjectId()]=obj; } /* SPECIAL CASE: Generating the correct order for tables, views, relationships and sequences @@ -7398,15 +7489,23 @@ void DatabaseModel::getObjectDependecies(BaseObject *object, vectorgetIndexElement(i).getCollation(), deps, inc_indirect_deps); } } + else if(obj_type==OBJ_POLICY) + { + Policy *pol=dynamic_cast(object); + + for(auto role : pol->getRoles()) + getObjectDependecies(role, deps, inc_indirect_deps); + } //** Getting the dependecies for table ** else if(obj_type==OBJ_TABLE) { Table *tab=dynamic_cast
(object); - BaseObject *usr_type=nullptr; + BaseObject *usr_type=nullptr, *seq=nullptr; Constraint *constr=nullptr; Trigger *trig=nullptr; Index *index=nullptr; Column *col=nullptr; + Policy *pol=nullptr; unsigned count, i, count1, i1; count=tab->getColumnCount(); @@ -7414,9 +7513,16 @@ void DatabaseModel::getObjectDependecies(BaseObject *object, vectorgetColumn(i); usr_type=getObjectPgSQLType(col->getType()); + seq=col->getSequence(); - if(!col->isAddedByLinking() && usr_type) - getObjectDependecies(usr_type, deps, inc_indirect_deps); + if(!col->isAddedByLinking()) + { + if(usr_type) + getObjectDependecies(usr_type, deps, inc_indirect_deps); + + if(seq) + getObjectDependecies(seq, deps, inc_indirect_deps); + } } count=tab->getConstraintCount(); @@ -7477,6 +7583,15 @@ void DatabaseModel::getObjectDependecies(BaseObject *object, vectorgetIndexElement(i1).getCollation(), deps, inc_indirect_deps); } } + + count=tab->getPolicyCount(); + for(i=0; i < count; i++) + { + pol=dynamic_cast(tab->getPolicy(i)); + + for(auto role : pol->getRoles()) + getObjectDependecies(role, deps, inc_indirect_deps); + } } //** Getting the dependecies for user defined type ** else if(obj_type==OBJ_TYPE) @@ -7595,9 +7710,9 @@ void DatabaseModel::getObjectReferences(BaseObject *object, vector vector::iterator itr, itr_end; vector *tab_objs; unsigned i, count; - ObjectType tab_obj_types[3]={ OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX }; + ObjectType tab_obj_types[4]={ OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX, OBJ_POLICY }; - for(i=0; i < 3; i++) + for(i=0; i < 4; i++) { tab_objs=table->getObjectList(tab_obj_types[i]); refs.insert(refs.end(), tab_objs->begin(), tab_objs->end()); @@ -7986,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); @@ -8191,6 +8309,19 @@ void DatabaseModel::getObjectReferences(BaseObject *object, vector refer=true; refs.push_back(*itr); } + + if((*itr)->getObjectType() == OBJ_TABLE) + { + for(auto obj : *(dynamic_cast
(*itr))->getObjectList(OBJ_POLICY)) + { + if(dynamic_cast(obj)->isRoleExists(role)) + { + refer=true; + refs.push_back(obj); + } + } + } + itr++; } } @@ -8680,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, @@ -8730,8 +8870,8 @@ void DatabaseModel::setCodesInvalidated(vector types) else { ObjectType tab_obj_types[]={OBJ_COLUMN, OBJ_CONSTRAINT, - OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX}; - for(unsigned i=0; i < 5; i++) + OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX, OBJ_POLICY}; + for(unsigned i=0; i < 6; i++) sel_types.erase(std::find(sel_types.begin(), sel_types.end(), tab_obj_types[i])); sel_types=types; @@ -9046,6 +9186,16 @@ void DatabaseModel::setDefaultObject(BaseObject *object, ObjectType obj_type) default_objs[object->getObjectType()]=object; } +void DatabaseModel::setIsTemplate(bool value) +{ + is_template = value; +} + +void DatabaseModel::setAllowConnections(bool value) +{ + allow_conns = value; +} + bool DatabaseModel::isAppendAtEOD(void) { return(append_at_eod); @@ -9056,6 +9206,16 @@ bool DatabaseModel::isPrependedAtBOD(void) return(prepend_at_bod); } +bool DatabaseModel::isTemplate(void) +{ + return(is_template); +} + +bool DatabaseModel::isAllowConnections(void) +{ + return(allow_conns); +} + void DatabaseModel::saveObjectsMetadata(const QString &filename, unsigned options) { QFile output(filename); diff --git a/libpgmodeler/src/databasemodel.h b/libpgmodeler/src/databasemodel.h index be608e828..f0cde903c 100644 --- a/libpgmodeler/src/databasemodel.h +++ b/libpgmodeler/src/databasemodel.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -87,6 +87,12 @@ class DatabaseModel: public QObject, public BaseObject { //! \brief Maximum number of connections int conn_limit; + //! \brief Indicates if the database can be used as template + bool is_template, + + //! \brief Indicates if the database accepts connection + allow_conns; + //! \brief Vectors that stores all the objects types vector textboxes; vector relationships; @@ -255,12 +261,20 @@ class DatabaseModel: public QObject, public BaseObject { void setDefaultObject(BaseObject *object, ObjectType obj_type=BASE_OBJECT); + void setIsTemplate(bool value); + + void setAllowConnections(bool value); + //! \brief Returns the current state of the sql appeding at end of entire model definition bool isAppendAtEOD(void); //! \brief Returns the current state of the sql prepeding at beginning of entire model definition bool isPrependedAtBOD(void); + bool isTemplate(void); + + bool isAllowConnections(void); + //! \brief Destroys all the objects void destroyObjects(void); @@ -331,8 +345,9 @@ class DatabaseModel: public QObject, public BaseObject { /*! \brief Searchs and returns the relationship between the specified tables. If the second parameter is ommited (nullptr), the method returns the first relationship where the source table is - participating */ - BaseRelationship *getRelationship(BaseTable *src_tab, BaseTable *dst_tab); + participating. The optional parameter ref_fk will search for foreign key relationships which the reference foreign key + is the one provided */ + BaseRelationship *getRelationship(BaseTable *src_tab, BaseTable *dst_tab, Constraint *ref_fk = nullptr); //! \brief Searchs and returns all the relationships that the specified table participates vector getRelationships(BaseTable *tab); @@ -502,6 +517,7 @@ class DatabaseModel: public QObject, public BaseObject { Rule *createRule(void); Index *createIndex(void); Trigger *createTrigger(void); + Policy *createPolicy(void); EventTrigger *createEventTrigger(void); GenericSQL *createGenericSQL(void); @@ -545,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/src/domain.cpp b/libpgmodeler/src/domain.cpp index ea344f371..fe5672dc5 100644 --- a/libpgmodeler/src/domain.cpp +++ b/libpgmodeler/src/domain.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -24,9 +24,41 @@ Domain::Domain(void) not_null=false; attributes[ParsersAttributes::DEFAULT_VALUE]=QString(); attributes[ParsersAttributes::NOT_NULL]=QString(); - attributes[ParsersAttributes::EXPRESSION]=QString(); attributes[ParsersAttributes::TYPE]=QString(); - attributes[ParsersAttributes::CONSTRAINT]=QString(); + attributes[ParsersAttributes::CONSTRAINTS]=QString(); +} + +void Domain::addCheckConstraint(const QString &name, const QString &expr) +{ + //Raises an error if the constraint name is invalid + if(!name.isEmpty() && !BaseObject::isValidName(name)) + throw Exception(ERR_ASG_INV_NAME_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(expr.isEmpty()) + throw Exception(ERR_ASG_INV_EXPR_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(chk_constrs.count(name)) + { + throw Exception(QString(Exception::getErrorMessage(ERR_ASG_DUPLIC_OBJECT)) + .arg(name) + .arg(BaseObject::getTypeName(OBJ_CONSTRAINT)) + .arg(this->getName(true)) + .arg(this->getTypeName()), + ERR_ASG_DUPLIC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + + chk_constrs[name] = expr; + setCodeInvalidated(true); +} + +void Domain::removeCheckConstraints(void) +{ + chk_constrs.clear(); +} + +attribs_map Domain::getCheckConstraints(void) +{ + return(chk_constrs); } void Domain::setName(const QString &name) @@ -52,22 +84,6 @@ void Domain::setSchema(BaseObject *schema) PgSQLType::renameUserType(prev_name, this, this->getName(true)); } -void Domain::setConstraintName(const QString &constr_name) -{ - //Raises an error if the constraint name is invalid - if(!constr_name.isEmpty() && !BaseObject::isValidName(constr_name)) - throw Exception(ERR_ASG_INV_NAME_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); - - setCodeInvalidated(constraint_name != constr_name); - this->constraint_name=constr_name; -} - -void Domain::setExpression(const QString &expr) -{ - setCodeInvalidated(expression != expr); - this->expression=expr; -} - void Domain::setDefaultValue(const QString &default_val) { QString def=default_val.trimmed(); @@ -88,16 +104,6 @@ void Domain::setType(PgSQLType type) this->type=type; } -QString Domain::getConstraintName(void) -{ - return(constraint_name); -} - -QString Domain::getExpression(void) -{ - return(expression); -} - QString Domain::getDefaultValue(void) { return(default_value); @@ -118,17 +124,22 @@ QString Domain::getCodeDefinition(unsigned def_type) QString code_def=getCachedCode(def_type, false); if(!code_def.isEmpty()) return(code_def); + attribs_map aux_attribs; + attributes[ParsersAttributes::NOT_NULL]=(not_null ? ParsersAttributes::_TRUE_ : QString()); attributes[ParsersAttributes::DEFAULT_VALUE]=default_value; - attributes[ParsersAttributes::EXPRESSION]=expression; - attributes[ParsersAttributes::CONSTRAINT]=BaseObject::formatName(constraint_name); + + for(auto itr : chk_constrs) + { + aux_attribs[ParsersAttributes::NAME] = itr.first; + aux_attribs[ParsersAttributes::EXPRESSION] = itr.second; + attributes[ParsersAttributes::CONSTRAINTS]+=schparser.getCodeDefinition(ParsersAttributes::DOM_CONSTRAINT, aux_attribs, def_type); + } if(def_type==SchemaParser::SQL_DEFINITION) attributes[ParsersAttributes::TYPE]=(*type); else - { attributes[ParsersAttributes::TYPE]=type.getCodeDefinition(def_type); - } return(BaseObject::__getCodeDefinition(def_type)); } @@ -138,11 +149,10 @@ void Domain::operator = (Domain &domain) QString prev_name=this->getName(true); *(dynamic_cast(this))=dynamic_cast(domain); - this->constraint_name=domain.constraint_name; - this->expression=domain.expression; this->not_null=domain.not_null; this->default_value=domain.default_value; this->type=domain.type; + this->chk_constrs=domain.chk_constrs; PgSQLType::renameUserType(prev_name, this, this->getName(true)); } @@ -156,10 +166,12 @@ QString Domain::getAlterDefinition(BaseObject *object) try { QString alter_def=BaseObject::getAlterDefinition(object); + attribs_map orig_constrs, aux_constrs, aux_attribs; + QString orig_expr, aux_expr; attributes[ParsersAttributes::DEFAULT_VALUE]=QString(); attributes[ParsersAttributes::NOT_NULL]=QString(); - attributes[ParsersAttributes::CONSTRAINT]=QString(); + attributes[ParsersAttributes::CONSTRAINTS]=QString(); attributes[ParsersAttributes::EXPRESSION]=QString(); attributes[ParsersAttributes::OLD_NAME]=QString(); attributes[ParsersAttributes::NEW_NAME]=QString(); @@ -170,17 +182,44 @@ QString Domain::getAlterDefinition(BaseObject *object) if(this->not_null!=domain->not_null) attributes[ParsersAttributes::NOT_NULL]=(domain->not_null ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); - if(this->expression!=domain->expression) + orig_constrs = this->chk_constrs; + aux_constrs = domain->chk_constrs; + aux_attribs[ParsersAttributes::SQL_OBJECT] = this->getSQLName(); + aux_attribs[ParsersAttributes::SIGNATURE] = this->getSignature(); + + //Generating the DROP for check constraints that does not exists anymore + for(auto constr : orig_constrs) { - attributes[ParsersAttributes::CONSTRAINT]=domain->constraint_name; - attributes[ParsersAttributes::EXPRESSION]=(!domain->expression.isEmpty() ? domain->expression : ParsersAttributes::UNSET); + orig_expr = QString(constr.second).remove(QChar(' ')).toLower(); + aux_expr = QString(aux_constrs[constr.first]).remove(QChar(' ')).toLower(); + + //If the check constraint expression exists and the expressions differ from source to destination we drop it + if(aux_constrs.count(constr.first) == 0 || + (aux_constrs.count(constr.first) && orig_expr != aux_expr)) + { + aux_attribs[ParsersAttributes::NAME]=constr.first; + aux_attribs[ParsersAttributes::EXPRESSION]=ParsersAttributes::UNSET; + attributes[ParsersAttributes::CONSTRAINTS]+=BaseObject::getAlterDefinition(ParsersAttributes::DOM_CONSTRAINT, aux_attribs, false, true); + } + + //We should include a command to recreate the check constraint with the new expression + if(aux_constrs.count(constr.first) && orig_expr != aux_expr) + { + aux_attribs[ParsersAttributes::NAME]=constr.first; + aux_attribs[ParsersAttributes::EXPRESSION]=aux_constrs[constr.first]; + attributes[ParsersAttributes::CONSTRAINTS]+=BaseObject::getAlterDefinition(ParsersAttributes::DOM_CONSTRAINT, aux_attribs, false, true); + } } - if(!this->constraint_name.isEmpty() && !domain->constraint_name.isEmpty() && - this->constraint_name!=domain->constraint_name) + //Generating the ADD for new check constraints + for(auto constr : aux_constrs) { - attributes[ParsersAttributes::OLD_NAME]=this->constraint_name; - attributes[ParsersAttributes::NEW_NAME]=domain->constraint_name; + if(orig_constrs.count(constr.first) == 0) + { + aux_attribs[ParsersAttributes::NAME]=constr.first; + aux_attribs[ParsersAttributes::EXPRESSION]=constr.second; + attributes[ParsersAttributes::CONSTRAINTS]+=BaseObject::getAlterDefinition(ParsersAttributes::DOM_CONSTRAINT, aux_attribs, false, true); + } } alter_def+=BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, true); diff --git a/libpgmodeler/src/domain.h b/libpgmodeler/src/domain.h index 8e419946b..8ca4b9e3b 100644 --- a/libpgmodeler/src/domain.h +++ b/libpgmodeler/src/domain.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -31,12 +31,8 @@ class Domain: public BaseObject{ private: - //! \brief Constraint name used by the domain - QString constraint_name, - //! \brief Validation expression used by domain (check) constraint - expression, //! \brief Domain default data type value - default_value; + QString default_value; //! \brief Indicates that the domains accepts null values or not bool not_null; @@ -44,14 +40,17 @@ class Domain: public BaseObject{ //! \brief Domain data type PgSQLType type; + //! \brief Store the check constraint expressions (key:name value:expression) + attribs_map chk_constrs; + public: Domain(void); - //! \brief Sets the domain's constraint name - void setConstraintName(const QString &constr_name); + void addCheckConstraint(const QString &name, const QString &expr); + + void removeCheckConstraints(void); - //! \brief Sets the check expression of the domain - void setExpression(const QString &expr); + attribs_map getCheckConstraints(void); //! \brief Sets the default value of the domain void setDefaultValue(const QString &default_val); diff --git a/libpgmodeler/src/element.cpp b/libpgmodeler/src/element.cpp index 530fc169a..9cdb02407 100644 --- a/libpgmodeler/src/element.cpp +++ b/libpgmodeler/src/element.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/element.h b/libpgmodeler/src/element.h index b39a5ed50..181161a8b 100644 --- a/libpgmodeler/src/element.h +++ b/libpgmodeler/src/element.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/eventtrigger.cpp b/libpgmodeler/src/eventtrigger.cpp index e8c388d3f..7d5edd7a8 100644 --- a/libpgmodeler/src/eventtrigger.cpp +++ b/libpgmodeler/src/eventtrigger.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/eventtrigger.h b/libpgmodeler/src/eventtrigger.h index cf8bcbcc3..0e81d0452 100644 --- a/libpgmodeler/src/eventtrigger.h +++ b/libpgmodeler/src/eventtrigger.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/excludeelement.h b/libpgmodeler/src/excludeelement.h index 7e7cc4b9e..8f362b8d8 100644 --- a/libpgmodeler/src/excludeelement.h +++ b/libpgmodeler/src/excludeelement.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/extension.cpp b/libpgmodeler/src/extension.cpp index aced680b6..d4ef4246b 100644 --- a/libpgmodeler/src/extension.cpp +++ b/libpgmodeler/src/extension.cpp @@ -28,23 +28,21 @@ void Extension::setName(const QString &name) void Extension::setSchema(BaseObject *schema) { - if(!handles_type) - BaseObject::setSchema(schema); + if(!schema) + this->schema = schema; else { - QString prev_name; - - prev_name=this->getName(true); BaseObject::setSchema(schema); - //Renames the PostgreSQL type represented by the extension - PgSQLType::renameUserType(prev_name, this, this->getName(true)); - } -} + if(handles_type) + { + QString prev_name; + prev_name=this->getName(true); -QString Extension::getSignature(bool format) -{ - return(getName(format, false)); + //Renames the PostgreSQL type represented by the extension + PgSQLType::renameUserType(prev_name, this, this->getName(true)); + } + } } void Extension::setHandlesType(bool value) @@ -119,6 +117,22 @@ QString Extension::getAlterDefinition(BaseObject *object) } } +QString Extension::getDropDefinition(bool cascade) +{ + attributes[ParsersAttributes::NAME] = this->getName(); + return(BaseObject::getDropDefinition(cascade)); +} + +QString Extension::getSignature(bool format) +{ + return(this->getName(format, false)); +} + +QString Extension::getName(bool format, bool) +{ + return(BaseObject::getName(format, false)); +} + void Extension::operator = (Extension &ext) { QString prev_name=this->getName(true); diff --git a/libpgmodeler/src/extension.h b/libpgmodeler/src/extension.h index 60122758d..2ca77f871 100644 --- a/libpgmodeler/src/extension.h +++ b/libpgmodeler/src/extension.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -46,7 +46,6 @@ class Extension: public BaseObject { void setName(const QString &name); void setSchema(BaseObject *schema); - QString getSignature(bool format); /*! \brief Defines if the extension handles a datatype. When setting to true the extension will be registered as a datatype on DatabaseModel class. This method has no effect when @@ -67,6 +66,12 @@ class Extension: public BaseObject { virtual QString getAlterDefinition(BaseObject *object) final; + virtual QString getDropDefinition(bool cascade) final; + + virtual QString getSignature(bool format = true) final; + + virtual QString getName(bool format = false, bool = false) final; + void operator = (Extension &ext); }; diff --git a/libpgmodeler/src/function.cpp b/libpgmodeler/src/function.cpp index 61788dbaf..b7ef235a6 100644 --- a/libpgmodeler/src/function.cpp +++ b/libpgmodeler/src/function.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/function.h b/libpgmodeler/src/function.h index daa51f024..53930e5ff 100644 --- a/libpgmodeler/src/function.h +++ b/libpgmodeler/src/function.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/genericsql.cpp b/libpgmodeler/src/genericsql.cpp index 9f44c796d..bdff78407 100644 --- a/libpgmodeler/src/genericsql.cpp +++ b/libpgmodeler/src/genericsql.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/genericsql.h b/libpgmodeler/src/genericsql.h index 6cd6c9171..b21d0ce50 100644 --- a/libpgmodeler/src/genericsql.h +++ b/libpgmodeler/src/genericsql.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/index.cpp b/libpgmodeler/src/index.cpp index 6f539527d..242e61b5b 100644 --- a/libpgmodeler/src/index.cpp +++ b/libpgmodeler/src/index.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -384,12 +384,11 @@ QString Index::getAlterDefinition(BaseObject *object) try { + attribs_map attribs; attributes[ParsersAttributes::ALTER_CMDS]=BaseObject::getAlterDefinition(object); if(this->indexing_type==index->indexing_type) { - attribs_map attribs; - if(this->fill_factor!=index->fill_factor && index->fill_factor >= 10) attribs[ParsersAttributes::FACTOR]=QString::number(index->fill_factor); @@ -400,10 +399,9 @@ QString Index::getAlterDefinition(BaseObject *object) if(this->indexing_type==IndexingType::gist && this->index_attribs[BUFFERING] != index->index_attribs[BUFFERING]) attribs[ParsersAttributes::BUFFERING]=(index->index_attribs[BUFFERING] ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); - - copyAttributes(attribs); } + copyAttributes(attribs); return(BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, true)); } catch(Exception &e) diff --git a/libpgmodeler/src/index.h b/libpgmodeler/src/index.h index 016f8770f..d372b739b 100644 --- a/libpgmodeler/src/index.h +++ b/libpgmodeler/src/index.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/indexelement.cpp b/libpgmodeler/src/indexelement.cpp index 5a11447c7..95a93d097 100644 --- a/libpgmodeler/src/indexelement.cpp +++ b/libpgmodeler/src/indexelement.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/indexelement.h b/libpgmodeler/src/indexelement.h index 117252699..c472a6bc8 100644 --- a/libpgmodeler/src/indexelement.h +++ b/libpgmodeler/src/indexelement.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/language.cpp b/libpgmodeler/src/language.cpp index a3bcef106..050e3a8ea 100644 --- a/libpgmodeler/src/language.cpp +++ b/libpgmodeler/src/language.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/language.h b/libpgmodeler/src/language.h index 51066f406..c76b41ce4 100644 --- a/libpgmodeler/src/language.h +++ b/libpgmodeler/src/language.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operation.cpp b/libpgmodeler/src/operation.cpp index fab11c7db..21bc64a67 100644 --- a/libpgmodeler/src/operation.cpp +++ b/libpgmodeler/src/operation.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operation.h b/libpgmodeler/src/operation.h index 70c7d3ac8..f8fc51e5f 100644 --- a/libpgmodeler/src/operation.h +++ b/libpgmodeler/src/operation.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operationlist.cpp b/libpgmodeler/src/operationlist.cpp index 46fa18a0f..f5e2d5e75 100644 --- a/libpgmodeler/src/operationlist.cpp +++ b/libpgmodeler/src/operationlist.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operationlist.h b/libpgmodeler/src/operationlist.h index d81aeb6fa..3896d65ed 100644 --- a/libpgmodeler/src/operationlist.h +++ b/libpgmodeler/src/operationlist.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operator.cpp b/libpgmodeler/src/operator.cpp index d7833098b..276ab253f 100644 --- a/libpgmodeler/src/operator.cpp +++ b/libpgmodeler/src/operator.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -262,7 +262,7 @@ QString Operator::getSignature(bool format_name) if(argument_types[i]==QString("\"any\"")) args.push_back(QString("NONE")); else - args.push_back(*argument_types[i]); + args.push_back(argument_types[i].getTypeName(true)); } signature+=QString("(") + args.join(',') + QString(")"); @@ -293,12 +293,12 @@ QString Operator::getCodeDefinition(unsigned def_type, bool reduced_form) if(def_type==SchemaParser::SQL_DEFINITION) { if(argument_types[i]!=QString("\"any\"")) - attributes[type_attribs[i]]=(*argument_types[i]); + attributes[type_attribs[i]]=~argument_types[i]; } else { attributes[type_attribs[i]]=argument_types[i]. - getCodeDefinition(SchemaParser::XML_DEFINITION,type_attribs[i]); + getCodeDefinition(SchemaParser::XML_DEFINITION,type_attribs[i]); } } diff --git a/libpgmodeler/src/operator.h b/libpgmodeler/src/operator.h index dd7e03cac..aa5685e5f 100644 --- a/libpgmodeler/src/operator.h +++ b/libpgmodeler/src/operator.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operatorclass.cpp b/libpgmodeler/src/operatorclass.cpp index 47c1f90a4..514f421b8 100644 --- a/libpgmodeler/src/operatorclass.cpp +++ b/libpgmodeler/src/operatorclass.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operatorclass.h b/libpgmodeler/src/operatorclass.h index eb9b3cdc9..f2b89625d 100644 --- a/libpgmodeler/src/operatorclass.h +++ b/libpgmodeler/src/operatorclass.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operatorclasselement.cpp b/libpgmodeler/src/operatorclasselement.cpp index 179917f0a..1c2b1922f 100644 --- a/libpgmodeler/src/operatorclasselement.cpp +++ b/libpgmodeler/src/operatorclasselement.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operatorclasselement.h b/libpgmodeler/src/operatorclasselement.h index bcb067903..07463ad46 100644 --- a/libpgmodeler/src/operatorclasselement.h +++ b/libpgmodeler/src/operatorclasselement.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operatorfamily.cpp b/libpgmodeler/src/operatorfamily.cpp index 8bdeedd70..3a3cbde95 100644 --- a/libpgmodeler/src/operatorfamily.cpp +++ b/libpgmodeler/src/operatorfamily.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/operatorfamily.h b/libpgmodeler/src/operatorfamily.h index 0c62d6d0c..709ef31c6 100644 --- a/libpgmodeler/src/operatorfamily.h +++ b/libpgmodeler/src/operatorfamily.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/parameter.cpp b/libpgmodeler/src/parameter.cpp index fff5c1e0d..580ad98c4 100644 --- a/libpgmodeler/src/parameter.cpp +++ b/libpgmodeler/src/parameter.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/parameter.h b/libpgmodeler/src/parameter.h index e618afff7..36d7e3c90 100644 --- a/libpgmodeler/src/parameter.h +++ b/libpgmodeler/src/parameter.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/permission.cpp b/libpgmodeler/src/permission.cpp index 44a343a9d..82b59ec76 100644 --- a/libpgmodeler/src/permission.cpp +++ b/libpgmodeler/src/permission.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -115,19 +115,8 @@ bool Permission::objectAcceptsPermission(ObjectType obj_type, int privilege) bool Permission::isRoleExists(Role *role) { - vector::iterator itr, itr_end; - bool found=false; - - itr=roles.begin(); - itr_end=roles.end(); - - while(itr!=itr_end && !found) - { - found=((*itr)==role); - itr++; - } - - return(found); + if(!role) return(false); + return(std::find(roles.begin(), roles.end(), role) != roles.end()); } void Permission::addRole(Role *role) diff --git a/libpgmodeler/src/permission.h b/libpgmodeler/src/permission.h index 005469a09..e0198fa49 100644 --- a/libpgmodeler/src/permission.h +++ b/libpgmodeler/src/permission.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/pgmodelerns.cpp b/libpgmodeler/src/pgmodelerns.cpp index 730047448..84e933a0a 100644 --- a/libpgmodeler/src/pgmodelerns.cpp +++ b/libpgmodeler/src/pgmodelerns.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -81,6 +81,9 @@ namespace PgModelerNS { case OBJ_INDEX: copyObject(psrc_obj, dynamic_cast(copy_obj)); break; + case OBJ_POLICY: + copyObject(psrc_obj, dynamic_cast(copy_obj)); + break; case OBJ_TABLE: copyObject(psrc_obj, dynamic_cast
(copy_obj)); break; diff --git a/libpgmodeler/src/pgmodelerns.h b/libpgmodeler/src/pgmodelerns.h index 50a6602d2..109ddca21 100644 --- a/libpgmodeler/src/pgmodelerns.h +++ b/libpgmodeler/src/pgmodelerns.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -50,11 +50,11 @@ namespace PgModelerNS { /*! \brief Generates a unique name based upon the specified object and the list of objects of the same type. User can specify a suffix for the generated name as well if the comparison inside the method must be done with - formated names */ + formated names. The last optinal parameter indicates that the suffix should be used only in case of conflicts */ template - QString generateUniqueName(BaseObject *obj, vector &obj_vector, bool fmt_name=false, const QString &suffix=QString()) + QString generateUniqueName(BaseObject *obj, vector &obj_vector, bool fmt_name=false, const QString &suffix=QString(), bool use_suf_on_conflict=false) { - unsigned counter=1; + unsigned counter=0; int len=0; QString aux_name, obj_name, id; Class *aux_obj=nullptr; @@ -71,9 +71,10 @@ namespace PgModelerNS { obj_name=obj->getName(fmt_name); obj_type=obj->getObjectType(); - if(obj_type!=OBJ_OPERATOR) + if(!use_suf_on_conflict && obj_type!=OBJ_OPERATOR) obj_name += suffix; + counter = (use_suf_on_conflict && obj_type!= OBJ_OPERATOR? 0 : 1); id=QString::number(obj->getObjectId()); len=obj_name.size() + id.size(); @@ -97,13 +98,19 @@ namespace PgModelerNS { itr++; //If a conflicting object is found - if(aux_obj!=obj && aux_obj->getName(fmt_name)==aux_name) + if(/*aux_obj!=obj &&*/ aux_obj->getName(fmt_name)==aux_name) { //For operators is appended a '?' on the name if(obj_type==OBJ_OPERATOR) aux_name=QString("%1%2").arg(obj_name).arg(QString("").leftJustified(counter++, oper_uniq_chr)); else - aux_name=QString("%1%2").arg(obj_name).arg(counter++); + { + aux_name=QString("%1%2%3") + .arg(obj_name) + .arg(use_suf_on_conflict ? suffix : QString()) + .arg(use_suf_on_conflict && counter == 0 ? QString() : QString::number(counter)); + counter++; + } itr=obj_vector.begin(); } diff --git a/libpgmodeler/src/pgsqltypes.cpp b/libpgmodeler/src/pgsqltypes.cpp index c4868f8d7..745cea71c 100644 --- a/libpgmodeler/src/pgsqltypes.cpp +++ b/libpgmodeler/src/pgsqltypes.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -106,38 +106,39 @@ QString BaseType::type_list[types_count]= "tsrange","tstzrange","daterange", //Object Identification type (OID) - //offsets 108 to 120 + //offsets 108 to 122 "oid", "regproc", "regprocedure", "regoper", "regoperator", "regclass", - "regtype", "regconfig", "regdictionary", - "xid", "cid", "tid", "oidvector", + "regrole", "regnamespace", "regtype", + "regconfig", "regdictionary", "xid", "cid", + "tid", "oidvector", //Pseudo-types - //offsets 121 to 135 + //offsets 123 to 137 "\"any\"","anyarray","anyelement","anyenum", "anynonarray", "anyrange", "cstring","internal","language_handler", "record","trigger","void","opaque", "fdw_handler", "event_trigger", //Interval types - //offsets 136 to 148 + //offsets 138 to 150 "YEAR", "MONTH", "DAY", "HOUR", "MINUTE", "SECOND","YEAR TO MONTH", "DAY TO HOUR","DAY TO MINUTE","DAY TO SECOND", "HOUR TO MINUTE","HOUR TO SECOND","MINUTE TO SECOND", //Types used by the class BehaviorType - //offsets 149 to 151 + //offsets 151 to 153 "CALLED ON NULL INPUT", "RETURNS NULL ON NULL INPUT", "STRICT", //Types used by the class SecurityType - //offsets 152 to 153 + //offsets 154 to 155 "SECURITY INVOKER", "SECURITY DEFINER", //Types used by the class LanguageType - //offsets 154 to 160 + //offsets 156 to 162 "sql", "c", "plpgsql", @@ -147,7 +148,7 @@ QString BaseType::type_list[types_count]= "internal", //Types used by the class EncodingType - //offsets 161 to 202 + //offsets 163 to 204 "UTF8", "BIG5", "EUC_CN", "EUC_JP", "EUC_JIS_2004", "EUC_KR", "EUC_TW", "GB18030", "GBK", "ISO_8859_5", "ISO_8859_6", "ISO_8859_7", "ISO_8859_8", @@ -160,25 +161,25 @@ QString BaseType::type_list[types_count]= "WIN1254", "WIN1255", "WIN1256", "WIN1257", "WIN1258", //Types used by the class StorageType - //offsets 203 to 206 + //offsets 205 to 208 "plain", "external", "extended", "main", //Types used by the class MatchType - //offsets 207 to 209 + //offsets 209 to 211 "MATCH FULL", "MATCH PARTIAL", "MATCH SIMPLE", //Types used by the class DeferralType - //offsets 210 to 211 + //offsets 212 to 213 "INITIALLY IMMEDIATE", "INITIALLY DEFERRED", //Types used by the class CategoryType - //offsets 212 to 225 - See table 44-43 on PostgreSQL 8.4 documentation + //offsets 214 to 227 - See table 44-43 on PostgreSQL 8.4 documentation "U", //User-defined types "A", //Array types "B", //Boolean types @@ -195,7 +196,7 @@ QString BaseType::type_list[types_count]= "X", //Unknown type //Types used by the class FiringType - //offsets 226 to 228 + //offsets 228 to 230 "BEFORE", "AFTER", "INSTEAD OF", @@ -204,7 +205,7 @@ QString BaseType::type_list[types_count]= These types accepts variations Z, M e ZM. > Example: POINT, POINTZ, POINTM, POINTZM Reference: http://postgis.refractions.net/documentation/manual-2.0/using_postgis_dbmanagement.html */ - //offsets 229 to 244 + //offsets 231 to 246 "POINT", "LINESTRING", "POLYGON", @@ -223,16 +224,29 @@ QString BaseType::type_list[types_count]= "MULTISURFACE", //Types used by the class EventTriggerType - //offsets 245 to 248 + //offsets 247 to 250 "ddl_command_start", "ddl_command_end", "sql_drop", - "table_rewrite" + "table_rewrite", + + //Types used by the class IdentityType + //offsets 251 to 252 + "ALWAYS", + "BY DEFAULT", + + //Types used by the class PolicyCmdType + //offsets 253 to 257 + "ALL", + "SELECT", + "INSERT", + "DELETE", + "UPDATE" }; BaseType::BaseType(void) { - type_idx=0; + type_idx=BaseType::null; } QString BaseType::getTypeString(unsigned type_id) @@ -258,7 +272,7 @@ void BaseType::setType(unsigned type_id,unsigned offset,unsigned count) bool BaseType::isTypeValid(unsigned type_id,unsigned offset,unsigned count) { //Returns if the type id is valid according to the specified interval (offset-count) - return((type_id>=offset && type_id<=(offset+count-1)) || type_id==0); + return((type_id>=offset && type_id<=(offset+count-1)) || type_id==BaseType::null); } void BaseType::getTypes(QStringList &types,unsigned offset,unsigned count) @@ -778,8 +792,8 @@ PgSQLType PgSQLType::parseString(const QString &str) { QString type_str=str.toLower().simplified(), sptype, interv; bool with_tz=false; - unsigned len=0, dim=0, srid=0; - int prec=-1; + unsigned dim=0, srid=0; + int prec=-1, len = -1; int start=-1, end=-1; QStringList value, intervals; PgSQLType type; @@ -816,7 +830,7 @@ PgSQLType PgSQLType::parseString(const QString &str) { start=type_str.indexOf('('); end=type_str.indexOf(')', start); - len=type_str.mid(start+1, end-start-1).toUInt(); + len=type_str.mid(start+1, end-start-1).toInt(); } //Check if the type is a numeric type, e.g, numeric(10,2) else if(QRegExp(QString("(.)+\\(( )*[0-9]+( )*(,)( )*[0-9]+( )*\\)")).indexIn(type_str) >=0) @@ -824,7 +838,7 @@ PgSQLType PgSQLType::parseString(const QString &str) start=type_str.indexOf('('); end=type_str.indexOf(')', start); value=type_str.mid(start+1, end-start-1).split(','); - len=value[0].toUInt(); + len=value[0].toInt(); prec=value[1].toUInt(); } //Check if the type is a spatial type (PostGiS), e.g, geography(POINTZ, 4296) @@ -879,7 +893,7 @@ PgSQLType PgSQLType::parseString(const QString &str) type.setLength(len); type.setPrecision(prec); } - else if(type.isDateTimeType() && len > 0) + else if(type.isDateTimeType() && len >= 0) type.setPrecision(len); else if(type.hasVariableLength() && len > 0) type.setLength(len); @@ -967,8 +981,20 @@ unsigned PgSQLType::getTypeId(void) return(!(*this)); } -QString PgSQLType::getTypeName(void) +QString PgSQLType::getTypeName(bool incl_dimension) { + if(incl_dimension) + { + QString type; + + type=~(*this); + + if(type!=QString("void") && dimension > 0) + type+=QString("[]").repeated(dimension); + + return(type); + } + return(~(*this)); } @@ -1567,8 +1593,6 @@ QString PgSQLType::getCodeDefinition(unsigned def_type,QString ref_type) attribs[ParsersAttributes::REF_TYPE]=ref_type; attribs[ParsersAttributes::NAME]=(~(*this)); - - //if(length > 1) attribs[ParsersAttributes::LENGTH]=QString("%1").arg(this->length); if(dimension > 0) @@ -2095,3 +2119,79 @@ unsigned EventTriggerType::operator = (const QString &type_name) return(type_id); } +/*************************** + * CLASS: IdentityMode * + ***************************/ +IdentityType::IdentityType(void) +{ + type_idx=offset; +} + +IdentityType::IdentityType(unsigned type_id) +{ + (*this)=type_id; +} + +IdentityType::IdentityType(const QString &type_name) +{ + (*this)=type_name; +} + +void IdentityType::getTypes(QStringList &tipos) +{ + BaseType::getTypes(tipos,offset,types_count); +} + +unsigned IdentityType::operator = (unsigned type_id) +{ + BaseType::setType(type_id,offset,types_count); + return(type_idx); +} + +unsigned IdentityType::operator = (const QString &type_name) +{ + unsigned type_id; + + type_id=BaseType::getType(type_name, offset, types_count); + BaseType::setType(type_id,offset,types_count); + return(type_id); +} + +/*************************** + * CLASS: PolicyCmdType * + ***************************/ +PolicyCmdType::PolicyCmdType(void) +{ + type_idx=offset; +} + +PolicyCmdType::PolicyCmdType(unsigned type_id) +{ + (*this)=type_id; +} + +PolicyCmdType::PolicyCmdType(const QString &type_name) +{ + (*this)=type_name; +} + +void PolicyCmdType::getTypes(QStringList &tipos) +{ + BaseType::getTypes(tipos,offset,types_count); +} + +unsigned PolicyCmdType::operator = (unsigned type_id) +{ + BaseType::setType(type_id,offset,types_count); + return(type_idx); +} + +unsigned PolicyCmdType::operator = (const QString &type_name) +{ + unsigned type_id; + + type_id=BaseType::getType(type_name, offset, types_count); + BaseType::setType(type_id,offset,types_count); + return(type_id); +} + diff --git a/libpgmodeler/src/pgsqltypes.h b/libpgmodeler/src/pgsqltypes.h index d8e56a0b7..32dc8ee47 100644 --- a/libpgmodeler/src/pgsqltypes.h +++ b/libpgmodeler/src/pgsqltypes.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -33,7 +33,7 @@ class BaseType{ protected: - static const unsigned types_count=249; + static const unsigned types_count=258; static QString type_list[types_count]; //! \brief Index of the type on the type_list vector @@ -210,7 +210,7 @@ class IndexingType: public BaseType{ class IntervalType: public BaseType{ private: - static const unsigned offset=136; + static const unsigned offset=138; static const unsigned types_count=13; public: @@ -280,7 +280,7 @@ class UserTypeConfig { class SpatialType: public BaseType{ private: unsigned variation; - static const unsigned offset=229; + static const unsigned offset=231; static const unsigned types_count=16; /*! \brief Used in conjunction with spatial_type, and denotes the SRID value @@ -319,15 +319,15 @@ class SpatialType: public BaseType{ class PgSQLType: public BaseType{ private: static const unsigned offset=27; - static const unsigned types_count=109; + static const unsigned types_count=111; //! \brief Offset for oid types static const unsigned oid_start=108; - static const unsigned oid_end=120; + static const unsigned oid_end=122; //! \brief Offset for pseudo types - static const unsigned pseudo_start=121; - static const unsigned pseudo_end=135; + static const unsigned pseudo_start=123; + static const unsigned pseudo_end=137; //! \brief Configuration for user defined types static vector user_types; @@ -457,7 +457,7 @@ class PgSQLType: public BaseType{ QString getCodeDefinition(unsigned def_type, QString ref_type=QString()); QString operator ~ (void); - //! \brief Retorns the SQL definition for the type + //! \brief Returns the SQL definition for the type QString operator * (void); unsigned operator << (void *ptype); @@ -481,8 +481,10 @@ class PgSQLType: public BaseType{ //! \brief Returns the code (id) of the type. This is equivalent to call !type unsigned getTypeId(void); - //! \brief Returns the name of the type. This is equivalent to call ~type - QString getTypeName(void); + /*! \brief Returns the name of the type. This is equivalent to call ~type. + * If incl_dimension is true then returns only the type name appending the dimension descriptor [] if the type's dimension is > 0. + * Other attributes of the type are discarded. */ + QString getTypeName(bool incl_dimension); //! \brief Returns the name of the type in SQL form including length, precision and other parameters. This is equivalent to call *type QString getSQLTypeName(void); @@ -498,7 +500,7 @@ class PgSQLType: public BaseType{ class BehaviorType: public BaseType{ private: - static const unsigned offset=149; + static const unsigned offset=151; static const unsigned types_count=3; public: @@ -517,7 +519,7 @@ class BehaviorType: public BaseType{ class SecurityType: public BaseType{ private: - static const unsigned offset=152; + static const unsigned offset=154; static const unsigned types_count=2; public: @@ -535,7 +537,7 @@ class SecurityType: public BaseType{ class LanguageType: public BaseType{ private: - static const unsigned offset=154; + static const unsigned offset=156; static const unsigned types_count=7; public: @@ -558,7 +560,7 @@ class LanguageType: public BaseType{ class EncodingType: public BaseType{ private: - static const unsigned offset=161; + static const unsigned offset=163; static const unsigned types_count=42; public: @@ -578,7 +580,7 @@ class EncodingType: public BaseType{ class StorageType: public BaseType{ private: - static const unsigned offset=203; + static const unsigned offset=207; static const unsigned types_count=4; public: @@ -601,7 +603,7 @@ class StorageType: public BaseType{ class MatchType: public BaseType{ private: - static const unsigned offset=207; + static const unsigned offset=209; static const unsigned types_count=3; public: @@ -620,7 +622,7 @@ class MatchType: public BaseType{ class DeferralType: public BaseType{ private: - static const unsigned offset=210; + static const unsigned offset=212; static const unsigned types_count=2; public: @@ -638,7 +640,7 @@ class DeferralType: public BaseType{ class CategoryType: public BaseType{ private: - static const unsigned offset=212; + static const unsigned offset=214; static const unsigned types_count=14; public: @@ -668,7 +670,7 @@ class CategoryType: public BaseType{ class FiringType: public BaseType{ private: - static const unsigned offset=226; + static const unsigned offset=228; static const unsigned types_count=3; public: @@ -687,7 +689,7 @@ class FiringType: public BaseType{ class EventTriggerType: public BaseType{ private: - static const unsigned offset=245; + static const unsigned offset=247; static const unsigned types_count=4; public: @@ -705,4 +707,43 @@ class EventTriggerType: public BaseType{ unsigned operator = (const QString &type_name); }; +class IdentityType: public BaseType{ + private: + static const unsigned offset=251; + static const unsigned types_count=2; + + public: + static const unsigned always=offset; + static const unsigned by_default=offset+1; + + IdentityType(const QString &type_name); + IdentityType(unsigned type_id); + IdentityType(void); + + static void getTypes(QStringList&type_list); + unsigned operator = (unsigned type_id); + unsigned operator = (const QString &type_name); +}; + +class PolicyCmdType: public BaseType { + private: + static const unsigned offset=253; + static const unsigned types_count=5; + + public: + static const unsigned all=offset; + static const unsigned select=offset+1; + static const unsigned insert=offset+2; + static const unsigned updated=offset+3; + static const unsigned delete_=offset+4; + + PolicyCmdType(const QString &type_name); + PolicyCmdType(unsigned type_id); + PolicyCmdType(void); + + static void getTypes(QStringList&type_list); + unsigned operator = (unsigned type_id); + unsigned operator = (const QString &type_name); +}; + #endif diff --git a/libpgmodeler/src/policy.cpp b/libpgmodeler/src/policy.cpp new file mode 100644 index 000000000..b01a3c5fd --- /dev/null +++ b/libpgmodeler/src/policy.cpp @@ -0,0 +1,189 @@ +/* +# 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 "policy.h" + +Policy::Policy(void) : TableObject() +{ + obj_type=OBJ_POLICY; + permissive = false; + policy_cmd = PolicyCmdType::all; + + attributes[ParsersAttributes::PERMISSIVE] = QString(); + attributes[ParsersAttributes::COMMAND] = QString(); + attributes[ParsersAttributes::USING_EXP] = QString(); + attributes[ParsersAttributes::CHECK_EXP] = QString(); + attributes[ParsersAttributes::ROLES] = QString(); +} + +void Policy::setParentTable(BaseTable *table) +{ + if(table && table->getObjectType() != OBJ_TABLE) + { + throw Exception(Exception::getErrorMessage(ERR_ASG_INV_OBJECT_TYPE) + .arg(this->obj_name) + .arg(this->getTypeName()) + .arg(BaseObject::getTypeName(OBJ_TABLE)), + ERR_ASG_INV_OBJECT_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + + TableObject::setParentTable(table); +} + +void Policy::setPermissive(bool value) +{ + setCodeInvalidated(permissive != value); + permissive = value; +} + +bool Policy::isPermissive(void) +{ + return(permissive); +} + +void Policy::setPolicyCommand(PolicyCmdType cmd) +{ + setCodeInvalidated(policy_cmd != cmd); + policy_cmd = cmd; +} + +PolicyCmdType Policy::getPolicyCommand(void) +{ + return(policy_cmd); +} + +void Policy::setUsingExpression(const QString &expr) +{ + setCodeInvalidated(using_expr != expr); + using_expr = expr; +} + +QString Policy::getUsingExpression(void) +{ + return(using_expr); +} + +void Policy::setCheckExpression(const QString &expr) +{ + setCodeInvalidated(check_expr != expr); + check_expr = expr; +} + +QString Policy::getCheckExpression(void) +{ + return(check_expr); +} + +void Policy::addRole(Role *role) +{ + if(!role) + throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(std::find(roles.begin(), roles.end(), role) == roles.end()) + roles.push_back(role); +} + +void Policy::removeRoles(void) +{ + roles.clear(); + setCodeInvalidated(true); +} + +vector Policy::getRoles(void) +{ + return(roles); +} + +QString Policy::getCodeDefinition(unsigned def_type) +{ + QString code_def=getCachedCode(def_type, false); + if(!code_def.isEmpty()) return(code_def); + + QStringList rol_names; + + if(getParentTable()) + attributes[ParsersAttributes::TABLE]=getParentTable()->getName(true); + + attributes[ParsersAttributes::COMMAND] = ~policy_cmd; + + for(auto role : roles) + rol_names.append(role->getName(true)); + + attributes[ParsersAttributes::PERMISSIVE] = (permissive ? ParsersAttributes::_TRUE_ : QString()); + attributes[ParsersAttributes::USING_EXP] = using_expr; + attributes[ParsersAttributes::CHECK_EXP] = check_expr; + attributes[ParsersAttributes::ROLES] = rol_names.join(QString(", ")); + + return(BaseObject::__getCodeDefinition(def_type)); +} + +QString Policy::getSignature(bool format) +{ + if(!getParentTable()) + return(BaseObject::getSignature(format)); + + return(QString("%1 ON %2").arg(this->getName(format)).arg(getParentTable()->getSignature(true))); +} + +QString Policy::getAlterDefinition(BaseObject *object) +{ + Policy *policy=dynamic_cast(object); + + if(!policy) + throw Exception(ERR_OPR_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + try + { + QStringList rol_names, aux_rol_names; + attribs_map attribs; + + attributes[ParsersAttributes::ALTER_CMDS]=BaseObject::getAlterDefinition(object); + + if(this->using_expr.simplified() != policy->using_expr.simplified()) + attribs[ParsersAttributes::USING_EXP] = policy->using_expr; + + if(this->check_expr.simplified() != policy->check_expr.simplified()) + attribs[ParsersAttributes::CHECK_EXP] = policy->check_expr; + + for(auto role : this->roles) + rol_names.append(role->getName(true)); + + for(auto role : policy->roles) + aux_rol_names.append(role->getName(true)); + + rol_names.sort(); + aux_rol_names.sort(); + + if(!rol_names.isEmpty() && aux_rol_names.isEmpty()) + attribs[ParsersAttributes::ROLES] = ParsersAttributes::UNSET; + else if(rol_names.join(QString(", ")) != aux_rol_names.join(QString(", "))) + attribs[ParsersAttributes::ROLES] = aux_rol_names.join(QString(", ")); + + copyAttributes(attribs); + return(BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, true)); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); + } +} + +bool Policy::isRoleExists(Role *role) +{ + if(!role) return(false); + return(std::find(roles.begin(), roles.end(), role) != roles.end()); +} diff --git a/libpgmodeler/src/policy.h b/libpgmodeler/src/policy.h new file mode 100644 index 000000000..cda7614ea --- /dev/null +++ b/libpgmodeler/src/policy.h @@ -0,0 +1,99 @@ +/* +# 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 +\class Policy +\brief Implements the operations to manipulate row level security (RLS). +*/ + +#ifndef POLICY_H +#define POLICY_H + +#include "tableobject.h" +#include "role.h" + +class Policy : public TableObject { + private: + /*! \brief Roles that has permissions over the object. This vector can be + empty indicating that all roles on the cluster has permission over + the object. */ + vector roles; + + //! \brief Defines the USING expression applied to queries referencing the table which policy is applied + QString using_expr, + + //! \brief Defines the CHECK expression applied to INSERT/UPDATE queries + check_expr; + + /*! \brief Indicates if the policy is permissive. Permissive policies are combined using OR operator by PostgreSQL + and reducing the set of records accessed by a query. When the policy is restrictive the policies are combined using AND. + By default, a policy is permissive. */ + bool permissive; + + PolicyCmdType policy_cmd; + + public: + Policy(void); + + virtual void setParentTable(BaseTable *table) final; + + //! \brief Defines if the the policy is permissive or restrictive + void setPermissive(bool value); + + //! \brief Returns if the policy is permissive or restrictive + bool isPermissive(void); + + //! \brief Defines the command affected by the policy. + void setPolicyCommand(PolicyCmdType cmd); + + //! \brief Returns the policy affected command + PolicyCmdType getPolicyCommand(void); + + //! \brief Defines the USING expresion of the policy + void setUsingExpression(const QString &expr); + + //! \brief Returns the USING expresion of the policy + QString getUsingExpression(void); + + //! \brief Defines the CHECK expresion of the policy + void setCheckExpression(const QString &expr); + + //! \brief Returns the CHECK expresion of the policy + QString getCheckExpression(void); + + //! \brief Adds a role that will have privileges over the object + void addRole(Role *role); + + //! \brief Remove all roles from the policy + void removeRoles(void); + + //! \brief Returns all the roles that is used by the policy + vector getRoles(void); + + //! \brief Returns the SQL / XML definition for the policy + virtual QString getCodeDefinition(unsigned def_type) final; + + virtual QString getSignature(bool format=false) final; + + virtual QString getAlterDefinition(BaseObject *object) final; + + bool isRoleExists(Role *role); +}; + +#endif diff --git a/libpgmodeler/src/reference.cpp b/libpgmodeler/src/reference.cpp index 03cdc5232..68e3537f5 100644 --- a/libpgmodeler/src/reference.cpp +++ b/libpgmodeler/src/reference.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/reference.h b/libpgmodeler/src/reference.h index 17987f5f1..0067a7759 100644 --- a/libpgmodeler/src/reference.h +++ b/libpgmodeler/src/reference.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -56,7 +56,8 @@ class Reference { static const unsigned SQL_REFER_WHERE=10, SQL_REFER_SELECT=20, SQL_REFER_FROM=30, - SQL_VIEW_DEFINITION=40; + SQL_REFER_END_EXPR=40, + SQL_VIEW_DEFINITION=50; Reference(void); diff --git a/libpgmodeler/src/relationship.cpp b/libpgmodeler/src/relationship.cpp index a0dcabdce..bd244cd1d 100644 --- a/libpgmodeler/src/relationship.cpp +++ b/libpgmodeler/src/relationship.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -2542,3 +2542,21 @@ QString Relationship::getInheritDefinition(bool undo_inherit) return(BaseObject::getAlterDefinition(this->getSchemaName(), attributes)); } + +bool Relationship::isReferenceTableMandatory(void) +{ + if(rel_type == BaseRelationship::RELATIONSHIP_11 && getReferenceTable() == dst_table && !src_mandatory) + return(dst_mandatory); + else + return((getReferenceTable() == src_table && isTableMandatory(SRC_TABLE)) || + (getReferenceTable() == dst_table && isTableMandatory(DST_TABLE))); +} + +bool Relationship::isReceiverTableMandatory(void) +{ + if(rel_type == BaseRelationship::RELATIONSHIP_11 && getReferenceTable() == dst_table && !src_mandatory) + return(false); + else + return((getReceiverTable() == src_table && isTableMandatory(SRC_TABLE)) || + (getReceiverTable() == dst_table && isTableMandatory(DST_TABLE))); +} diff --git a/libpgmodeler/src/relationship.h b/libpgmodeler/src/relationship.h index 2aa6f29c3..86d56a552 100644 --- a/libpgmodeler/src/relationship.h +++ b/libpgmodeler/src/relationship.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -484,6 +484,12 @@ class Relationship: public BaseRelationship { QString getInheritDefinition(bool undo_inherit); + //! \brief Returns true when the reference table is mandatory in the relationship + bool isReferenceTableMandatory(void); + + //! \brief Returns true when the receiver table is mandatory in the relationship + bool isReceiverTableMandatory(void); + friend class DatabaseModel; friend class ModelWidget; friend class RelationshipWidget; diff --git a/libpgmodeler/src/role.cpp b/libpgmodeler/src/role.cpp index ce1f660b6..982ee2ca2 100644 --- a/libpgmodeler/src/role.cpp +++ b/libpgmodeler/src/role.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -25,7 +25,7 @@ Role::Role(void) obj_type=OBJ_ROLE; object_id=Role::role_id++; - for(unsigned i=0; i <= OP_REPLICATION; i++) + for(unsigned i=0; i <= OP_BYPASSRLS; i++) options[i]=false; conn_limit=-1; @@ -44,11 +44,12 @@ Role::Role(void) attributes[ParsersAttributes::ADMIN_ROLES]=QString(); attributes[ParsersAttributes::REPLICATION]=QString(); attributes[ParsersAttributes::GROUP]=QString(); + attributes[ParsersAttributes::BYPASSRLS]=QString(); } void Role::setOption(unsigned op_type, bool value) { - if(op_type > OP_REPLICATION) + if(op_type > OP_BYPASSRLS) //Raises an error if the option type is invalid throw Exception(ERR_ASG_VAL_INV_ROLE_OPT_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); @@ -261,7 +262,7 @@ bool Role::isRoleExists(unsigned role_type, Role *role) bool Role::getOption(unsigned op_type) { - if(op_type > OP_REPLICATION) + if(op_type > OP_BYPASSRLS) throw Exception(ERR_ASG_VAL_INV_ROLE_OPT_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); return(options[op_type]); @@ -331,13 +332,13 @@ QString Role::getCodeDefinition(unsigned def_type) QString op_attribs[]={ ParsersAttributes::SUPERUSER, ParsersAttributes::CREATEDB, ParsersAttributes::CREATEROLE, ParsersAttributes::INHERIT, ParsersAttributes::LOGIN, ParsersAttributes::ENCRYPTED, - ParsersAttributes::REPLICATION }; + ParsersAttributes::REPLICATION, ParsersAttributes::BYPASSRLS }; setRoleAttribute(REF_ROLE); setRoleAttribute(MEMBER_ROLE); setRoleAttribute(ADMIN_ROLE); - for(i=0; i <= OP_REPLICATION; i++) + for(i=0; i <= OP_BYPASSRLS; i++) attributes[op_attribs[i]]=(options[i] ? ParsersAttributes::_TRUE_ : QString()); attributes[ParsersAttributes::PASSWORD]=password; @@ -362,7 +363,7 @@ QString Role::getAlterDefinition(BaseObject *object, bool ignore_name_diff) QString op_attribs[]={ ParsersAttributes::SUPERUSER, ParsersAttributes::CREATEDB, ParsersAttributes::CREATEROLE, ParsersAttributes::INHERIT, ParsersAttributes::LOGIN, ParsersAttributes::ENCRYPTED, - ParsersAttributes::REPLICATION }; + ParsersAttributes::REPLICATION, ParsersAttributes::BYPASSRLS }; attributes[ParsersAttributes::ALTER_CMDS]=BaseObject::getAlterDefinition(object, ignore_name_diff); @@ -372,7 +373,7 @@ QString Role::getAlterDefinition(BaseObject *object, bool ignore_name_diff) if(this->validity!=role->validity) attribs[ParsersAttributes::VALIDITY]=role->validity; - for(unsigned i=0; i <= OP_REPLICATION; i++) + for(unsigned i=0; i <= OP_BYPASSRLS; i++) { if((attribs.count(ParsersAttributes::PASSWORD) && i==OP_ENCRYPTED) || this->options[i]!=role->options[i]) diff --git a/libpgmodeler/src/role.h b/libpgmodeler/src/role.h index a25eb5a73..df8a48686 100644 --- a/libpgmodeler/src/role.h +++ b/libpgmodeler/src/role.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -33,8 +33,8 @@ class Role: public BaseObject { static unsigned role_id; /*! \brief Options for the role (SUPERUSER, CREATEDB, CREATEROLE, - INHERIT, LOGIN, ENCRYPTED, REPLICATION) */ - bool options[7]; + INHERIT, LOGIN, ENCRYPTED, REPLICATION, BYPASSRLS) */ + bool options[8]; //! \brief Connection limit for the role int conn_limit; @@ -65,7 +65,8 @@ class Role: public BaseObject { OP_INHERIT=3, OP_LOGIN=4, OP_ENCRYPTED=5, - OP_REPLICATION=6; + OP_REPLICATION=6, + OP_BYPASSRLS=7; //! \brief Constants used to reference the internal role lists of the class static const unsigned REF_ROLE=10, diff --git a/libpgmodeler/src/rule.cpp b/libpgmodeler/src/rule.cpp index d8370202e..f8364202e 100644 --- a/libpgmodeler/src/rule.cpp +++ b/libpgmodeler/src/rule.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/rule.h b/libpgmodeler/src/rule.h index 1e4d1cd49..90379857e 100644 --- a/libpgmodeler/src/rule.h +++ b/libpgmodeler/src/rule.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/schema.cpp b/libpgmodeler/src/schema.cpp index ced7832be..9ee5d93d3 100644 --- a/libpgmodeler/src/schema.cpp +++ b/libpgmodeler/src/schema.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/schema.h b/libpgmodeler/src/schema.h index e0015b6af..99174dcb2 100644 --- a/libpgmodeler/src/schema.h +++ b/libpgmodeler/src/schema.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/sequence.cpp b/libpgmodeler/src/sequence.cpp index 9b86b2c46..808df35f2 100644 --- a/libpgmodeler/src/sequence.cpp +++ b/libpgmodeler/src/sequence.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -41,6 +41,7 @@ Sequence::Sequence(void) attributes[ParsersAttributes::OWNER_COLUMN]=QString(); attributes[ParsersAttributes::TABLE]=QString(); attributes[ParsersAttributes::COLUMN]=QString(); + attributes[ParsersAttributes::COL_IS_IDENTITY]=QString(); } bool Sequence::isNullValue(const QString &value) @@ -394,6 +395,9 @@ QString Sequence::getCodeDefinition(unsigned def_type) attributes[ParsersAttributes::TABLE]=(table ? table->getName(true) : QString()); attributes[ParsersAttributes::COLUMN]=(owner_col ? owner_col->getName(true) : QString()); + attributes[ParsersAttributes::COL_IS_IDENTITY]= + (owner_col && owner_col->getIdentityType() != BaseType::null ? ParsersAttributes::_TRUE_ : QString()); + attributes[ParsersAttributes::INCREMENT]=increment; attributes[ParsersAttributes::MIN_VALUE]=min_value; attributes[ParsersAttributes::MAX_VALUE]=max_value; diff --git a/libpgmodeler/src/sequence.h b/libpgmodeler/src/sequence.h index 9d21bb9e7..4f7bd2cf5 100644 --- a/libpgmodeler/src/sequence.h +++ b/libpgmodeler/src/sequence.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/table.cpp b/libpgmodeler/src/table.cpp index e28d1a1fa..3daa505f4 100644 --- a/libpgmodeler/src/table.cpp +++ b/libpgmodeler/src/table.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -25,7 +25,7 @@ const QString Table::DATA_LINE_BREAK = QString("%1%2").arg("⸣").arg('\n'); Table::Table(void) : BaseTable() { obj_type=OBJ_TABLE; - with_oid=gen_alter_cmds=unlogged=false; + with_oid=gen_alter_cmds=unlogged=rls_enabled=rls_forced=false; attributes[ParsersAttributes::COLUMNS]=QString(); attributes[ParsersAttributes::INH_COLUMNS]=QString(); attributes[ParsersAttributes::CONSTRAINTS]=QString(); @@ -39,6 +39,8 @@ Table::Table(void) : BaseTable() attributes[ParsersAttributes::CONSTR_INDEXES]=QString(); attributes[ParsersAttributes::UNLOGGED]=QString(); attributes[ParsersAttributes::INITIAL_DATA]=QString(); + attributes[ParsersAttributes::RLS_ENABLED]=QString(); + attributes[ParsersAttributes::RLS_FORCED]=QString(); copy_table=nullptr; this->setName(trUtf8("new_table").toUtf8()); @@ -83,6 +85,18 @@ void Table::setUnlogged(bool value) unlogged=value; } +void Table::setRLSEnabled(bool value) +{ + setCodeInvalidated(rls_enabled != value); + rls_enabled = value; +} + +void Table::setRLSForced(bool value) +{ + setCodeInvalidated(rls_forced != value); + rls_forced = value; +} + void Table::setProtected(bool value) { ObjectType obj_types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, @@ -303,6 +317,8 @@ vector *Table::getObjectList(ObjectType obj_type) return(&triggers); else if(obj_type==OBJ_INDEX) return(&indexes); + else if(obj_type==OBJ_POLICY) + return(&policies); else throw Exception(ERR_OBT_OBJ_INVALID_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); } @@ -355,6 +371,7 @@ void Table::addObject(BaseObject *obj, int obj_idx) case OBJ_TRIGGER: case OBJ_INDEX: case OBJ_RULE: + case OBJ_POLICY: TableObject *tab_obj; vector *obj_list; Column *col; @@ -493,6 +510,18 @@ void Table::addRule(Rule *reg, int idx_reg) } } +void Table::addPolicy(Policy *pol, int idx_pol) +{ + try + { + addObject(pol, idx_pol); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} + void Table::addConstraint(Constraint *constr, int idx) { try @@ -754,6 +783,30 @@ void Table::removeRule(unsigned idx) } } +void Table::removePolicy(const QString &name) +{ + try + { + removeObject(name, OBJ_POLICY); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} + +void Table::removePolicy(unsigned idx) +{ + try + { + removeObject(idx, OBJ_POLICY); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} + void Table::removeConstraint(const QString &name) { try @@ -1022,6 +1075,17 @@ Rule *Table::getRule(unsigned idx) return(dynamic_cast(getObject(idx,OBJ_RULE))); } +Policy *Table::getPolicy(const QString &name) +{ + int idx; + return(dynamic_cast(getObject(name, OBJ_POLICY,idx))); +} + +Policy *Table::getPolicy(unsigned idx) +{ + return(dynamic_cast(getObject(idx, OBJ_POLICY))); +} + unsigned Table::getColumnCount(void) { return(columns.size()); @@ -1047,6 +1111,11 @@ unsigned Table::getRuleCount(void) return(rules.size()); } +unsigned Table::getPolicyCount(void) +{ + return(policies.size()); +} + unsigned Table::getAncestorTableCount(void) { return(ancestor_tables.size()); @@ -1131,6 +1200,16 @@ bool Table::isUnlogged(void) return(unlogged); } +bool Table::isRLSEnabled(void) +{ + return(rls_enabled); +} + +bool Table::isRLSForced(void) +{ + return(rls_forced); +} + bool Table::isReferTableOnForeignKey(Table *ref_tab) { unsigned count,i; @@ -1358,6 +1437,8 @@ QString Table::getCodeDefinition(unsigned def_type) attributes[ParsersAttributes::OIDS]=(with_oid ? ParsersAttributes::_TRUE_ : QString()); attributes[ParsersAttributes::GEN_ALTER_CMDS]=(gen_alter_cmds ? ParsersAttributes::_TRUE_ : QString()); attributes[ParsersAttributes::UNLOGGED]=(unlogged ? ParsersAttributes::_TRUE_ : QString()); + attributes[ParsersAttributes::RLS_ENABLED]=(rls_enabled ? ParsersAttributes::_TRUE_ : QString()); + attributes[ParsersAttributes::RLS_FORCED]=(rls_forced ? ParsersAttributes::_TRUE_ : QString()); attributes[ParsersAttributes::COPY_TABLE]=QString(); attributes[ParsersAttributes::ANCESTOR_TABLE]=QString(); attributes[ParsersAttributes::TAG]=QString(); @@ -1553,31 +1634,36 @@ void Table::getColumnReferences(Column *column, vector &refs, boo } } -vector Table::getObjects(void) +vector Table::getObjects(bool excl_cols_constr) { vector list; - ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, - OBJ_TRIGGER, OBJ_INDEX, OBJ_RULE }; - unsigned cnt=sizeof(types)/sizeof(ObjectType); + vector types={ OBJ_COLUMN, OBJ_CONSTRAINT, + OBJ_TRIGGER, OBJ_INDEX, OBJ_RULE, OBJ_POLICY }; - for(unsigned i=0; i < cnt; i++) - list.insert(list.end(), getObjectList(types[i])->begin(), getObjectList(types[i])->end()) ; + for(auto type : types) + { + if(excl_cols_constr && (type == OBJ_COLUMN || type == OBJ_CONSTRAINT)) + continue; + + list.insert(list.end(), getObjectList(type)->begin(), getObjectList(type)->end()) ; + } return(list); } +vector Table::getObjects(void) +{ + return(getObjects(false)); +} + void Table::setCodeInvalidated(bool value) { - ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, - OBJ_TRIGGER, OBJ_INDEX, OBJ_RULE }; - unsigned cnt=sizeof(types)/sizeof(ObjectType); - vector *list=nullptr; + vector types={ OBJ_COLUMN, OBJ_CONSTRAINT, + OBJ_TRIGGER, OBJ_INDEX, OBJ_RULE, OBJ_POLICY }; - for(unsigned i=0; i < cnt; i++) + for(auto type : types) { - list=getObjectList(types[i]); - - for(auto &obj : *list) + for(auto &obj : *getObjectList(type)) obj->setCodeInvalidated(value); } @@ -1594,19 +1680,30 @@ QString Table::getAlterDefinition(BaseObject *object) try { QString alter_def; + attribs_map attribs; - attributes[ParsersAttributes::OIDS]=QString(); - attributes[ParsersAttributes::HAS_CHANGES]=QString(); - attributes[ParsersAttributes::ALTER_CMDS]=BaseObject::getAlterDefinition(object, true); + attribs[ParsersAttributes::OIDS]=QString(); + attribs[ParsersAttributes::ALTER_CMDS]=BaseObject::getAlterDefinition(object, true); - if(this->getName()==tab->getName() && this->with_oid!=tab->with_oid) + if(this->getName()==tab->getName()) { - attributes[ParsersAttributes::OIDS]=(tab->with_oid ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); - attributes[ParsersAttributes::HAS_CHANGES]=ParsersAttributes::_TRUE_; + attribs[ParsersAttributes::HAS_CHANGES]=ParsersAttributes::_TRUE_; + + if(this->with_oid!=tab->with_oid) + attribs[ParsersAttributes::OIDS]=(tab->with_oid ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); + + if(this->unlogged!=tab->unlogged) + attribs[ParsersAttributes::UNLOGGED]=(tab->unlogged ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); + + if(this->rls_enabled!=tab->rls_enabled) + attribs[ParsersAttributes::RLS_ENABLED]=(tab->rls_enabled ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); + + if(this->rls_forced!=tab->rls_forced) + attribs[ParsersAttributes::RLS_FORCED]=(tab->rls_forced ? ParsersAttributes::_TRUE_ : ParsersAttributes::UNSET); } + copyAttributes(attribs); alter_def=BaseObject::getAlterDefinition(this->getSchemaName(), attributes, false, true); - attributes[ParsersAttributes::OIDS]=QString(); return(alter_def); } diff --git a/libpgmodeler/src/table.h b/libpgmodeler/src/table.h index 948216dab..f94db964e 100644 --- a/libpgmodeler/src/table.h +++ b/libpgmodeler/src/table.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,6 +34,7 @@ #include "trigger.h" #include "function.h" #include "role.h" +#include "policy.h" #include "copyoptions.h" #include @@ -49,6 +50,7 @@ class Table: public BaseTable { vector indexes; vector rules; vector triggers; + vector policies; //! \brief Stores the tables that 'this' object inherits attributes vector
ancestor_tables; @@ -68,7 +70,12 @@ class Table: public BaseTable { gen_alter_cmds, //! \brief Indicates if the table is unlogged, which means, is not controled by the WAL (write ahead logs) - unlogged; + unlogged, + + //! \brief Indicates if the row level security is enabled + rls_enabled, + + rls_forced; //! \brief Stores the relationship added column / constraints indexes map col_indexes, constr_indexes; @@ -126,6 +133,12 @@ class Table: public BaseTable { //! \brief Defines if the table is unlogged void setUnlogged(bool value); + //! \brief Defines if the row level security on table is enabled + void setRLSEnabled(bool value); + + //! \brief Defines if the row level security on table is forced for the table owner + void setRLSForced(bool value); + //! \brief Adds an object to the table. It can be inserted at a specified index 'obj_idx'. void addObject(BaseObject *obj, int obj_idx=-1); @@ -159,6 +172,9 @@ class Table: public BaseTable { //! \brief Adds a rule to table (optionally the user can add the object at the specified index 'idx') void addRule(Rule *reg, int idx_reg=-1); + //! \brief Adds a policy to table (optionally the user can add the object at the specified index 'idx') + void addPolicy(Policy *pol, int idx_pol=-1); + //! \brief Configures the copy table void setCopyTable(Table *tab); @@ -202,6 +218,12 @@ class Table: public BaseTable { //! \brief Gets a rule through its index Rule *getRule(unsigned idx); + //! \brief Gets a policy through its name + Policy *getPolicy(const QString &name); + + //! \brief Gets a policy through its index + Policy *getPolicy(unsigned idx); + //! \brief Gets a ancestor table through its name Table *getAncestorTable(const QString &name); @@ -223,6 +245,9 @@ class Table: public BaseTable { //! \brief Gets the rule count unsigned getRuleCount(void); + //! \brief Gets the policy count + unsigned getPolicyCount(void); + //! \brief Gets the ancestor table count unsigned getAncestorTableCount(void); @@ -260,6 +285,12 @@ class Table: public BaseTable { //! \brief Removes a rule through its index void removeRule(unsigned idx); + //! \brief Removes a policy through its name + void removePolicy(const QString &name); + + //! \brief Removes a policy through its index + void removePolicy(unsigned idx); + //! \brief Returns the SQL / XML definition for table virtual QString getCodeDefinition(unsigned def_type) final; @@ -274,7 +305,11 @@ class Table: public BaseTable { //! \brief Returns the primary key of the table. Returns nullptr when it doesn't exists Constraint *getPrimaryKey(void); - //! \brief Returns all child objects of the table + /*! \brief Returns all child objects of the table. If the excl_cols_contr is true + then the method will return all objects except columns and constraint */ + vector getObjects(bool excl_cols_constr); + + //! \brief Returns all child objects of the table. This is the same as call getObjects(false) vector getObjects(void); /*! \brief Stores on the specified vector 'fks' the foreign key present on table. The @@ -288,6 +323,12 @@ class Table: public BaseTable { //! \brief Returns if the table is configured as unlogged bool isUnlogged(void); + //! \brief Returns if RLS is enabled on the table + bool isRLSEnabled(void); + + //! \brief Returns if RLS is forced on the table + bool isRLSForced(void); + //! \brief Protects the table and its aggregated objects against modification void setProtected(bool value); diff --git a/libpgmodeler/src/tableobject.cpp b/libpgmodeler/src/tableobject.cpp index 045a83e7d..0b4b6f500 100644 --- a/libpgmodeler/src/tableobject.cpp +++ b/libpgmodeler/src/tableobject.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -90,7 +90,7 @@ bool TableObject::isDeclaredInTable(void) bool TableObject::isTableObject(ObjectType type) { return(type==OBJ_COLUMN || type==OBJ_CONSTRAINT || type==OBJ_TRIGGER || - type==OBJ_RULE || type==OBJ_INDEX); + type==OBJ_RULE || type==OBJ_INDEX || type==OBJ_POLICY); } void TableObject::operator = (TableObject &object) diff --git a/libpgmodeler/src/tableobject.h b/libpgmodeler/src/tableobject.h index d5e4ee810..06e155d0f 100644 --- a/libpgmodeler/src/tableobject.h +++ b/libpgmodeler/src/tableobject.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -68,7 +68,7 @@ class TableObject: public BaseObject { TableObject(void); //! \brief Defines the parent table for the object - void setParentTable(BaseTable *table); + virtual void setParentTable(BaseTable *table); //! \brief Returns the object parent table BaseTable *getParentTable(void); diff --git a/libpgmodeler/src/tablespace.cpp b/libpgmodeler/src/tablespace.cpp index bc1197088..1531dd87d 100644 --- a/libpgmodeler/src/tablespace.cpp +++ b/libpgmodeler/src/tablespace.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/tablespace.h b/libpgmodeler/src/tablespace.h index cec56a878..4ea005254 100644 --- a/libpgmodeler/src/tablespace.h +++ b/libpgmodeler/src/tablespace.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/tag.cpp b/libpgmodeler/src/tag.cpp index 063b63f6d..0a736bb85 100644 --- a/libpgmodeler/src/tag.cpp +++ b/libpgmodeler/src/tag.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/tag.h b/libpgmodeler/src/tag.h index b4c68bacf..e4ca3a680 100644 --- a/libpgmodeler/src/tag.h +++ b/libpgmodeler/src/tag.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/textbox.cpp b/libpgmodeler/src/textbox.cpp index ac0721251..53ab43417 100644 --- a/libpgmodeler/src/textbox.cpp +++ b/libpgmodeler/src/textbox.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/textbox.h b/libpgmodeler/src/textbox.h index 73e6bd141..321e3f8c0 100644 --- a/libpgmodeler/src/textbox.h +++ b/libpgmodeler/src/textbox.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/trigger.cpp b/libpgmodeler/src/trigger.cpp index acd69776f..0b26af80e 100644 --- a/libpgmodeler/src/trigger.cpp +++ b/libpgmodeler/src/trigger.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/trigger.h b/libpgmodeler/src/trigger.h index 5b1c49611..bc2d86dca 100644 --- a/libpgmodeler/src/trigger.h +++ b/libpgmodeler/src/trigger.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/type.cpp b/libpgmodeler/src/type.cpp index 39de87be8..cc3c5d5c8 100644 --- a/libpgmodeler/src/type.cpp +++ b/libpgmodeler/src/type.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/type.h b/libpgmodeler/src/type.h index 1e767e47b..1d4eb4e37 100644 --- a/libpgmodeler/src/type.h +++ b/libpgmodeler/src/type.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/typeattribute.cpp b/libpgmodeler/src/typeattribute.cpp index 2b1e85a8a..d5add59c4 100644 --- a/libpgmodeler/src/typeattribute.cpp +++ b/libpgmodeler/src/typeattribute.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/typeattribute.h b/libpgmodeler/src/typeattribute.h index ad1dcd9f6..a8385a3c1 100644 --- a/libpgmodeler/src/typeattribute.h +++ b/libpgmodeler/src/typeattribute.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler/src/view.cpp b/libpgmodeler/src/view.cpp index 567fec832..864a50fb4 100644 --- a/libpgmodeler/src/view.cpp +++ b/libpgmodeler/src/view.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,6 +27,7 @@ View::View(void) : BaseTable() attributes[ParsersAttributes::SELECT_EXP]=QString(); attributes[ParsersAttributes::FROM_EXP]=QString(); attributes[ParsersAttributes::SIMPLE_EXP]=QString(); + attributes[ParsersAttributes::END_EXP]=QString(); attributes[ParsersAttributes::CTE_EXPRESSION]=QString(); attributes[ParsersAttributes::MATERIALIZED]=QString(); attributes[ParsersAttributes::RECURSIVE]=QString(); @@ -178,6 +179,8 @@ vector *View::getExpressionList(unsigned sql_type) return(&exp_from); else if(sql_type==Reference::SQL_REFER_WHERE) return(&exp_where); + else if(sql_type==Reference::SQL_REFER_END_EXPR) + return(&exp_end); else return(nullptr); } @@ -334,7 +337,7 @@ Reference View::getReference(unsigned ref_id, unsigned sql_type) void View::removeReference(unsigned ref_id) { - vector *vect_idref[3]={&exp_select, &exp_from, &exp_where}; + vector *vect_idref[4]={&exp_select, &exp_from, &exp_where, &exp_end}; vector::iterator itr, itr_end; unsigned i; @@ -368,6 +371,7 @@ void View::removeReferences(void) exp_select.clear(); exp_from.clear(); exp_where.clear(); + exp_end.clear(); setCodeInvalidated(true); } @@ -426,35 +430,36 @@ void View::setDefinitionAttribute(void) } else { - vector *refs_vect[3]={&exp_select, &exp_from, &exp_where}; + vector *refs_vect[4]={&exp_select, &exp_from, &exp_where, &exp_end}; vector::iterator itr, itr_end; - QString palavras[3]={"SELECT\n", "\nFROM\n", "\nWHERE\n"}; - unsigned i, qtd, idx, tipo_sql[3]={Reference::SQL_REFER_SELECT, - Reference::SQL_REFER_FROM, - Reference::SQL_REFER_WHERE}; + QString keywords[4]={"SELECT\n", "\nFROM\n", "\nWHERE\n", "\n"}; + unsigned i, cnt, idx, sql_type[4]={ Reference::SQL_REFER_SELECT, + Reference::SQL_REFER_FROM, + Reference::SQL_REFER_WHERE, + Reference::SQL_REFER_END_EXPR }; - for(i=0; i < 3; i++) + for(i=0; i < 4; i++) { if(refs_vect[i]->size() > 0) { - decl+=palavras[i]; + decl+=keywords[i]; itr=refs_vect[i]->begin(); itr_end=refs_vect[i]->end(); while(itr!=itr_end) { idx=(*itr); - decl+=references[idx].getSQLDefinition(tipo_sql[i]); + decl+=references[idx].getSQLDefinition(sql_type[i]); itr++; } - if(tipo_sql[i]==Reference::SQL_REFER_SELECT || - tipo_sql[i]==Reference::SQL_REFER_FROM) + if(sql_type[i]==Reference::SQL_REFER_SELECT || + sql_type[i]==Reference::SQL_REFER_FROM) { //Removing the final comma from SELECT / FROM declarations - qtd=decl.size(); - if(decl[qtd-2]==',') - decl.remove(qtd-2,2); + cnt=decl.size(); + if(decl[cnt-2]==',') + decl.remove(cnt-2,2); } } } @@ -472,24 +477,25 @@ void View::setReferencesAttribute(void) { QString str_aux; QString attribs[]={ ParsersAttributes::SELECT_EXP, - ParsersAttributes::FROM_EXP, - ParsersAttributes::SIMPLE_EXP }; - vector *vect_exp[]={&exp_select, &exp_from, &exp_where}; - int qtd, i, i1; - - qtd=references.size(); - for(i=0; i < qtd; i++) + ParsersAttributes::FROM_EXP, + ParsersAttributes::SIMPLE_EXP, + ParsersAttributes::END_EXP}; + vector *vect_exp[]={&exp_select, &exp_from, &exp_where, &exp_end}; + int cnt, i, i1; + + cnt=references.size(); + for(i=0; i < cnt; i++) str_aux+=references[i].getXMLDefinition(); attributes[ParsersAttributes::REFERENCES]=str_aux; - for(i=0; i < 3; i++) + for(i=0; i < 4; i++) { str_aux=QString(); - qtd=vect_exp[i]->size(); - for(i1=0; i1 < qtd; i1++) + cnt=vect_exp[i]->size(); + for(i1=0; i1 < cnt; i1++) { str_aux+=QString("%1").arg(vect_exp[i]->at(i1)); - if(i1 < qtd-1) str_aux+=QString(","); + if(i1 < cnt-1) str_aux+=QString(","); } attributes[attribs[i]]=str_aux; } diff --git a/libpgmodeler/src/view.h b/libpgmodeler/src/view.h index b1ac0de08..8c0547a5e 100644 --- a/libpgmodeler/src/view.h +++ b/libpgmodeler/src/view.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,10 +34,11 @@ class View: public BaseTable { vector references; /*! \brief Vectors that stores indexes to the view references in each - SQL part: SELECT-FROM, FROM-WHERE, after WHERE*/ + SQL part: SELECT-FROM, FROM-WHERE, after WHERE, expressions at the very end of definition (e.g. group by) */ vector exp_select, exp_from, - exp_where; + exp_where, + exp_end; vector triggers; vector rules; diff --git a/libpgmodeler_ui/libpgmodeler_ui.pro b/libpgmodeler_ui/libpgmodeler_ui.pro index 0110edb17..48455934a 100644 --- a/libpgmodeler_ui/libpgmodeler_ui.pro +++ b/libpgmodeler_ui/libpgmodeler_ui.pro @@ -27,7 +27,6 @@ SOURCES += src/mainwindow.cpp \ src/syntaxhighlighter.cpp \ src/databasewidget.cpp \ src/schemawidget.cpp \ - src/objecttablewidget.cpp \ src/rolewidget.cpp \ src/permissionwidget.cpp \ src/tablespacewidget.cpp \ @@ -110,7 +109,11 @@ SOURCES += src/mainwindow.cpp \ src/plaintextitemdelegate.cpp \ src/csvloadwidget.cpp \ src/genericsqlwidget.cpp \ - src/sceneinfowidget.cpp + src/sceneinfowidget.cpp \ + src/bulkdataeditwidget.cpp \ + src/policywidget.cpp \ + src/objectstablewidget.cpp \ + src/resultsetmodel.cpp HEADERS += src/mainwindow.h \ @@ -125,7 +128,6 @@ HEADERS += src/mainwindow.h \ src/syntaxhighlighter.h \ src/databasewidget.h \ src/schemawidget.h \ - src/objecttablewidget.h \ src/rolewidget.h \ src/permissionwidget.h \ src/tablespacewidget.h \ @@ -208,7 +210,11 @@ HEADERS += src/mainwindow.h \ src/plaintextitemdelegate.h \ src/csvloadwidget.h \ src/genericsqlwidget.h \ - src/sceneinfowidget.h + src/sceneinfowidget.h \ + src/bulkdataeditwidget.h \ + src/policywidget.h \ + src/objectstablewidget.h \ + src/resultsetmodel.h FORMS += ui/mainwindow.ui \ ui/textboxwidget.ui \ @@ -219,7 +225,6 @@ FORMS += ui/mainwindow.ui \ ui/sourcecodewidget.ui \ ui/databasewidget.ui \ ui/baseobjectwidget.ui \ - ui/objecttablewidget.ui \ ui/rolewidget.ui \ ui/permissionwidget.ui \ ui/tablespacewidget.ui \ @@ -289,7 +294,10 @@ FORMS += ui/mainwindow.ui \ ui/tabledatawidget.ui \ ui/csvloadwidget.ui \ ui/genericsqlwidget.ui \ - ui/sceneinfowidget.ui + ui/sceneinfowidget.ui \ + ui/bulkdataeditwidget.ui \ + ui/policywidget.ui \ + ui/objectstablewidget.ui unix|windows: LIBS += -L$$OUT_PWD/../libobjrenderer/ -lobjrenderer \ -L$$OUT_PWD/../libpgconnector/ -lpgconnector \ diff --git a/libpgmodeler_ui/res/icones/bulkedit.png b/libpgmodeler_ui/res/icones/bulkedit.png new file mode 100644 index 000000000..e45872a5e Binary files /dev/null and b/libpgmodeler_ui/res/icones/bulkedit.png differ diff --git a/libpgmodeler_ui/res/icones/flag_ecuador.png b/libpgmodeler_ui/res/icones/flag_ecuador.png new file mode 100644 index 000000000..86c720dae Binary files /dev/null and b/libpgmodeler_ui/res/icones/flag_ecuador.png differ diff --git a/libpgmodeler_ui/res/icones/policy.png b/libpgmodeler_ui/res/icones/policy.png new file mode 100644 index 000000000..357b05843 Binary files /dev/null and b/libpgmodeler_ui/res/icones/policy.png differ diff --git a/libpgmodeler_ui/res/icones/policy_grp.png b/libpgmodeler_ui/res/icones/policy_grp.png new file mode 100644 index 000000000..6d5725c76 Binary files /dev/null and b/libpgmodeler_ui/res/icones/policy_grp.png differ diff --git a/libpgmodeler_ui/res/icones/schemarect.png b/libpgmodeler_ui/res/icones/schemarect.png new file mode 100644 index 000000000..71ad337f3 Binary files /dev/null and b/libpgmodeler_ui/res/icones/schemarect.png differ diff --git a/libpgmodeler_ui/res/icones/sortasc.png b/libpgmodeler_ui/res/icones/sortasc.png new file mode 100644 index 000000000..6624f0195 Binary files /dev/null and b/libpgmodeler_ui/res/icones/sortasc.png differ diff --git a/libpgmodeler_ui/res/imagens/crows_foot_notation.png b/libpgmodeler_ui/res/imagens/crows_foot_notation.png new file mode 100644 index 000000000..52da782d9 Binary files /dev/null and b/libpgmodeler_ui/res/imagens/crows_foot_notation.png differ diff --git a/libpgmodeler_ui/res/imagens/rel_center_pnts.png b/libpgmodeler_ui/res/imagens/rel_center_pnts.png index 2fb7ab324..ae47c836c 100644 Binary files a/libpgmodeler_ui/res/imagens/rel_center_pnts.png and b/libpgmodeler_ui/res/imagens/rel_center_pnts.png differ diff --git a/libpgmodeler_ui/res/imagens/rel_fk_to_pk.png b/libpgmodeler_ui/res/imagens/rel_fk_to_pk.png index bdfbddb23..2118cc4ef 100644 Binary files a/libpgmodeler_ui/res/imagens/rel_fk_to_pk.png and b/libpgmodeler_ui/res/imagens/rel_fk_to_pk.png differ diff --git a/libpgmodeler_ui/res/imagens/rel_tab_edges.png b/libpgmodeler_ui/res/imagens/rel_tab_edges.png new file mode 100644 index 000000000..70400784c Binary files /dev/null and b/libpgmodeler_ui/res/imagens/rel_tab_edges.png differ diff --git a/libpgmodeler_ui/res/resources.qrc b/libpgmodeler_ui/res/resources.qrc index 0267ecdba..c4688eecf 100644 --- a/libpgmodeler_ui/res/resources.qrc +++ b/libpgmodeler_ui/res/resources.qrc @@ -233,6 +233,12 @@ icones/aligntogrid.png icones/arrangetables.png icones/jumptotable.png + icones/schemarect.png + icones/flag_ecuador.png + icones/sortasc.png + icones/bulkedit.png + icones/policy_grp.png + icones/policy.png imagens/model2sql.png @@ -248,6 +254,8 @@ imagens/diff2db.png imagens/diff2sql.png imagens/bugreport.png + imagens/crows_foot_notation.png + imagens/rel_tab_edges.png styles/pgmodeler_bg_logo.png diff --git a/libpgmodeler_ui/src/aboutwidget.cpp b/libpgmodeler_ui/src/aboutwidget.cpp index 21338df3c..7e01b667c 100644 --- a/libpgmodeler_ui/src/aboutwidget.cpp +++ b/libpgmodeler_ui/src/aboutwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/aboutwidget.h b/libpgmodeler_ui/src/aboutwidget.h index 1c75f5614..046441549 100644 --- a/libpgmodeler_ui/src/aboutwidget.h +++ b/libpgmodeler_ui/src/aboutwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/aggregatewidget.cpp b/libpgmodeler_ui/src/aggregatewidget.cpp index ff6ae5a3e..38b6169c2 100644 --- a/libpgmodeler_ui/src/aggregatewidget.cpp +++ b/libpgmodeler_ui/src/aggregatewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -37,8 +37,8 @@ AggregateWidget::AggregateWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_ input_type=new PgSQLTypeWidget(this, trUtf8("Input Data Type")); state_type=new PgSQLTypeWidget(this, trUtf8("State Data Type")); - input_types_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - ObjectTableWidget::EDIT_BUTTON, true, this); + input_types_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + ObjectsTableWidget::EDIT_BUTTON, true, this); input_types_tab->setColumnCount(1); funcaoagregacao_grid->addWidget(final_func_sel,0,1,1,1); @@ -83,16 +83,6 @@ AggregateWidget::AggregateWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_ } } -void AggregateWidget::hideEvent(QHideEvent *event) -{ - final_func_sel->clearSelector(); - transition_func_sel->clearSelector(); - sort_op_sel->clearSelector(); - input_types_tab->removeRows(); - initial_cond_txt->clear(); - BaseObjectWidget::hideEvent(event); -} - void AggregateWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Aggregate *aggregate) { unsigned count, i; diff --git a/libpgmodeler_ui/src/aggregatewidget.h b/libpgmodeler_ui/src/aggregatewidget.h index f6e601b14..32b8936d3 100644 --- a/libpgmodeler_ui/src/aggregatewidget.h +++ b/libpgmodeler_ui/src/aggregatewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -29,7 +29,7 @@ #include "baseobjectwidget.h" #include "ui_aggregatewidget.h" #include "pgsqltypewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" class AggregateWidget: public BaseObjectWidget, public Ui::AggregateWidget { private: @@ -44,7 +44,7 @@ class AggregateWidget: public BaseObjectWidget, public Ui::AggregateWidget { /*! \brief Table that stores the multiple input data types. The elements in this table are converted to class PgSQLType and assigned as input types to the aggregat */ - ObjectTableWidget *input_types_tab; + ObjectsTableWidget *input_types_tab; //! \brief Syntax highlighter used by the initial condition field SyntaxHighlighter *initial_cond_hl; @@ -59,7 +59,6 @@ class AggregateWidget: public BaseObjectWidget, public Ui::AggregateWidget { void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Aggregate *aggregate); private slots: - void hideEvent(QHideEvent *event); void handleDataType(int row); public slots: diff --git a/libpgmodeler_ui/src/appearanceconfigwidget.cpp b/libpgmodeler_ui/src/appearanceconfigwidget.cpp index b7c8d4e03..6bfb5c817 100644 --- a/libpgmodeler_ui/src/appearanceconfigwidget.cpp +++ b/libpgmodeler_ui/src/appearanceconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/appearanceconfigwidget.h b/libpgmodeler_ui/src/appearanceconfigwidget.h index 05ff8b4eb..40e64f84c 100644 --- a/libpgmodeler_ui/src/appearanceconfigwidget.h +++ b/libpgmodeler_ui/src/appearanceconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/baseconfigwidget.cpp b/libpgmodeler_ui/src/baseconfigwidget.cpp index 6e7a78d83..e211d74e1 100644 --- a/libpgmodeler_ui/src/baseconfigwidget.cpp +++ b/libpgmodeler_ui/src/baseconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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 92c3e4669..9225a529b 100644 --- a/libpgmodeler_ui/src/baseconfigwidget.h +++ b/libpgmodeler_ui/src/baseconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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 df14069ab..689910088 100644 --- a/libpgmodeler_ui/src/baseform.cpp +++ b/libpgmodeler_ui/src/baseform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -21,7 +21,7 @@ BaseForm::BaseForm(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { setupUi(this); - this->setWindowFlags(this->windowFlags() ^ Qt::WindowContextHelpButtonHint); + this->setWindowFlags((this->windowFlags() | Qt::WindowMinMaxButtonsHint) ^ Qt::WindowContextHelpButtonHint); } void BaseForm::setButtonConfiguration(unsigned button_conf) @@ -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; @@ -111,8 +113,13 @@ void BaseForm::resizeForm(QWidget *widget) if(curr_h > screen->size().height()) curr_h = screen->size().height() * 0.80; - this->setMinimumSize(curr_w, curr_h); - this->resize(this->minimumSize()); + this->setMinimumSize(min_size); + this->resize(curr_w, curr_h); +} + +void BaseForm::closeEvent(QCloseEvent *) +{ + this->reject(); } void BaseForm::setMainWidget(BaseObjectWidget *widget) @@ -129,6 +136,7 @@ void BaseForm::setMainWidget(BaseObjectWidget *widget) setButtonConfiguration(Messagebox::OK_CANCEL_BUTTONS); connect(cancel_btn, SIGNAL(clicked(bool)), this, SLOT(reject())); + //connect(this, SIGNAL(rejected()), widget, SLOT(cancelConfiguration())); connect(apply_ok_btn, SIGNAL(clicked(bool)), widget, SLOT(applyConfiguration())); connect(widget, SIGNAL(s_closeRequested()), this, SLOT(accept())); } diff --git a/libpgmodeler_ui/src/baseform.h b/libpgmodeler_ui/src/baseform.h index 7a2322195..488fc1707 100644 --- a/libpgmodeler_ui/src/baseform.h +++ b/libpgmodeler_ui/src/baseform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -42,6 +42,8 @@ class BaseForm: public QDialog, public Ui::BaseForm { try to preserve the minimum width */ void resizeForm(QWidget *widget); + void closeEvent(QCloseEvent *); + public: BaseForm(QWidget * parent = 0, Qt::WindowFlags f = 0); diff --git a/libpgmodeler_ui/src/baseobjectwidget.cpp b/libpgmodeler_ui/src/baseobjectwidget.cpp index cb9ef1b61..a1f300b21 100644 --- a/libpgmodeler_ui/src/baseobjectwidget.cpp +++ b/libpgmodeler_ui/src/baseobjectwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -126,20 +126,6 @@ bool BaseObjectWidget::isHandledObjectProtected(void) return(object_protected); } -void BaseObjectWidget::hideEvent(QHideEvent *) -{ - name_edt->clear(); - comment_edt->clear(); - - tablespace_sel->clearSelector(); - schema_sel->clearSelector(); - owner_sel->clearSelector(); - collation_sel->clearSelector(); - - disable_sql_chk->setChecked(false); - new_object=false; -} - void BaseObjectWidget::showEvent(QShowEvent *) { name_edt->setFocus(); @@ -149,26 +135,22 @@ void BaseObjectWidget::setRequiredField(QWidget *widget) { if(widget) { - QLabel *lbl=dynamic_cast(widget); - QLineEdit *edt=dynamic_cast(widget); - QTextEdit *txt=dynamic_cast(widget); - QGroupBox *grp=dynamic_cast(widget); + QLabel *lbl=qobject_cast(widget); + QLineEdit *edt=qobject_cast(widget); + QTextEdit *txt=qobject_cast(widget); + QGroupBox *grp=qobject_cast(widget); ObjectSelectorWidget *sel=dynamic_cast(widget); PgSQLTypeWidget *pgtype=dynamic_cast(widget); QString str_aux=QString(" * "); QColor bgcolor=QColor(QString("#ffffc0")); - QFont fnt=widget->font(); - if(lbl || pgtype || grp) { - fnt.setBold(true); - if(lbl) lbl->setText(str_aux + lbl->text()); if(!grp) - widget->setFont(fnt); + widget->setStyleSheet(QString("QWidget { font-weight: bold; }")); else grp->setStyleSheet(QString("QGroupBox { font-weight: bold; }")); } @@ -372,7 +354,7 @@ void BaseObjectWidget::setAttributes(DatabaseModel *model, OperationList *op_lis else name_edt->setText(object->getSignature()); - comment_edt->setText(object->getComment()); + comment_edt->setPlainText(object->getComment()); /* When creating a new table or relationship the object is pre allocated and the flag new_object is set. In order to avoid the selectors to have empty values, we check if the flag is false which means @@ -480,8 +462,11 @@ void BaseObjectWidget::configureFormLayout(QGridLayout *grid, ObjectType obj_typ setRequiredField(name_edt); } - setRequiredField(schema_lbl); - setRequiredField(schema_sel); + if(obj_type!=OBJ_EXTENSION) + { + setRequiredField(schema_lbl); + setRequiredField(schema_sel); + } } if(BaseObject::acceptsCollation(obj_type)) @@ -570,59 +555,47 @@ QFrame *BaseObjectWidget::generateInformationFrame(const QString &msg) return(info_frm); } -QFrame *BaseObjectWidget::generateVersionWarningFrame(map > &fields, - map< QWidget *, vector > *values) +void BaseObjectWidget::highlightVersionSpecificFields(map > &fields, + map< QWidget *, vector > *values) { - QFrame *alert_frm=nullptr; - QGridLayout *grid=nullptr; - QLabel *ico_lbl=nullptr, *msg_lbl=nullptr; QString field_name; - QFont font; - QWidget *wgt=nullptr; - QPalette pal; QColor color=QColor(0,0,128); - map >::iterator itr, itr_end; - vector values_vect; - unsigned i, count, count1, i1; - itr=fields.begin(); - itr_end=fields.end(); - - while(itr!=itr_end) + for(auto itr : fields) { - count=itr->second.size(); - - for(i=0; i < count; i++) + for(auto wgt : itr.second) { - wgt=itr->second.at(i); if(values && values->count(wgt) > 0) { - values_vect=values->at(wgt); - count1=values_vect.size(); - field_name+=QString("
") + trUtf8("Value(s)") + QString(": ("); - for(i1=0; i1 < count1; i1++) + for(auto value : values->at(wgt)) { - field_name+=values_vect.at(i1); - if(i1 < count1-1) field_name+=", "; + field_name += value; + field_name+=", "; } + + field_name.remove(field_name.length() - 2, 2); field_name+=")"; } - font=wgt->font(); - - pal.setBrush(QPalette::Active, QPalette::WindowText, color); - wgt->setPalette(pal); - - font.setBold(true); - font.setItalic(true); - wgt->setFont(font); - wgt->setToolTip(QString("") + trUtf8("Version") + - itr->first + QString(" %1").arg(field_name)); + wgt->setStyleSheet(QString("QWidget { font-weight: bold; font-style: italic; color: %1}").arg(color.name())); + wgt->setToolTip(QString("") + + trUtf8("Version") + + itr.first + QString(" %1").arg(field_name)); } - itr++; } +} +QFrame *BaseObjectWidget::generateVersionWarningFrame(map > &fields, + map< QWidget *, vector > *values) +{ + QFrame *alert_frm=nullptr; + QGridLayout *grid=nullptr; + QLabel *ico_lbl=nullptr, *msg_lbl=nullptr; + QFont font; + QColor color=QColor(0,0,128); + + highlightVersionSpecificFields(fields, values); alert_frm = new QFrame; font.setItalic(false); @@ -700,6 +673,7 @@ void BaseObjectWidget::applyConfiguration(void) ObjectType obj_type=object->getObjectType(); QString obj_name; + QApplication::setOverrideCursor(Qt::WaitCursor); obj_name=BaseObject::formatName(name_edt->text().toUtf8(), obj_type==OBJ_OPERATOR); if(this->object->acceptsSchema() && schema_sel->getSelectedObject()) @@ -764,7 +738,7 @@ void BaseObjectWidget::applyConfiguration(void) //Sets the object's comment if(comment_edt->isVisible()) - object->setComment(comment_edt->text().toUtf8()); + object->setComment(comment_edt->toPlainText().toUtf8()); //Sets the object's tablespace if(tablespace_sel->isVisible()) @@ -791,6 +765,7 @@ void BaseObjectWidget::applyConfiguration(void) } catch(Exception &e) { + QApplication::restoreOverrideCursor(); throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); } } @@ -878,9 +853,13 @@ void BaseObjectWidget::finishConfiguration(void) emit s_objectManipulated(); emit s_closeRequested(); } + + QApplication::restoreOverrideCursor(); } catch(Exception &e) { + QApplication::restoreOverrideCursor(); + if(e.getErrorType()==ERR_ASG_OBJ_INV_DEFINITION) throw Exception(Exception::getErrorMessage(ERR_REQ_FIELDS_NOT_FILLED) .arg(this->object->getName()).arg(this->object->getTypeName()), @@ -892,8 +871,10 @@ void BaseObjectWidget::finishConfiguration(void) void BaseObjectWidget::cancelConfiguration(void) { - ObjectType obj_type; + if(!object) + return; + ObjectType obj_type; obj_type=this->object->getObjectType(); if(new_object) @@ -932,6 +913,7 @@ void BaseObjectWidget::cancelConfiguration(void) catch(Exception &){} } + QApplication::restoreOverrideCursor(); emit s_objectManipulated(); } diff --git a/libpgmodeler_ui/src/baseobjectwidget.h b/libpgmodeler_ui/src/baseobjectwidget.h index b0cae15a5..4f3136391 100644 --- a/libpgmodeler_ui/src/baseobjectwidget.h +++ b/libpgmodeler_ui/src/baseobjectwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -112,15 +112,10 @@ class BaseObjectWidget: public QWidget, public Ui::BaseObjectWidget { /*! \brief Finishes the edition / creation of object, registering it on the operation list and inserts is on the parent object */ void finishConfiguration(void); - - /*! \brief Aborts the object configuration, deallocation it if necessary or restoring it to - its previous configuration */ - virtual void cancelConfiguration(void); - + //! \brief Apply the basic configurations to the object (name, schema, comment, owner, tablespace) virtual void applyConfiguration(void); - void hideEvent(QHideEvent *); void showEvent(QShowEvent *); void setAttributes(DatabaseModel *model, OperationList *op_list, @@ -136,10 +131,7 @@ class BaseObjectWidget: public QWidget, public Ui::BaseObjectWidget { void disableReferencesSQL(BaseObject *object); void configureTabOrder(vector widgets={}); - - //! \brief Executes the proper actions to cancel chained operations. - void cancelChainedOperation(void); - + public: //! \brief Constants used to generate version intervals for version alert frame static const unsigned UNTIL_VERSION=0, @@ -161,6 +153,8 @@ class BaseObjectWidget: public QWidget, public Ui::BaseObjectWidget { //! \brief Generates a informative frame containing the specified message static QFrame *generateInformationFrame(const QString &msg); + + static void highlightVersionSpecificFields(map > &fields, map > *values=nullptr); //! \brief Highlights the specified widget as a required field static void setRequiredField(QWidget *widget); @@ -179,6 +173,13 @@ class BaseObjectWidget: public QWidget, public Ui::BaseObjectWidget { //! \brief Register the new object in the operation history if it is not registered already void registerNewObject(void); + + /*! \brief Aborts the object configuration, deallocation it if necessary or restoring it to + its previous configuration */ + virtual void cancelConfiguration(void); + + //! \brief Executes the proper actions to cancel chained operations. + virtual void cancelChainedOperation(void); signals: //! \brief Signal emitted whenever a object is created / edited using the form @@ -186,6 +187,8 @@ class BaseObjectWidget: public QWidget, public Ui::BaseObjectWidget { //! \brief Signal emitted whenever the object editing was successful and the form need to be closed void s_closeRequested(void); + + friend class BaseForm; }; template diff --git a/libpgmodeler_ui/src/bugreportform.cpp b/libpgmodeler_ui/src/bugreportform.cpp index 10d24642b..2e9262cf4 100644 --- a/libpgmodeler_ui/src/bugreportform.cpp +++ b/libpgmodeler_ui/src/bugreportform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/bugreportform.h b/libpgmodeler_ui/src/bugreportform.h index 6a64b665a..58ce26c9c 100644 --- a/libpgmodeler_ui/src/bugreportform.h +++ b/libpgmodeler_ui/src/bugreportform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/bulkdataeditwidget.cpp b/libpgmodeler_ui/src/bulkdataeditwidget.cpp new file mode 100644 index 000000000..a94af2ac8 --- /dev/null +++ b/libpgmodeler_ui/src/bulkdataeditwidget.cpp @@ -0,0 +1,28 @@ +/* +# 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 "bulkdataeditwidget.h" + +BulkDataEditWidget::BulkDataEditWidget(QWidget *parent) : QWidget(parent) +{ + setupUi(this); +} + +void BulkDataEditWidget::showEvent(QShowEvent *) +{ + value_edt->setFocus(); +} diff --git a/libpgmodeler_ui/src/bulkdataeditwidget.h b/libpgmodeler_ui/src/bulkdataeditwidget.h new file mode 100644 index 000000000..bad6b36ff --- /dev/null +++ b/libpgmodeler_ui/src/bulkdataeditwidget.h @@ -0,0 +1,35 @@ +/* +# 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 +*/ + +#ifndef BULK_DATA_EDIT_WIDGET_H +#define BULK_DATA_EDIT_WIDGET_H + +#include +#include "ui_bulkdataeditwidget.h" + +class BulkDataEditWidget: public QWidget, public Ui::BulkDataEditWidget { + private: + Q_OBJECT + + void showEvent(QShowEvent *); + + public: + BulkDataEditWidget(QWidget *parent = 0); +}; + +#endif diff --git a/libpgmodeler_ui/src/castwidget.cpp b/libpgmodeler_ui/src/castwidget.cpp index be68f6118..4e383e5f1 100644 --- a/libpgmodeler_ui/src/castwidget.cpp +++ b/libpgmodeler_ui/src/castwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -54,7 +54,7 @@ CastWidget::CastWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_CAST) configureTabOrder({ explicit_rb, implicit_rb, assignment_rb, input_output_chk, conv_func_sel, src_datatype, trg_datatype }); - setMinimumSize(520, 420); + setMinimumSize(520, 460); } catch(Exception &e) { @@ -62,14 +62,6 @@ CastWidget::CastWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_CAST) } } -void CastWidget::hideEvent(QHideEvent *event) -{ - input_output_chk->setChecked(false); - implicit_rb->setChecked(true); - conv_func_sel->clearSelector(); - BaseObjectWidget::hideEvent(event); -} - void CastWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Cast *cast) { PgSQLType src_type, trg_type; @@ -108,8 +100,10 @@ void CastWidget::applyConfiguration(void) if(implicit_rb->isChecked()) cast->setCastType(Cast::IMPLICIT); - else + else if(assignment_rb->isChecked()) cast->setCastType(Cast::ASSIGNMENT); + else + cast->setCastType(Cast::EXPLICIT); cast->setCastFunction(dynamic_cast(conv_func_sel->getSelectedObject())); diff --git a/libpgmodeler_ui/src/castwidget.h b/libpgmodeler_ui/src/castwidget.h index a7376b7a3..157a779e7 100644 --- a/libpgmodeler_ui/src/castwidget.h +++ b/libpgmodeler_ui/src/castwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -39,8 +39,6 @@ class CastWidget: public BaseObjectWidget, public Ui::CastWidget { //! \brief Conversion function selector ObjectSelectorWidget *conv_func_sel; - void hideEvent(QHideEvent *event); - public: CastWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, Cast *cast); diff --git a/libpgmodeler_ui/src/codecompletionwidget.cpp b/libpgmodeler_ui/src/codecompletionwidget.cpp index 2c76891f1..737dd633a 100644 --- a/libpgmodeler_ui/src/codecompletionwidget.cpp +++ b/libpgmodeler_ui/src/codecompletionwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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 c9d370920..d8faf7a3d 100644 --- a/libpgmodeler_ui/src/codecompletionwidget.h +++ b/libpgmodeler_ui/src/codecompletionwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/collationwidget.cpp b/libpgmodeler_ui/src/collationwidget.cpp index cf84a448a..ceec9a4bb 100644 --- a/libpgmodeler_ui/src/collationwidget.cpp +++ b/libpgmodeler_ui/src/collationwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -62,7 +62,7 @@ CollationWidget::CollationWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_ configureTabOrder({ locale_cmb, encoding_cmb, lccollate_cmb, lcctype_cmb }); - setMinimumSize(520, 380); + setMinimumSize(520, 420); } catch(Exception &e) { @@ -98,12 +98,6 @@ void CollationWidget::setAttributes(DatabaseModel *model, OperationList *op_list } } -void CollationWidget::hideEvent(QHideEvent *event) -{ - resetFields(); - BaseObjectWidget::hideEvent(event); -} - void CollationWidget::resetFields(void) { //Block object's signals to evict an infinite call to this method @@ -166,10 +160,10 @@ void CollationWidget::applyConfiguration(void) collation->setLocale(locale_cmb->currentText()); if(lccollate_cmb->currentIndex() > 0) - collation->setLocalization(LC_COLLATE, lccollate_cmb->currentText()); + collation->setLocalization(Collation::_LC_COLLATE, lccollate_cmb->currentText()); if(lcctype_cmb->currentIndex() > 0) - collation->setLocalization(LC_CTYPE, lcctype_cmb->currentText()); + collation->setLocalization(Collation::_LC_CTYPE, lcctype_cmb->currentText()); finishConfiguration(); } diff --git a/libpgmodeler_ui/src/collationwidget.h b/libpgmodeler_ui/src/collationwidget.h index 20c876b7b..8a287e5f5 100644 --- a/libpgmodeler_ui/src/collationwidget.h +++ b/libpgmodeler_ui/src/collationwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -32,8 +32,6 @@ class CollationWidget: public BaseObjectWidget, public Ui::CollationWidget { private: Q_OBJECT - void hideEvent(QHideEvent *event); - public: CollationWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Collation *collation); diff --git a/libpgmodeler_ui/src/colorpickerwidget.cpp b/libpgmodeler_ui/src/colorpickerwidget.cpp index 6d529cb68..857c59d71 100644 --- a/libpgmodeler_ui/src/colorpickerwidget.cpp +++ b/libpgmodeler_ui/src/colorpickerwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/colorpickerwidget.h b/libpgmodeler_ui/src/colorpickerwidget.h index e4dd686ec..95e30b361 100644 --- a/libpgmodeler_ui/src/colorpickerwidget.h +++ b/libpgmodeler_ui/src/colorpickerwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/columnwidget.cpp b/libpgmodeler_ui/src/columnwidget.cpp index 5ffe58993..6eb8f8467 100644 --- a/libpgmodeler_ui/src/columnwidget.cpp +++ b/libpgmodeler_ui/src/columnwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -23,13 +23,16 @@ ColumnWidget::ColumnWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_COLUMN try { QSpacerItem *spacer=new QSpacerItem(10,10,QSizePolicy::Fixed,QSizePolicy::Expanding); + QStringList list; + Ui_ColumnWidget::setupUi(this); + + IdentityType::getTypes(list); + identity_type_cmb->addItems(list); data_type=nullptr; data_type=new PgSQLTypeWidget(this); - Ui_ColumnWidget::setupUi(this); - hl_default_value=nullptr; hl_default_value=new SyntaxHighlighter(def_value_txt, true); hl_default_value->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); @@ -37,23 +40,45 @@ ColumnWidget::ColumnWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_COLUMN sequence_sel=new ObjectSelectorWidget(OBJ_SEQUENCE, true, this); sequence_sel->setEnabled(false); - column_grid->addWidget(data_type,0,0,1,0); column_grid->addWidget(default_value_grp,1,0,1,1); column_grid->addItem(spacer,column_grid->count(),0); - dynamic_cast(default_value_grp->layout())->addWidget(sequence_sel, 1, 1); + dynamic_cast(default_value_grp->layout())->addWidget(sequence_sel, 1, 1, 1, 2); configureFormLayout(column_grid, OBJ_COLUMN); configureTabOrder({ data_type }); + map > fields_map; + fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_100)].push_back(identity_rb); + highlightVersionSpecificFields(fields_map); + connect(sequence_rb, &QRadioButton::clicked, - [&](){ sequence_sel->setEnabled(true); def_value_txt->setEnabled(false); }); + [&](){ + sequence_sel->setEnabled(true); + def_value_txt->setEnabled(false); + identity_type_cmb->setEnabled(false); + notnull_chk->setEnabled(true); + }); connect(expression_rb, &QRadioButton::clicked, - [&](){ sequence_sel->setEnabled(false); def_value_txt->setEnabled(true); }); - - setMinimumSize(540, 460); + [&](){ + sequence_sel->setEnabled(false); + def_value_txt->setEnabled(true); + identity_type_cmb->setEnabled(false); + notnull_chk->setEnabled(true); + }); + + connect(identity_rb, &QRadioButton::clicked, + [&](){ + sequence_sel->setEnabled(false); + def_value_txt->setEnabled(false); + identity_type_cmb->setEnabled(true); + notnull_chk->setChecked(true); + notnull_chk->setEnabled(false); + }); + + setMinimumSize(540, 480); } catch(Exception &e) { @@ -61,15 +86,6 @@ ColumnWidget::ColumnWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_COLUMN } } -void ColumnWidget::hideEvent(QHideEvent *event) -{ - def_value_txt->clear(); - notnull_chk->setChecked(false); - sequence_sel->clearSelector(); - expression_rb->setChecked(true); - BaseObjectWidget::hideEvent(event); -} - void ColumnWidget::setAttributes(DatabaseModel *model, OperationList *op_list, BaseObject *parent_obj, Column *column) { PgSQLType type; @@ -92,10 +108,18 @@ void ColumnWidget::setAttributes(DatabaseModel *model, OperationList *op_list, B sequence_sel->setEnabled(true); sequence_sel->setSelectedObject(column->getSequence()); } + else if(column->getIdentityType() != BaseType::null) + { + identity_rb->setChecked(true); + identity_type_cmb->setEnabled(true); + identity_type_cmb->setCurrentText(~column->getIdentityType()); + notnull_chk->setEnabled(false); + } } - data_type->setAttributes(type, model, UserTypeConfig::BASE_TYPE | UserTypeConfig::TABLE_TYPE | UserTypeConfig::VIEW_TYPE | - UserTypeConfig::DOMAIN_TYPE | UserTypeConfig::EXTENSION_TYPE, true,false); + data_type->setAttributes(type, model, + UserTypeConfig::BASE_TYPE | UserTypeConfig::TABLE_TYPE | UserTypeConfig::VIEW_TYPE | + UserTypeConfig::DOMAIN_TYPE | UserTypeConfig::EXTENSION_TYPE, true,false); } void ColumnWidget::applyConfiguration(void) @@ -103,6 +127,7 @@ void ColumnWidget::applyConfiguration(void) try { Column *column=nullptr; + Constraint *pk = nullptr; startConfiguration(); column=dynamic_cast(this->object); @@ -111,8 +136,20 @@ void ColumnWidget::applyConfiguration(void) if(expression_rb->isChecked()) column->setDefaultValue(def_value_txt->toPlainText()); - else + else if(sequence_rb->isChecked()) column->setSequence(sequence_sel->getSelectedObject()); + else + column->setIdentityType(IdentityType(identity_type_cmb->currentText())); + + if(table) + { + pk = dynamic_cast
(table)->getPrimaryKey(); + if(pk && pk->isColumnReferenced(column) && !notnull_chk->isChecked()) + throw Exception(Exception::getErrorMessage(ERR_NULL_PK_COLUMN) + .arg(column->getName()) + .arg(pk->getParentTable()->getSignature(true)), + ERR_NULL_PK_COLUMN,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } BaseObjectWidget::applyConfiguration(); finishConfiguration(); diff --git a/libpgmodeler_ui/src/columnwidget.h b/libpgmodeler_ui/src/columnwidget.h index e10be41ce..42bf2dfa5 100644 --- a/libpgmodeler_ui/src/columnwidget.h +++ b/libpgmodeler_ui/src/columnwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,9 +36,7 @@ class ColumnWidget: public BaseObjectWidget, public Ui::ColumnWidget { SyntaxHighlighter *hl_default_value; PgSQLTypeWidget *data_type; ObjectSelectorWidget *sequence_sel; - - void hideEvent(QHideEvent *event); - + public: ColumnWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, BaseObject *parent_obj, Column *column); diff --git a/libpgmodeler_ui/src/configurationform.cpp b/libpgmodeler_ui/src/configurationform.cpp index 87a119fce..b832b17f4 100644 --- a/libpgmodeler_ui/src/configurationform.cpp +++ b/libpgmodeler_ui/src/configurationform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/configurationform.h b/libpgmodeler_ui/src/configurationform.h index d4349566e..ab3344750 100644 --- a/libpgmodeler_ui/src/configurationform.h +++ b/libpgmodeler_ui/src/configurationform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/connectionsconfigwidget.cpp b/libpgmodeler_ui/src/connectionsconfigwidget.cpp index ecbce6fac..6a764e5dd 100644 --- a/libpgmodeler_ui/src/connectionsconfigwidget.cpp +++ b/libpgmodeler_ui/src/connectionsconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/connectionsconfigwidget.h b/libpgmodeler_ui/src/connectionsconfigwidget.h index f64753ed5..4b8229301 100644 --- a/libpgmodeler_ui/src/connectionsconfigwidget.h +++ b/libpgmodeler_ui/src/connectionsconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/constraintwidget.cpp b/libpgmodeler_ui/src/constraintwidget.cpp index 7a1721999..4bb4eca7c 100644 --- a/libpgmodeler_ui/src/constraintwidget.cpp +++ b/libpgmodeler_ui/src/constraintwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -38,15 +38,15 @@ ConstraintWidget::ConstraintWidget(QWidget *parent): BaseObjectWidget(parent, OB expression_hl=new SyntaxHighlighter(expression_txt, false, true); expression_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); - columns_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::EDIT_BUTTON | - ObjectTableWidget::UPDATE_BUTTON | - ObjectTableWidget::DUPLICATE_BUTTON), true, this); + columns_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::EDIT_BUTTON | + ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::DUPLICATE_BUTTON), true, this); - ref_columns_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::EDIT_BUTTON | - ObjectTableWidget::UPDATE_BUTTON | - ObjectTableWidget::DUPLICATE_BUTTON), true, this); + ref_columns_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::EDIT_BUTTON | + ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::DUPLICATE_BUTTON), true, this); ref_table_sel=new ObjectSelectorWidget(OBJ_TABLE, true, this); @@ -126,7 +126,7 @@ ConstraintWidget::ConstraintWidget(QWidget *parent): BaseObjectWidget(parent, OB void ConstraintWidget::addColumn(int row) { QObject *sender_obj=sender(); - ObjectTableWidget *aux_col_tab=nullptr; + ObjectsTableWidget *aux_col_tab=nullptr; QComboBox *combo=nullptr; Column *column=nullptr; unsigned col_id; @@ -156,7 +156,7 @@ void ConstraintWidget::addColumn(int row) addColumn(column, col_id, row); //When there is no items con the combo the insert button of the table is disabled - aux_col_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (combo->count()!=0)); + aux_col_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (combo->count()!=0)); } catch(Exception &e) { @@ -183,7 +183,7 @@ void ConstraintWidget::removeColumns(void) void ConstraintWidget::addColumn(Column *column, unsigned col_id, int row) { - ObjectTableWidget *table_wgt=nullptr; + ObjectsTableWidget *table_wgt=nullptr; if(column && row >= 0) { @@ -213,7 +213,7 @@ void ConstraintWidget::addColumn(Column *column, unsigned col_id, int row) void ConstraintWidget::updateColumnsCombo(unsigned col_id) { - ObjectTableWidget *aux_col_tab=nullptr; + ObjectsTableWidget *aux_col_tab=nullptr; Column *column=nullptr; Table *table=nullptr; QComboBox *combo=nullptr; @@ -267,7 +267,7 @@ void ConstraintWidget::updateColumnsCombo(unsigned col_id) QString(")"), QVariant::fromValue(column)); } - aux_col_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (combo->count()!=0)); + aux_col_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (combo->count()!=0)); } catch(Exception &e) { @@ -294,33 +294,6 @@ void ConstraintWidget::selectReferencedTable(void) } } -void ConstraintWidget::hideEvent(QHideEvent *event) -{ - expression_txt->clear(); - column_cmb->clear(); - ref_column_cmb->clear(); - - no_inherit_chk->setChecked(false); - deferrable_chk->setChecked(false); - constr_type_lbl->setEnabled(true); - constr_type_cmb->setEnabled(true); - constr_type_cmb->setCurrentIndex(0); - match_cmb->setCurrentIndex(0); - deferral_cmb->setCurrentIndex(0); - - columns_tab->blockSignals(true); - ref_columns_tab->blockSignals(true); - columns_tab->removeRows(); - ref_columns_tab->removeRows(); - columns_tab->blockSignals(false); - ref_columns_tab->blockSignals(false); - - ref_table_sel->clearSelector(); - excl_elems_wgt->clear(); - - BaseObjectWidget::hideEvent(event); -} - void ConstraintWidget::selectConstraintType(void) { ConstraintType constr_type=ConstraintType(constr_type_cmb->currentText()); @@ -420,7 +393,7 @@ void ConstraintWidget::setAttributes(DatabaseModel *model, OperationList *op_lis } updateColumnsCombo(Constraint::SOURCE_COLS); - columns_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); + columns_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); columns_tab->blockSignals(false); if(constr) @@ -465,7 +438,7 @@ void ConstraintWidget::setAttributes(DatabaseModel *model, OperationList *op_lis } updateColumnsCombo(Constraint::REFERENCED_COLS); - ref_columns_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); + ref_columns_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); ref_columns_tab->blockSignals(false); } } @@ -480,7 +453,7 @@ void ConstraintWidget::applyConfiguration(void) Constraint *constr=nullptr; unsigned i, col_id, count; Column *column=nullptr; - ObjectTableWidget *aux_col_tab=nullptr; + ObjectsTableWidget *aux_col_tab=nullptr; vector excl_elems; startConfiguration(); diff --git a/libpgmodeler_ui/src/constraintwidget.h b/libpgmodeler_ui/src/constraintwidget.h index 8e5594a9f..531f64cb8 100644 --- a/libpgmodeler_ui/src/constraintwidget.h +++ b/libpgmodeler_ui/src/constraintwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_constraintwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "messagebox.h" #include "elementswidget.h" @@ -43,7 +43,7 @@ class ConstraintWidget: public BaseObjectWidget, public Ui::ConstraintWidget { /*! \brief Table widgets used to store the columns that forms the constraint as well the referenced columns (only for foreign keys) */ - ObjectTableWidget *columns_tab, + ObjectsTableWidget *columns_tab, *ref_columns_tab; //! \brief Referenced table selector @@ -55,8 +55,6 @@ class ConstraintWidget: public BaseObjectWidget, public Ui::ConstraintWidget { //! \brief Adds the column to the column's table at the specified row void addColumn(Column *column, unsigned col_id, int row); - void hideEvent(QHideEvent *event); - public: ConstraintWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, BaseObject *parent_obj, Constraint *constr); diff --git a/libpgmodeler_ui/src/conversionwidget.cpp b/libpgmodeler_ui/src/conversionwidget.cpp index 198a9228f..cefaa18f0 100644 --- a/libpgmodeler_ui/src/conversionwidget.cpp +++ b/libpgmodeler_ui/src/conversionwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -56,13 +56,6 @@ ConversionWidget::ConversionWidget(QWidget *parent): BaseObjectWidget(parent, OB } } -void ConversionWidget::hideEvent(QHideEvent *event) -{ - conv_func_sel->clearSelector(); - default_conv_chk->setChecked(false); - BaseObjectWidget::hideEvent(event); -} - void ConversionWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Conversion *conv) { BaseObjectWidget::setAttributes(model, op_list, conv, schema); diff --git a/libpgmodeler_ui/src/conversionwidget.h b/libpgmodeler_ui/src/conversionwidget.h index 07be4a5b3..1bf00490c 100644 --- a/libpgmodeler_ui/src/conversionwidget.h +++ b/libpgmodeler_ui/src/conversionwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -38,7 +38,6 @@ class ConversionWidget: public BaseObjectWidget, public Ui::ConversionWidget { void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Conversion *conv); private slots: - void hideEvent(QHideEvent *event); public slots: void applyConfiguration(void); diff --git a/libpgmodeler_ui/src/csvloadwidget.cpp b/libpgmodeler_ui/src/csvloadwidget.cpp index a749d8e13..28f794e1a 100644 --- a/libpgmodeler_ui/src/csvloadwidget.cpp +++ b/libpgmodeler_ui/src/csvloadwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -87,12 +87,14 @@ QList CsvLoadWidget::loadCsvFromBuffer(const QString &csv_buffer, c if(!csv_buffer.isEmpty()) { QString double_quote=QString("%1%1").arg(text_delim), - placeholder = QString("⁋"); + placeholder = QString("⁋"), aux_buffer = csv_buffer; QStringList values, rows; QRegExp empty_val; //If no custom separator is specified we use the default ';' - rows=csv_buffer.split(QChar::LineFeed, QString::SkipEmptyParts); + aux_buffer.replace(QString("\r\n"), placeholder); + rows=aux_buffer.split(QChar::LineFeed, QString::SkipEmptyParts); + rows.replaceInStrings(placeholder, QString("\r\n")); if(cols_in_first_row) { diff --git a/libpgmodeler_ui/src/csvloadwidget.h b/libpgmodeler_ui/src/csvloadwidget.h index ba50a1e24..be030eb60 100644 --- a/libpgmodeler_ui/src/csvloadwidget.h +++ b/libpgmodeler_ui/src/csvloadwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/customsqlwidget.cpp b/libpgmodeler_ui/src/customsqlwidget.cpp index d6be95001..f0c588481 100644 --- a/libpgmodeler_ui/src/customsqlwidget.cpp +++ b/libpgmodeler_ui/src/customsqlwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -39,13 +39,9 @@ CustomSQLWidget::CustomSQLWidget(QWidget *parent) : BaseObjectWidget(parent) prepend_sql_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); prepend_sql_cp=new CodeCompletionWidget(prepend_sql_txt, true); - font=name_edt->font(); - font.setItalic(true); - name_edt->setReadOnly(true); - comment_edt->setFont(font); - comment_edt->setReadOnly(true); - comment_lbl->setText(trUtf8("Type:")); + comment_edt->setVisible(false); + comment_lbl->setVisible(false); PgModelerUiNS::configureWidgetFont(message_lbl, PgModelerUiNS::MEDIUM_FONT_FACTOR); @@ -134,6 +130,8 @@ void CustomSQLWidget::setAttributes(DatabaseModel *model, BaseObject *object) { BaseObjectWidget::setAttributes(model, object, nullptr); + name_edt->setText(QString("%1 (%2)").arg(object->getSignature()).arg(object->getTypeName())); + if(object->getObjectType()==OBJ_DATABASE) end_of_model_chk->setChecked(dynamic_cast(object)->isAppendAtEOD()); @@ -150,7 +148,6 @@ void CustomSQLWidget::setAttributes(DatabaseModel *model, BaseObject *object) end_of_model_chk->setVisible(object->getObjectType()==OBJ_DATABASE); begin_of_model_chk->setVisible(object->getObjectType()==OBJ_DATABASE); - comment_edt->setText(object->getTypeName()); protected_obj_frm->setVisible(false); obj_id_lbl->setVisible(false); diff --git a/libpgmodeler_ui/src/customsqlwidget.h b/libpgmodeler_ui/src/customsqlwidget.h index 8ff2abdb4..0cc69627b 100644 --- a/libpgmodeler_ui/src/customsqlwidget.h +++ b/libpgmodeler_ui/src/customsqlwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/databaseexplorerwidget.cpp b/libpgmodeler_ui/src/databaseexplorerwidget.cpp index ba7b0132f..d93cc1078 100644 --- a/libpgmodeler_ui/src/databaseexplorerwidget.cpp +++ b/libpgmodeler_ui/src/databaseexplorerwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -92,13 +92,19 @@ const attribs_map DatabaseExplorerWidget::attribs_i18n { {SSL_CERT_FILE, QT_TR_NOOP("SSL cert file")}, {SSL_CRL_FILE, QT_TR_NOOP("SSL crl file")}, {SSL_KEY_FILE, QT_TR_NOOP("SSL key file")}, {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")} + {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")}, + {RLS_ENABLED, QT_TR_NOOP("RLS enabled")}, {RLS_FORCED, QT_TR_NOOP("RLS forced")} }; DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent) { setupUi(this); - splitter->setSizes({ 70, 30 }); + + filter_parent->setVisible(false); + + sort_column = 0; + splitter->setSizes({ 80, 20 }); properties_tbw->setItemDelegate(new PlainTextItemDelegate(this, true)); rename_item=nullptr; @@ -107,6 +113,24 @@ DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent) runsql_tb->setToolTip(runsql_tb->toolTip() + QString(" (%1)").arg(runsql_tb->shortcut().toString())); refresh_tb->setToolTip(refresh_tb->toolTip() + QString(" (%1)").arg(refresh_tb->shortcut().toString())); + QAction *act = nullptr; + + act = toggle_disp_menu.addAction(trUtf8("Show objects filter")); + act->setCheckable(true); + connect(act, SIGNAL(toggled(bool)), filter_parent, SLOT(setVisible(bool))); + + toggle_disp_menu.addSeparator(); + + show_sys_objs = toggle_disp_menu.addAction(trUtf8("Show system objects")); + show_sys_objs->setCheckable(true); + connect(show_sys_objs, SIGNAL(toggled(bool)), this, SLOT(listObjects(void))); + + show_ext_objs = toggle_disp_menu.addAction(trUtf8("Show extension objects")); + show_ext_objs->setCheckable(true); + connect(show_ext_objs, SIGNAL(toggled(bool)), this, SLOT(listObjects(void))); + + toggle_display_tb->setMenu(&toggle_disp_menu); + snippets_menu.setTitle(trUtf8("Snippets")); snippets_menu.setIcon(QIcon(QString(":icones/icones/codesnippet.png"))); @@ -135,8 +159,6 @@ DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent) objects_trw->installEventFilter(this); connect(refresh_tb, SIGNAL(clicked(void)), this, SLOT(listObjects(void))); - connect(ext_objs_chk, SIGNAL(toggled(bool)), this, SLOT(listObjects(void))); - connect(sys_objs_chk, SIGNAL(toggled(bool)), this, SLOT(listObjects(void))); connect(objects_trw, SIGNAL(itemPressed(QTreeWidgetItem*,int)), this, SLOT(handleObject(QTreeWidgetItem *,int))); connect(objects_trw, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(showObjectProperties())); connect(raw_attrib_names_chk, SIGNAL(toggled(bool)), this, SLOT(showObjectProperties())); @@ -148,6 +170,8 @@ DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent) connect(data_grid_tb, SIGNAL(clicked(bool)), this, SLOT(openDataGrid())); connect(drop_db_tb, SIGNAL(clicked(bool)), this, SLOT(dropDatabase())); connect(collapse_all_tb, SIGNAL(clicked(bool)), objects_trw, SLOT(collapseAll(void))); + connect(by_oid_chk, SIGNAL(toggled(bool)), this, SLOT(filterObjects(void))); + connect(filter_edt, SIGNAL(textChanged(QString)), this, SLOT(filterObjects(void))); connect(runsql_tb, &QToolButton::clicked, [&]() { emit s_sqlExecutionRequested(); }); @@ -155,10 +179,6 @@ DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent) connect(properties_tbw, &QTableWidget::itemPressed, [&]() { SQLExecutionWidget::copySelection(properties_tbw, true); }); - connect(filter_edt, &QLineEdit::textChanged, - [&](){ DatabaseImportForm::filterObjects(objects_trw, filter_edt->text(), - (by_oid_chk->isChecked() ? DatabaseImportForm::OBJECT_ID : 0), false); }); - connect(expand_all_tb, &QToolButton::clicked, [&](){ objects_trw->blockSignals(true); @@ -177,10 +197,15 @@ DatabaseExplorerWidget::DatabaseExplorerWidget(QWidget *parent): QWidget(parent) } }); + connect(sort_by_name_tb, &QToolButton::clicked, + [&]() { + sort_column = sort_by_name_tb->isChecked() ? 0 : DatabaseImportForm::OBJECT_ID; + objects_trw->sortByColumn(sort_column); + }); + QMenu *refresh_menu=new QMenu(refresh_tb); - QAction *act=nullptr; - act=refresh_menu->addAction(trUtf8("Quick refresh"), this, SLOT(listObjects()), QKeySequence("F5")); + act=refresh_menu->addAction(trUtf8("Quick refresh"), this, SLOT(listObjects()), QKeySequence("Alt+F5")); act->setData(QVariant::fromValue(true)); act=refresh_menu->addAction(trUtf8("Full refresh"), this, SLOT(listObjects()), QKeySequence("Ctrl+F5")); @@ -282,6 +307,7 @@ attribs_map DatabaseExplorerWidget::formatObjectAttribs(attribs_map &attribs) case OBJ_COLUMN: formatColumnAttribs(attribs); break; case OBJ_CONSTRAINT: formatConstraintAttribs(attribs); break; case OBJ_INDEX: formatIndexAttribs(attribs); break; + case OBJ_POLICY: formatPolicyAttribs(attribs); break; default: break; } } @@ -484,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); } @@ -521,7 +549,7 @@ void DatabaseExplorerWidget::formatSequenceAttribs(attribs_map &attribs) ResultSet res; conn.connect(); - conn.executeDMLCommand(QString("SELECT last_value FROM %1.%2").arg(sch_name).arg(BaseObject::formatName(attribs[ParsersAttributes::NAME])), res); + conn.executeDMLCommand(QString("SELECT last_value FROM \"%1\".\"%2\"").arg(sch_name).arg(BaseObject::formatName(attribs[ParsersAttributes::NAME])), res); if(res.accessTuple(ResultSet::FIRST_TUPLE)) attribs[ParsersAttributes::LAST_VALUE]=res.getColumnValue(QString("last_value")); @@ -735,8 +763,12 @@ void DatabaseExplorerWidget::formatIndexAttribs(attribs_map &attribs) Catalog::parseArrayValues(attribs[ParsersAttributes::OP_CLASSES])).join(ELEM_SEPARATOR); attribs[ParsersAttributes::COLUMNS]=getObjectsNames(OBJ_COLUMN, - Catalog::parseArrayValues(attribs[ParsersAttributes::COLUMNS]), - names[0], names[1]).join(ELEM_SEPARATOR); + Catalog::parseArrayValues(attribs[ParsersAttributes::COLUMNS]), names[0], names[1]).join(ELEM_SEPARATOR); +} + +void DatabaseExplorerWidget::formatPolicyAttribs(attribs_map &attribs) +{ + attribs[ParsersAttributes::ROLES] = getObjectsNames(OBJ_ROLE, Catalog::parseArrayValues(attribs[ParsersAttributes::ROLES])).join(ELEM_SEPARATOR); } QString DatabaseExplorerWidget::formatObjectName(attribs_map &attribs) @@ -899,7 +931,7 @@ void DatabaseExplorerWidget::listObjects(void) if(quick_refresh) QApplication::setOverrideCursor(Qt::WaitCursor); - DatabaseImportForm::listObjects(import_helper, objects_trw, false, false, true, quick_refresh); + DatabaseImportForm::listObjects(import_helper, objects_trw, false, false, true, quick_refresh, sort_column); QTreeWidgetItem *root = new QTreeWidgetItem, *curr_root = nullptr; @@ -933,7 +965,9 @@ void DatabaseExplorerWidget::configureImportHelper(void) { import_helper.setConnection(connection); import_helper.setCurrentDatabase(connection.getConnectionParam(Connection::PARAM_DB_NAME)); - import_helper.setImportOptions(sys_objs_chk->isChecked(), ext_objs_chk->isChecked(), false, false, false, false, false); + import_helper.setImportOptions(show_sys_objs->isChecked(), + show_ext_objs->isChecked(), + false, false, false, false, false); catalog.closeConnection(); catalog.setFilter(Catalog::LIST_ALL_OBJS); @@ -1115,6 +1149,20 @@ attribs_map DatabaseExplorerWidget::extractAttributesFromItem(QTreeWidgetItem *i } else { + /* If we are handling a view we need to append the MATERIALIZED keyword in the sql-object in order + * to construct DDL commands correctly for this kind of object */ + if(obj_type==OBJ_VIEW) + { + attribs_map aux_attribs=item->data(DatabaseImportForm::OBJECT_OTHER_DATA, Qt::UserRole).value(); + + if(aux_attribs[ParsersAttributes::MATERIALIZED] == ParsersAttributes::_TRUE_) + { + attribs[ParsersAttributes::SQL_OBJECT] = + QString("%1 %2").arg(ParsersAttributes::MATERIALIZED.toUpper()) + .arg(BaseObject::getSQLName(OBJ_VIEW)); + } + } + if(!attribs[ParsersAttributes::SCHEMA].isEmpty() && attribs[ParsersAttributes::NAME].indexOf(attribs[ParsersAttributes::SCHEMA] + QString(".")) < 0) attribs[ParsersAttributes::SIGNATURE]=attribs[ParsersAttributes::SCHEMA] + QString(".") + attribs[ParsersAttributes::NAME]; @@ -1159,6 +1207,9 @@ void DatabaseExplorerWidget::dropObject(QTreeWidgetItem *item, bool cascade) attribs=extractAttributesFromItem(item); + if(obj_type==OBJ_OPERATOR || obj_type==OBJ_FUNCTION) + attribs[ParsersAttributes::SIGNATURE].replace(ELEM_SEPARATOR, QChar(',')); + //Generate the drop command schparser.ignoreEmptyAttributes(true); schparser.ignoreUnkownAttributes(true); @@ -1217,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) @@ -1226,9 +1278,9 @@ void DatabaseExplorerWidget::truncateTable(QTreeWidgetItem *item, bool cascade) Connection conn; attribs[ParsersAttributes::SQL_OBJECT]=BaseObject::getSQLName(OBJ_TABLE); - attribs[ParsersAttributes::SIGNATURE]=sch_name + QString(".") + obj_name; + 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); @@ -1303,11 +1355,11 @@ void DatabaseExplorerWidget::updateItem(QTreeWidgetItem *item) //Updates the group type only if(obj_id==0 || (obj_type!=OBJ_TABLE && obj_type!=OBJ_VIEW && obj_type!=OBJ_SCHEMA)) - gen_items=DatabaseImportForm::updateObjectsTree(import_helper, objects_trw, { obj_type }, false, false, root, sch_name, tab_name); + gen_items=DatabaseImportForm::updateObjectsTree(import_helper, objects_trw, { obj_type }, false, false, root, sch_name, tab_name, sort_column); else //Updates all child objcts when the selected object is a schema or table or view gen_items=DatabaseImportForm::updateObjectsTree(import_helper, objects_trw, - BaseObject::getChildObjectTypes(obj_type), false, false, root, sch_name, tab_name); + BaseObject::getChildObjectTypes(obj_type), false, false, root, sch_name, tab_name, sort_column); //Creating dummy items for schemas and tables if(obj_type==OBJ_SCHEMA || obj_type==OBJ_TABLE || obj_type==OBJ_VIEW) @@ -1321,7 +1373,7 @@ void DatabaseExplorerWidget::updateItem(QTreeWidgetItem *item) } import_helper.closeConnection(); - objects_trw->sortItems(0, Qt::AscendingOrder); + objects_trw->sortItems(sort_column, Qt::AscendingOrder); objects_trw->setCurrentItem(nullptr); if(obj_type==OBJ_TABLE) @@ -1703,7 +1755,9 @@ void DatabaseExplorerWidget::loadObjectSource(void) dbmodel.createSystemObjects(false); import_hlp.setConnection(connection); import_hlp.setCurrentDatabase(connection.getConnectionParam(Connection::PARAM_DB_NAME)); - import_hlp.setImportOptions(sys_objs_chk->isChecked(), ext_objs_chk->isChecked(), true, false, false, false, false); + import_hlp.setImportOptions(toggle_disp_menu.actions().at(0)->isChecked(), + toggle_disp_menu.actions().at(1)->isChecked(), + true, false, false, false, false); import_hlp.setSelectedOIDs(&dbmodel, {{OBJ_DATABASE, {db_oid}}, {obj_type,{oid}}}, {}); sys_oid=import_hlp.getLastSystemOID(); @@ -1804,6 +1858,12 @@ void DatabaseExplorerWidget::loadObjectSource(void) } } +void DatabaseExplorerWidget::filterObjects(void) +{ + DatabaseImportForm::filterObjects(objects_trw, filter_edt->text(), + (by_oid_chk->isChecked() ? DatabaseImportForm::OBJECT_ID : 0), false); +} + QString DatabaseExplorerWidget::getObjectSource(BaseObject *object, DatabaseModel *dbmodel) { if(!object || !dbmodel) diff --git a/libpgmodeler_ui/src/databaseexplorerwidget.h b/libpgmodeler_ui/src/databaseexplorerwidget.h index ef4e135fb..cd58b1c9f 100644 --- a/libpgmodeler_ui/src/databaseexplorerwidget.h +++ b/libpgmodeler_ui/src/databaseexplorerwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -60,17 +60,21 @@ class DatabaseExplorerWidget: public QWidget, public Ui::DatabaseExplorerWidget QMenu handle_menu, //! \brief Stores the snippets' actions - snippets_menu; + snippets_menu, + + toggle_disp_menu; QAction *copy_action, *drop_action, *drop_cascade_action, *show_data_action, *refresh_action, *properties_action, *trunc_cascade_action, *truncate_action, *rename_action, - *source_action; + *source_action, *show_sys_objs, *show_ext_objs; QTreeWidgetItem *rename_item; HintTextWidget *filter_ht; + unsigned sort_column; + void configureImportHelper(void); //! \brief Drops the object represented by the specified item @@ -127,6 +131,7 @@ class DatabaseExplorerWidget: public QWidget, public Ui::DatabaseExplorerWidget void formatColumnAttribs(attribs_map &attribs); void formatConstraintAttribs(attribs_map &attribs); void formatIndexAttribs(attribs_map &attribs); + void formatPolicyAttribs(attribs_map &attribs); void handleSelectedSnippet(const QString &snip_id); //! \brief Extract an attribute map containing the basic attributes for drop/rename commands @@ -180,6 +185,8 @@ class DatabaseExplorerWidget: public QWidget, public Ui::DatabaseExplorerWidget void loadObjectSource(void); + void filterObjects(void); + signals: //! \brief This signal is emmited to indicate that a sql execution widget need to be opened void s_sqlExecutionRequested(void); diff --git a/libpgmodeler_ui/src/databaseimportform.cpp b/libpgmodeler_ui/src/databaseimportform.cpp index d0b11386a..a52611c7b 100644 --- a/libpgmodeler_ui/src/databaseimportform.cpp +++ b/libpgmodeler_ui/src/databaseimportform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -391,8 +391,7 @@ void DatabaseImportForm::captureThreadError(Exception e) QTreeWidgetItem *item=nullptr; if(!create_model) - model_wgt->rearrangeSchemas(QPointF(origin_sb->value(), origin_sb->value()), - tabs_per_row_sb->value(), sch_per_row_sb->value(), obj_spacing_sb->value()); + model_wgt->rearrangeSchemasInGrid(); destroyModelWidget(); finishImport(trUtf8("Importing process aborted!")); @@ -415,7 +414,9 @@ void DatabaseImportForm::captureThreadError(Exception e) void DatabaseImportForm::filterObjects(void) { - DatabaseImportForm::filterObjects(db_objects_tw, filter_edt->text(), (by_oid_chk->isChecked() ? OBJECT_ID : 0), false); + DatabaseImportForm::filterObjects(db_objects_tw, + filter_edt->text(), + (by_oid_chk->isChecked() ? OBJECT_ID : 0), false); } void DatabaseImportForm::filterObjects(QTreeWidget *tree_wgt, const QString &pattern, int search_column, bool sel_single_leaf) @@ -423,9 +424,14 @@ void DatabaseImportForm::filterObjects(QTreeWidget *tree_wgt, const QString &pat if(!tree_wgt) throw Exception(ERR_OPR_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__); - QList items=tree_wgt->findItems(pattern, Qt::MatchStartsWith | Qt::MatchRecursive, search_column); + QList items; QTreeWidgetItemIterator itr(tree_wgt); + if(search_column == DatabaseImportForm::OBJECT_ID) + items = tree_wgt->findItems(QString("^(0)*(%1)(.)*").arg(pattern), Qt::MatchRegExp | Qt::MatchRecursive, search_column); + else + items = tree_wgt->findItems(pattern, Qt::MatchStartsWith | Qt::MatchRecursive, search_column); + tree_wgt->blockSignals(true); tree_wgt->collapseAll(); tree_wgt->clearSelection(); @@ -502,8 +508,7 @@ void DatabaseImportForm::handleImportCanceled(void) QString msg=trUtf8("Importing process canceled by user!"); if(!create_model) - model_wgt->rearrangeSchemas(QPointF(origin_sb->value(), origin_sb->value()), - tabs_per_row_sb->value(), sch_per_row_sb->value(), obj_spacing_sb->value()); + model_wgt->rearrangeSchemasInGrid(); destroyModelWidget(); finishImport(msg); @@ -520,8 +525,8 @@ void DatabaseImportForm::handleImportFinished(Exception e) msgbox.show(e, e.getErrorMessage(), Messagebox::ALERT_ICON); } - model_wgt->rearrangeSchemas(QPointF(origin_sb->value(), origin_sb->value()), - tabs_per_row_sb->value(), sch_per_row_sb->value(), obj_spacing_sb->value()); + model_wgt->rearrangeSchemasInGrid(); + model_wgt->getDatabaseModel()->setInvalidated(false); finishImport(trUtf8("Importing process sucessfuly ended!")); @@ -622,7 +627,7 @@ void DatabaseImportForm::listDatabases(DatabaseImportHelper &import_helper, QCom } void DatabaseImportForm::listObjects(DatabaseImportHelper &import_helper, QTreeWidget *tree_wgt, bool checkable_items, - bool disable_empty_grps, bool create_db_item, bool create_dummy_item) + bool disable_empty_grps, bool create_db_item, bool create_dummy_item, unsigned sort_by) { TaskProgressWidget task_prog_wgt; @@ -655,7 +660,7 @@ void DatabaseImportForm::listObjects(DatabaseImportHelper &import_helper, QTreeW db_item->setIcon(0, QPixmap(PgModelerUiNS::getIconPath(OBJ_DATABASE))); attribs=catalog.getObjectsAttributes(OBJ_DATABASE, QString(), QString(), {}, {{ParsersAttributes::NAME, import_helper.getCurrentDatabase()}}); - db_item->setData(OBJECT_ID, Qt::UserRole, attribs[0].at(ParsersAttributes::OID)); + db_item->setData(OBJECT_ID, Qt::UserRole, attribs[0].at(ParsersAttributes::OID).toUInt()); db_item->setData(OBJECT_TYPE, Qt::UserRole, OBJ_DATABASE); db_item->setData(OBJECT_TYPE, Qt::UserRole, OBJ_DATABASE); db_item->setToolTip(0, QString("OID: %1").arg(attribs[0].at(ParsersAttributes::OID))); @@ -714,7 +719,7 @@ void DatabaseImportForm::listObjects(DatabaseImportHelper &import_helper, QTreeW } } - tree_wgt->sortItems(0, Qt::AscendingOrder); + tree_wgt->sortItems(sort_by, Qt::AscendingOrder); if(db_item) db_item->setExpanded(true); @@ -735,7 +740,7 @@ void DatabaseImportForm::listObjects(DatabaseImportHelper &import_helper, QTreeW } vector DatabaseImportForm::updateObjectsTree(DatabaseImportHelper &import_helper, QTreeWidget *tree_wgt, vector types, bool checkable_items, - bool disable_empty_grps, QTreeWidgetItem *root, const QString &schema, const QString &table) + bool disable_empty_grps, QTreeWidgetItem *root, const QString &schema, const QString &table, unsigned sort_by) { vector items_vect; @@ -805,7 +810,8 @@ vector DatabaseImportForm::updateObjectsTree(DatabaseImportHe item=new QTreeWidgetItem(group); item->setIcon(0, QPixmap(PgModelerUiNS::getIconPath(obj_type))); item->setText(0, label); - item->setText(OBJECT_ID, attribs[ParsersAttributes::OID]); + item->setText(OBJECT_ID, attribs[ParsersAttributes::OID].rightJustified(10, '0')); + item->setData(OBJECT_ID, Qt::UserRole, attribs[ParsersAttributes::OID].toUInt()); item->setData(OBJECT_NAME, Qt::UserRole, name); if(checkable_items) @@ -876,7 +882,8 @@ vector DatabaseImportForm::updateObjectsTree(DatabaseImportHe } tree_wgt->addTopLevelItems(groups_list); - tree_wgt->setSortingEnabled(true); + //tree_wgt->setSortingEnabled(true); + tree_wgt->sortItems(sort_by, Qt::AscendingOrder); tree_wgt->setUpdatesEnabled(true); tree_wgt->blockSignals(false); } diff --git a/libpgmodeler_ui/src/databaseimportform.h b/libpgmodeler_ui/src/databaseimportform.h index dd39bbe14..ed05b4431 100644 --- a/libpgmodeler_ui/src/databaseimportform.h +++ b/libpgmodeler_ui/src/databaseimportform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -106,7 +106,8 @@ class DatabaseImportForm: public QDialog, public Ui::DatabaseImportForm { item representing the database itself. The parameter 'create_dummy_item' create an empty child item that represent schema or table child. In this case the generation of schema's or table's children need to be done manually. */ static void listObjects(DatabaseImportHelper &import_helper, QTreeWidget *tree_wgt, bool checkable_items, - bool disable_empty_grps, bool create_db_item, bool create_dummy_item = false); + bool disable_empty_grps, bool create_db_item, bool create_dummy_item = false, + unsigned sort_by = 0); /*! \brief Filters an tree widget using a pattern. The 'search_column' indicates in which column the pattern is applied. The paramenter 'sel_single_leaf' indicates if the single leaf (resulting from filtering) must be selected. */ @@ -118,7 +119,7 @@ class DatabaseImportForm: public QDialog, public Ui::DatabaseImportForm { This method automatically returns a list of QTreeWidgetItem when the vector "types" contains OBJ_SCHEMA or OBJ_TABLE or OBJ_VIEW */ static vector updateObjectsTree(DatabaseImportHelper &import_helper, QTreeWidget *tree_wgt, vector types, bool checkable_items=false, bool disable_empty_grps=true, QTreeWidgetItem *root=nullptr, - const QString &schema=QString(), const QString &table=QString()); + const QString &schema=QString(), const QString &table=QString(), unsigned sort_by = 0); private slots: void importDatabase(void); diff --git a/libpgmodeler_ui/src/databaseimporthelper.cpp b/libpgmodeler_ui/src/databaseimporthelper.cpp index b802e2d85..3030f9485 100644 --- a/libpgmodeler_ui/src/databaseimporthelper.cpp +++ b/libpgmodeler_ui/src/databaseimporthelper.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -657,6 +657,10 @@ void DatabaseImportHelper::createObject(attribs_map &attribs) ObjectType obj_type=static_cast(attribs[ParsersAttributes::OBJECT_TYPE].toUInt()); QString obj_name=getObjectName(attribs[ParsersAttributes::OID], (obj_type==OBJ_FUNCTION || obj_type==OBJ_OPERATOR)); + //Avoiding the creation of pgModeler's temp objects created in database during the catalog reading + if(obj_name.contains(Catalog::PGMODELER_TEMP_DB_OBJ)) + return; + try { if(!import_canceled && @@ -670,7 +674,7 @@ void DatabaseImportHelper::createObject(attribs_map &attribs) attribs[ParsersAttributes::DECL_IN_TABLE]=QString(); //System objects will have the sql disabled by default - attribs[ParsersAttributes::SQL_DISABLED]=(oid > catalog.getLastSysObjectOID() ? QString() : ParsersAttributes::_TRUE_); + attribs[ParsersAttributes::SQL_DISABLED]=(catalog.isSystemObject(oid) || catalog.isExtensionObject(oid) ? ParsersAttributes::_TRUE_ : QString()); attribs[ParsersAttributes::COMMENT]=getComment(attribs); if(attribs.count(ParsersAttributes::OWNER)) @@ -720,6 +724,7 @@ void DatabaseImportHelper::createObject(attribs_map &attribs) case OBJ_TRIGGER: createTrigger(attribs); break; case OBJ_INDEX: createIndex(attribs); break; case OBJ_CONSTRAINT: createConstraint(attribs); break; + case OBJ_POLICY: createPolicy(attribs); break; case OBJ_EVENT_TRIGGER: createEventTrigger(attribs); break; default: @@ -890,6 +895,7 @@ void DatabaseImportHelper::resetImportParameters(void) col_perms.clear(); connection.close(); catalog.closeConnection(); + inherited_cols.clear(); } QString DatabaseImportHelper::dumpObjectAttributes(attribs_map &attribs) @@ -977,9 +983,31 @@ void DatabaseImportHelper::createRole(attribs_map &attribs) void DatabaseImportHelper::createDomain(attribs_map &attribs) { Domain *dom=nullptr; + QStringList constraints, constr_attrs; + attribs_map aux_attribs; + QString expr; try { + constraints = Catalog::parseArrayValues(attribs[ParsersAttributes::CONSTRAINTS]); + attribs[ParsersAttributes::CONSTRAINTS].clear(); + + for(auto constr : constraints) + { + constr.remove(0, 1); + constr.remove(constr.length() - 1, 1); + constr_attrs = constr.split(QChar(':')); + + aux_attribs[ParsersAttributes::NAME] = constr_attrs.at(0); + + expr = constr_attrs.at(1); + expr.remove(0,1); + expr.remove(expr.length() - 1,1); + aux_attribs[ParsersAttributes::EXPRESSION] = expr; + + attribs[ParsersAttributes::CONSTRAINTS]+= schparser.getCodeDefinition(ParsersAttributes::DOM_CONSTRAINT, aux_attribs, SchemaParser::XML_DEFINITION); + } + attribs[ParsersAttributes::TYPE]=getType(attribs[ParsersAttributes::TYPE], true, attribs); attribs[ParsersAttributes::COLLATION]=getDependencyObject(attribs[ParsersAttributes::COLLATION], OBJ_COLLATION); loadObjectXML(OBJ_DOMAIN, attribs); @@ -1397,6 +1425,7 @@ void DatabaseImportHelper::createConversion(attribs_map &attribs) void DatabaseImportHelper::createSequence(attribs_map &attribs) { Sequence *seq=nullptr; + Column *col = nullptr; try { @@ -1408,11 +1437,32 @@ void DatabaseImportHelper::createSequence(attribs_map &attribs) attribs[ParsersAttributes::OWNER_COLUMN]=QString(); - /* If there are owner columns and the oid of sequence is greater that the owner column's table oid + /* If there are owner columns and the oid of sequence is greater than the owner column's table oid stores the oid of both (sequence and table) in order to swap it's ids at the end of import to avoid reference breaking when generation SQL code */ - if(owner_col.size()==2 && attribs[ParsersAttributes::OID].toUInt() > owner_col[0].toUInt()) - seq_tab_swap[attribs[ParsersAttributes::OID]]=owner_col[0]; + if(owner_col.size()==2) + { + Table *tab = nullptr; + QString col_name, tab_name; + attribs_map pos_attrib={ + { ParsersAttributes::X_POS, QString("0") }, + { ParsersAttributes::Y_POS, QString("0") }}; + + if(attribs[ParsersAttributes::OID].toUInt() > owner_col[0].toUInt()) + seq_tab_swap[attribs[ParsersAttributes::OID]]=owner_col[0]; + + /* Get the table and the owner column instances so the sequence code can be disabled if the + column is an identity one */ + tab_name = getDependencyObject(owner_col[0], OBJ_TABLE, true, auto_resolve_deps, false, + {{ ParsersAttributes::POSITION, + schparser.getCodeDefinition(ParsersAttributes::POSITION, pos_attrib, SchemaParser::XML_DEFINITION)}}); + + col_name=getColumnName(owner_col[0], owner_col[1]); + tab = dbmodel->getTable(tab_name); + + if(tab) + col = tab->getColumn(col_name); + } for(int i=0; i < seq_attribs.size(); i++) attribs[attr[i]]=seq_attribs[i]; @@ -1420,6 +1470,10 @@ void DatabaseImportHelper::createSequence(attribs_map &attribs) loadObjectXML(OBJ_SEQUENCE, attribs); seq=dbmodel->createSequence(); dbmodel->addSequence(seq); + + //Disable the sequence's SQL when the owner column is identity + if(col && col->isIdentity()) + seq->setSQLDisabled(true); } catch(Exception &e) { @@ -1444,9 +1498,10 @@ void DatabaseImportHelper::createAggregate(attribs_map &attribs) attribs[func_types[i]]=getDependencyObject(attribs[func_types[i]], OBJ_FUNCTION, true, auto_resolve_deps, true, {{ParsersAttributes::REF_TYPE, func_types[i]}}); types=getTypes(attribs[ParsersAttributes::TYPES], true); + attribs[ParsersAttributes::TYPES]=QString(); + if(!types.isEmpty()) { - attribs[ParsersAttributes::TYPES]=QString(); for(int i=0; i < types.size(); i++) attribs[ParsersAttributes::TYPES]+=types[i]; } @@ -1533,13 +1588,18 @@ void DatabaseImportHelper::createType(attribs_map &attribs) attribs[ParsersAttributes::ELEMENT]=getType(attribs[ParsersAttributes::ELEMENT], false); - for(i=0; i < count; i++) + /* Workaround: if importing a datatype that is part of an extension we avoid the importing of + * its supporting functions (since they will not be necessary here because the type will be sql-disabled)*/ + if(!catalog.isExtensionObject(attribs[ParsersAttributes::OID].toUInt())) { - attribs[func_types[i]]=getDependencyObject(attribs[func_types[i]], OBJ_FUNCTION, true, true, true, {{ParsersAttributes::REF_TYPE, func_types[i]}}); + for(i=0; i < count; i++) + { + attribs[func_types[i]]=getDependencyObject(attribs[func_types[i]], OBJ_FUNCTION, true, true, true, {{ParsersAttributes::REF_TYPE, func_types[i]}}); - /* Since pgModeler requires that type functions refers to the constructing type as "any" - it's necessary to replace the function parameter types names */ - attribs[func_types[i]].replace(QString("IN ") + type_name, QString("IN any")); + /* Since pgModeler requires that type functions refers to the constructing type as "any" + it's necessary to replace the function parameter types names */ + attribs[func_types[i]].replace(QString("IN ") + type_name, QString("IN any")); + } } } @@ -1567,9 +1627,9 @@ void DatabaseImportHelper::createTable(attribs_map &attribs) vector inh_cols; QString type_def, unknown_obj_xml, type_name, def_val; map::iterator itr, itr1, itr_end; - attribs_map pos_attrib={{ ParsersAttributes::X_POS, QString("0") }, - { ParsersAttributes::Y_POS, QString("0") }}; - + attribs_map pos_attrib={ + { ParsersAttributes::X_POS, QString("0") }, + { ParsersAttributes::Y_POS, QString("0") }}; attribs[ParsersAttributes::COLUMNS]=QString(); attribs[ParsersAttributes::POSITION]=schparser.getCodeDefinition(ParsersAttributes::POSITION, pos_attrib, SchemaParser::XML_DEFINITION); @@ -1610,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 @@ -1635,37 +1695,44 @@ 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]); - /* Removing extra/forced type casting in the retrieved default value. - This is done in order to avoid unnecessary entries in the diff results. + //Overriding the default value if the column is identity + if(!itr->second[ParsersAttributes::IDENTITY_TYPE].isEmpty()) + col.setIdentityType(itr->second[ParsersAttributes::IDENTITY_TYPE]); + else + { + /* Removing extra/forced type casting in the retrieved default value. + This is done in order to avoid unnecessary entries in the diff results. - For instance: say in the model we have a column with the following configutation: - > varchar(3) default 'foo' + For instance: say in the model we have a column with the following configutation: + > varchar(3) default 'foo' - Now, when importing the same column the default value for it will be something like: - > varchar(3) default 'foo'::character varying + Now, when importing the same column the default value for it will be something like: + > varchar(3) default 'foo'::character varying - Since the extra chars in the default value of the imported column are redundant (casting - varchar to character varying) we remove the '::character varying'. The idea here is to eliminate - the cast if the casting is equivalent to the column type. */ + Since the extra chars in the default value of the imported column are redundant (casting + varchar to character varying) we remove the '::character varying'. The idea here is to eliminate + the cast if the casting is equivalent to the column type. */ - def_val = itr->second[ParsersAttributes::DEFAULT_VALUE]; + def_val = itr->second[ParsersAttributes::DEFAULT_VALUE]; - if(!def_val.startsWith(QString("nextval(")) && def_val.contains(QString("::"))) - { - QStringList values = def_val.split(QString("::")); + if(!def_val.startsWith(QString("nextval(")) && def_val.contains(QString("::"))) + { + QStringList values = def_val.split(QString("::")); - if(values.size() > 1 && - ((~col.getType() == values[1]) || - (~col.getType() == QString("char") && values[1] == QString("bpchar")) || - (col.getType().isUserType() && (~col.getType()).endsWith(values[1])))) - def_val=values[0]; - } + if(values.size() > 1 && + ((~col.getType() == values[1]) || + (~col.getType() == QString("char") && values[1] == QString("bpchar")) || + (col.getType().isUserType() && (~col.getType()).endsWith(values[1])))) + def_val=values[0]; + } - col.setDefaultValue(def_val); + col.setDefaultValue(def_val); + } //Checking if the collation used by the column exists, if not it'll be created when auto_resolve_deps is checked if(auto_resolve_deps && !itr->second[ParsersAttributes::COLLATION].isEmpty()) @@ -1781,11 +1848,54 @@ void DatabaseImportHelper::createTrigger(attribs_map &attribs) } } +QStringList DatabaseImportHelper::parseIndexExpressions(const QString &expr) +{ + int open_paren = 0, close_paren = 0, pos = 0; + QStringList expressions; + QChar chr; + QString word; + bool open_apos = false; + + if(!expr.isEmpty()) + { + while(pos < expr.length()) + { + chr = expr[pos++]; + word += chr; + + if(chr == QChar('\'')) + open_apos = !open_apos; + + if(!open_apos && chr == QChar('(')) + open_paren++; + else if(!open_apos && chr == QChar(')')) + close_paren++; + + if(chr == QChar(',') || pos == expr.length()) + { + if(open_paren == close_paren) + { + if(word.endsWith(QChar(','))) + word.remove(word.length() - 1, 1); + + if(word.contains('(') && word.contains(')')) + expressions.push_back(word.trimmed()); + + word.clear(); + open_paren = close_paren = 0; + } + } + } + } + + return(expressions); +} + void DatabaseImportHelper::createIndex(attribs_map &attribs) { try { - QStringList cols, opclasses, collations; + QStringList cols, opclasses, collations, exprs; IndexElement elem; BaseTable *parent_tab=nullptr; Collation *coll=nullptr; @@ -1812,12 +1922,7 @@ void DatabaseImportHelper::createIndex(attribs_map &attribs) cols=Catalog::parseArrayValues(attribs[ParsersAttributes::COLUMNS]); collations=Catalog::parseArrayValues(attribs[ParsersAttributes::COLLATIONS]); opclasses=Catalog::parseArrayValues(attribs[ParsersAttributes::OP_CLASSES]); - - if(!attribs[ParsersAttributes::EXPRESSIONS].isEmpty()) - { - elem.setExpression(attribs[ParsersAttributes::EXPRESSIONS]); - attribs[ParsersAttributes::ELEMENTS]+=elem.getCodeDefinition(SchemaParser::XML_DEFINITION); - } + exprs = parseIndexExpressions(attribs[ParsersAttributes::EXPRESSIONS]); for(i=0; i < cols.size(); i++) { @@ -1830,19 +1935,26 @@ void DatabaseImportHelper::createIndex(attribs_map &attribs) else elem.setExpression(getColumnName(attribs[ParsersAttributes::TABLE], cols[i])); } + else if(!exprs.isEmpty()) + { + elem.setExpression(exprs.front()); + exprs.pop_front(); + } if(i < collations.size() && collations[i]!=QString("0")) { coll_name=getDependencyObject(collations[i], OBJ_COLLATION, false, true, false); coll=dynamic_cast(dbmodel->getObject(coll_name, OBJ_COLLATION)); - if(coll) + //Even if the collation exists we'll ignore it when it is the "pg_catalog.default" + if(coll && (!coll->isSystemObject() || + (coll->isSystemObject() && coll->getName() != QString("default")))) elem.setCollation(coll); } if(i < opclasses.size() && opclasses[i]!=QString("0")) { - opc_name=getDependencyObject(opclasses[i], OBJ_OPCLASS, false, true, false); + opc_name=getDependencyObject(opclasses[i], OBJ_OPCLASS, true, true, false); opclass=dynamic_cast(dbmodel->getObject(opc_name, OBJ_OPCLASS)); if(opclass) @@ -1891,7 +2003,7 @@ void DatabaseImportHelper::createConstraint(attribs_map &attribs) if(attribs[ParsersAttributes::TYPE]==ParsersAttributes::EX_CONSTR) { - QStringList cols, opclasses, opers; + QStringList cols, opclasses, opers, exprs; ExcludeElement elem; QString opc_name, op_name; OperatorClass *opclass=nullptr; @@ -1904,22 +2016,31 @@ void DatabaseImportHelper::createConstraint(attribs_map &attribs) opers=Catalog::parseArrayValues(attribs[ParsersAttributes::OPERATORS]); opclasses=Catalog::parseArrayValues(attribs[ParsersAttributes::OP_CLASSES]); - if(!attribs[ParsersAttributes::EXPRESSIONS].isEmpty()) - { - elem.setExpression(attribs[ParsersAttributes::EXPRESSIONS]); - attribs[ParsersAttributes::ELEMENTS]+=elem.getCodeDefinition(SchemaParser::XML_DEFINITION); - } + /* Due to the way exclude constraints are constructed (similar to indexes), + * we get the constraint's definition in for of expressions. Internally we use pg_get_constraintdef. + * This way we will get EXCLUDE USING [index type](elements). The elements in this case is a set of expression + * which we work to separate column only references from complex expression. Only complex expression will be used + * and assigned to their exclude constraint elements. Column references are used in exclude elements but relying in + * the cols list above */ + exprs=attribs[ParsersAttributes::EXPRESSIONS] + .replace(QString("EXCLUDE USING %1 (").arg(attribs[ParsersAttributes::INDEX_TYPE]), QString()) + .split(QRegExp("(WITH )(\\+|\\-|\\*|\\/|\\<|\\>|\\=|\\~|\\!|\\@|\\#|\\%|\\^|\\&|\\||\\'|\\?)+((,)?|(\\))?)"), + QString::SkipEmptyParts); for(int i=0; i < cols.size(); i++) { elem=ExcludeElement(); - if(cols[i]!=QString("0")) + if(cols[i] != QString("0")) elem.setColumn(table->getColumn(getColumnName(table_oid, cols[i]))); + else + elem.setExpression(exprs.front().trimmed()); + + exprs.pop_front(); if(i < opclasses.size() && opclasses[i]!=QString("0")) { - opc_name=getDependencyObject(opclasses[i], OBJ_OPCLASS, false, true, false); + opc_name=getDependencyObject(opclasses[i], OBJ_OPCLASS, true, true, false); opclass=dynamic_cast(dbmodel->getObject(opc_name, OBJ_OPCLASS)); if(opclass) @@ -1935,8 +2056,7 @@ void DatabaseImportHelper::createConstraint(attribs_map &attribs) elem.setOperator(oper); } - if(elem.getColumn()) - attribs[ParsersAttributes::ELEMENTS]+=elem.getCodeDefinition(SchemaParser::XML_DEFINITION); + attribs[ParsersAttributes::ELEMENTS]+=elem.getCodeDefinition(SchemaParser::XML_DEFINITION); } } else @@ -1969,6 +2089,22 @@ void DatabaseImportHelper::createConstraint(attribs_map &attribs) } } +void DatabaseImportHelper::createPolicy(attribs_map &attribs) +{ + try + { + attribs[ParsersAttributes::TABLE]=getDependencyObject(attribs[ParsersAttributes::TABLE], OBJ_TABLE, true, auto_resolve_deps, false); + attribs[ParsersAttributes::ROLES]=getObjectNames(attribs[ParsersAttributes::ROLES]).join(','); + loadObjectXML(OBJ_POLICY, attribs); + dbmodel->createPolicy(); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorType(), + __PRETTY_FUNCTION__,__FILE__,__LINE__, &e, xmlparser->getXMLBuffer()); + } +} + void DatabaseImportHelper::createEventTrigger(attribs_map &attribs) { try @@ -2040,6 +2176,13 @@ void DatabaseImportHelper::createPermission(attribs_map &attribs) { role=dynamic_cast(dbmodel->getObject(role_name, OBJ_ROLE)); + if(auto_resolve_deps && !role_name.isEmpty() && !role) + { + QString oid = catalog.getObjectOID(role_name, OBJ_ROLE); + getDependencyObject(oid, OBJ_ROLE); + role=dynamic_cast(dbmodel->getObject(role_name, OBJ_ROLE)); + } + /* If the role doesn't exists and there is a name defined, throws an error because the roles wasn't found on the model */ if(!role && !role_name.isEmpty()) @@ -2120,7 +2263,7 @@ void DatabaseImportHelper::destroyDetachedColumns(void) dbmodel->disconnectRelationships(); - emit s_progressUpdated(95, + emit s_progressUpdated(100, trUtf8("Destroying unused detached columns..."), OBJ_COLUMN); @@ -2157,7 +2300,7 @@ void DatabaseImportHelper::assignSequencesToColumns(void) { Table *table=nullptr; Column *col=nullptr; - emit s_progressUpdated(95, + emit s_progressUpdated(100, trUtf8("Assigning sequences to columns..."), OBJ_SEQUENCE); @@ -2310,7 +2453,7 @@ QString DatabaseImportHelper::getObjectName(const QString &oid, bool signature_f obj_name.prepend(sch_name + QString(".")); //Formatting the name in form of signature (only for functions and operators) - if(signature_form && (obj_type==OBJ_FUNCTION || obj_type==OBJ_OPERATOR || obj_type==OBJ_AGGREGATE || obj_type==OBJ_OPFAMILY)) + if(signature_form && (obj_type==OBJ_FUNCTION || obj_type==OBJ_OPERATOR || obj_type==OBJ_AGGREGATE || obj_type==OBJ_OPFAMILY || obj_type==OBJ_OPCLASS)) { QStringList params; @@ -2358,7 +2501,7 @@ QString DatabaseImportHelper::getObjectName(const QString &oid, bool signature_f obj_name += QString(" USING %1").arg(obj_attr[ParsersAttributes::INDEX_TYPE]); } - if(obj_type != OBJ_OPFAMILY) + if(obj_type != OBJ_OPFAMILY && obj_type != OBJ_OPCLASS) obj_name+=QString("(") + params.join(',') + QString(")"); } @@ -2429,6 +2572,7 @@ QString DatabaseImportHelper::getType(const QString &oid_str, bool generate_xml, QString xml_def, sch_name, obj_name, aux_name; unsigned type_oid=oid_str.toUInt(), elem_tp_oid = 0, dimension=0, object_id=type_attr[ParsersAttributes::OBJECT_ID].toUInt(); + bool is_derivated_from_obj = false; if(type_oid > 0) { @@ -2467,6 +2611,7 @@ QString DatabaseImportHelper::getType(const QString &oid_str, bool generate_xml, else obj_type=OBJ_SEQUENCE; + is_derivated_from_obj = true; getDependencyObject(type_attr[ParsersAttributes::OBJECT_ID], obj_type, true, true, false); } @@ -2485,19 +2630,19 @@ QString DatabaseImportHelper::getType(const QString &oid_str, bool generate_xml, !obj_name.contains(QRegExp(QString("^(\\\")?(%1)(\\\")?(\\.)").arg(sch_name)))) obj_name.prepend(sch_name + QString(".")); - /* In case of auto resolve dependencies, if the type is a user defined one and was not created in the database - model but its attributes were retrieved the object will be created to avoid reference errors */ + /* In case of auto resolve dependencies, if the type is a user defined one and is not derivated from table/view/sequence and + was not created in the database model but its attributes were retrieved, the object will be created to avoid reference errors */ aux_name = obj_name; aux_name.remove(QString("[]")); - if(auto_resolve_deps && !type_attr.empty() && + if(auto_resolve_deps && !type_attr.empty() && !is_derivated_from_obj && type_oid > catalog.getLastSysObjectOID() && !dbmodel->getType(aux_name)) { //If the type is not an array one we simply use the current type attributes map - if(type_attr[ParsersAttributes::CATEGORY] != QString("A")) + if(type_attr[ParsersAttributes::CATEGORY] != QString("A")) createObject(type_attr); /* In case the type is an array one we should use the oid held by "element" attribute to create the type related to current one */ - else if(elem_tp_oid > catalog.getLastSysObjectOID() && types.count(elem_tp_oid)) + else if(elem_tp_oid > catalog.getLastSysObjectOID() && types.count(elem_tp_oid)) createObject(types[elem_tp_oid]); } diff --git a/libpgmodeler_ui/src/databaseimporthelper.h b/libpgmodeler_ui/src/databaseimporthelper.h index e4bffc962..928843075 100644 --- a/libpgmodeler_ui/src/databaseimporthelper.h +++ b/libpgmodeler_ui/src/databaseimporthelper.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -154,6 +154,7 @@ class DatabaseImportHelper: public QObject { void createTrigger(attribs_map &attribs); void createIndex(attribs_map &attribs); void createConstraint(attribs_map &attribs); + void createPolicy(attribs_map &attribs); void createPermission(attribs_map &attribs); void createEventTrigger(attribs_map &attribs); void __createTableInheritances(void); @@ -204,6 +205,10 @@ class DatabaseImportHelper: public QObject { //! \brief Return a string containing all attributes and their values in a formatted way QString dumpObjectAttributes(attribs_map &attribs); + /*! \brief Parse a set of expressions related to an index returned by the pg_get_expr(oid) and separates + * them as a string list. */ + QStringList parseIndexExpressions(const QString &expr); + public: DatabaseImportHelper(QObject *parent=0); diff --git a/libpgmodeler_ui/src/databasewidget.cpp b/libpgmodeler_ui/src/databasewidget.cpp index 78dd9b15b..2c8fbb2ac 100644 --- a/libpgmodeler_ui/src/databasewidget.cpp +++ b/libpgmodeler_ui/src/databasewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -69,7 +69,7 @@ DatabaseWidget::DatabaseWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_DA lccollate_cmb->addItems(loc_list); lcctype_cmb->addItems(loc_list); - setMinimumSize(560, 340); + setMinimumSize(560, 380); } catch(Exception &e) { @@ -109,6 +109,9 @@ void DatabaseWidget::setAttributes(DatabaseModel *model) def_tablespace_sel->setModel(model); def_tablespace_sel->setSelectedObject(model->getDefaultObject(OBJ_TABLESPACE)); + allow_conn_chk->setChecked(model->isAllowConnections()); + is_template_chk->setChecked(model->isTemplate()); + BaseObjectWidget::setAttributes(model, model, nullptr); } } @@ -143,6 +146,8 @@ void DatabaseWidget::applyConfiguration(void) model->setDefaultObject(def_owner_sel->getSelectedObject(), OBJ_ROLE); model->setDefaultObject(def_collation_sel->getSelectedObject(), OBJ_COLLATION); model->setDefaultObject(def_tablespace_sel->getSelectedObject(), OBJ_TABLESPACE); + model->setIsTemplate(is_template_chk->isChecked()); + model->setAllowConnections(allow_conn_chk->isChecked()); finishConfiguration(); } diff --git a/libpgmodeler_ui/src/databasewidget.h b/libpgmodeler_ui/src/databasewidget.h index d2b3a8721..dbc7b1aef 100644 --- a/libpgmodeler_ui/src/databasewidget.h +++ b/libpgmodeler_ui/src/databasewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/datamanipulationform.cpp b/libpgmodeler_ui/src/datamanipulationform.cpp index 2611f305a..0e7394af5 100644 --- a/libpgmodeler_ui/src/datamanipulationform.cpp +++ b/libpgmodeler_ui/src/datamanipulationform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -21,6 +21,8 @@ #include "pgmodeleruins.h" #include "pgmodelerns.h" #include "plaintextitemdelegate.h" +#include "baseform.h" +#include "bulkdataeditwidget.h" const QColor DataManipulationForm::ROW_COLORS[3]={ QColor(QString("#C0FFC0")), QColor(QString("#FFFFC0")), QColor(QString("#FFC0C0")) }; const unsigned DataManipulationForm::NO_OPERATION=0; @@ -114,6 +116,7 @@ DataManipulationForm::DataManipulationForm(QWidget * parent, Qt::WindowFlags f): connect(duplicate_tb, SIGNAL(clicked()), this, SLOT(duplicateRows())); connect(undo_tb, SIGNAL(clicked()), this, SLOT(undoOperations())); connect(save_tb, SIGNAL(clicked()), this, SLOT(saveChanges())); + connect(bulkedit_tb, SIGNAL(clicked()), this, SLOT(bulkDataEdit())); connect(ord_columns_lst, SIGNAL(currentRowChanged(int)), this, SLOT(enableColumnControlButtons())); connect(move_down_tb, SIGNAL(clicked()), this, SLOT(swapColumns())); connect(move_up_tb, SIGNAL(clicked()), this, SLOT(swapColumns())); @@ -160,6 +163,9 @@ DataManipulationForm::DataManipulationForm(QWidget * parent, Qt::WindowFlags f): act = item_menu.addAction(delete_tb->icon(), trUtf8("Delete row(s)"), this, SLOT(markDeleteOnRows()), delete_tb->shortcut()); act->setEnabled(delete_tb->isEnabled()); + + act = item_menu.addAction(bulkedit_tb->icon(), trUtf8("Edit cell(s)"), this, SLOT(bulkDataEdit()), bulkedit_tb->shortcut()); + act->setEnabled(bulkedit_tb->isEnabled()); } item_menu.exec(QCursor::pos()); @@ -216,6 +222,11 @@ void DataManipulationForm::setAttributes(Connection conn, const QString curr_sch } } +void DataManipulationForm::setHasCsvClipboard(bool value) +{ + has_csv_clipboard = value; +} + void DataManipulationForm::listTables(void) { table_cmb->clear(); @@ -299,7 +310,7 @@ void DataManipulationForm::retrieveData(void) unsigned limit=limit_spb->value(); //Building the where clause - if(!filter_txt->toPlainText().isEmpty()) + if(!filter_txt->toPlainText().trimmed().isEmpty()) query+=QString(" WHERE ") + filter_txt->toPlainText(); //Building the order by clause @@ -363,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) { @@ -408,6 +422,7 @@ void DataManipulationForm::enableRowControlButtons(void) table_cmb->currentData().toUInt() == OBJ_TABLE && !col_names.isEmpty()); browse_tabs_tb->setEnabled((!fk_infos.empty() || !ref_fk_infos.empty()) && sel_ranges.count() == 1 && sel_ranges.at(0).rowCount() == 1); + bulkedit_tb->setEnabled(sel_ranges.count() != 0); } void DataManipulationForm::resetAdvancedControls(void) @@ -958,7 +973,7 @@ void DataManipulationForm::markDeleteOnRows(void) results_tbw->clearSelection(); } -void DataManipulationForm::addRow(void) +void DataManipulationForm::addRow(bool focus_new_row) { int row=results_tbw->rowCount(); QTableWidgetItem *item=nullptr; @@ -984,15 +999,17 @@ void DataManipulationForm::addRow(void) results_tbw->setVerticalHeaderItem(row, new QTableWidgetItem(QString::number(row + 1))); results_tbw->blockSignals(false); - results_tbw->setFocus(); markOperationOnRow(OP_INSERT, row); - - results_tbw->clearSelection(); item=results_tbw->item(row, 0); - results_tbw->setCurrentCell(row, 0, QItemSelectionModel::ClearAndSelect); - results_tbw->editItem(item); hint_frm->setVisible(true); + + if(focus_new_row) + { + results_tbw->setFocus(); + results_tbw->setCurrentCell(row, 0, QItemSelectionModel::ClearAndSelect); + results_tbw->editItem(item); + } } void DataManipulationForm::duplicateRows(void) @@ -1005,7 +1022,7 @@ void DataManipulationForm::duplicateRows(void) { for(int row=sel_rng.topRow(); row <= sel_rng.bottomRow(); row++) { - addRow(); + addRow(false); for(int col=0; col < results_tbw->columnCount(); col++) { @@ -1014,6 +1031,8 @@ void DataManipulationForm::duplicateRows(void) } } } + + results_tbw->setCurrentItem(results_tbw->item(results_tbw->rowCount() - 1, 0), QItemSelectionModel::ClearAndSelect); } } @@ -1108,6 +1127,31 @@ void DataManipulationForm::browseReferrerTable(void) browseTable(qobject_cast(sender())->data().toString(), true); } +void DataManipulationForm::bulkDataEdit(void) +{ + BaseForm base_frm; + BulkDataEditWidget *bulkedit_wgt = new BulkDataEditWidget; + + base_frm.setMainWidget(bulkedit_wgt); + base_frm.setButtonConfiguration(Messagebox::OK_CANCEL_BUTTONS); + + if(base_frm.exec() == QDialog::Accepted) + { + QList sel_ranges=results_tbw->selectedRanges(); + + for(auto range : sel_ranges) + { + for(int row = range.topRow(); row <= range.bottomRow(); row++) + { + for(int col = range.leftColumn(); col <= range.rightColumn(); col++) + { + results_tbw->item(row, col)->setText(bulkedit_wgt->value_edt->toPlainText()); + } + } + } + } +} + void DataManipulationForm::browseReferencedTable(void) { browseTable(qobject_cast(sender())->data().toString(), false); @@ -1256,6 +1300,7 @@ QString DataManipulationForm::getDMLCommand(int row) unsigned op_type=results_tbw->verticalHeaderItem(row)->data(Qt::UserRole).toUInt(); QStringList val_list, col_list, flt_list; QString col_name, value; + QVariant data; if(op_type==OP_DELETE || op_type==OP_UPDATE) { @@ -1272,8 +1317,12 @@ QString DataManipulationForm::getDMLCommand(int row) //Creating the where clause with original column's values for(QString pk_col : pk_col_names) { - flt_list.push_back(QString("\"%1\"='%2'").arg(pk_col) - .arg(results_tbw->item(row, col_names.indexOf(pk_col))->data(Qt::UserRole).toString().replace("\'","''"))); + data = results_tbw->item(row, col_names.indexOf(pk_col))->data(Qt::UserRole); + + if(data.toString() == SQLExecutionWidget::COLUMN_NULL_VALUE) + flt_list.push_back(QString("\"%1\" IS NULL").arg(pk_col)); + else + flt_list.push_back(QString("\"%1\"='%2'").arg(pk_col).arg(data.toString().replace("\'","''"))); } } diff --git a/libpgmodeler_ui/src/datamanipulationform.h b/libpgmodeler_ui/src/datamanipulationform.h index d1c1f0f74..30f91b75e 100644 --- a/libpgmodeler_ui/src/datamanipulationform.h +++ b/libpgmodeler_ui/src/datamanipulationform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -108,6 +108,8 @@ class DataManipulationForm: public QDialog, public Ui::DataManipulationForm { //! \brief Defines the connection and current schema and table to be handled, this method should be called before show the dialog void setAttributes(Connection conn, const QString curr_schema=QString("public"), const QString curr_table=QString(), const QString &filter=QString()); + static void setHasCsvClipboard(bool value); + private slots: //! \brief List the tables based upon the current schema void listTables(void); @@ -149,7 +151,7 @@ class DataManipulationForm: public QDialog, public Ui::DataManipulationForm { void markDeleteOnRows(void); //! \brief Add a new row on the grid with the first column with edition enabled - void addRow(void); + void addRow(bool focus_new_row = true); //! \brief Duplicate the selected rows creating new ones with the same values as the selection void duplicateRows(void); @@ -174,6 +176,9 @@ class DataManipulationForm: public QDialog, public Ui::DataManipulationForm { //! brief Browse the referencing table data using the selected row in the results grid void browseReferrerTable(void); + + //! brief Changes the values of the grid selection at once + void bulkDataEdit(void); }; #endif diff --git a/libpgmodeler_ui/src/domainwidget.cpp b/libpgmodeler_ui/src/domainwidget.cpp index cae7d1ba4..a25e8c4ba 100644 --- a/libpgmodeler_ui/src/domainwidget.cpp +++ b/libpgmodeler_ui/src/domainwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -31,15 +31,32 @@ DomainWidget::DomainWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_DOMAIN data_type=nullptr; data_type=new PgSQLTypeWidget(this); - domain_grid->addWidget(data_type,4,0,1,2); - domain_grid->addItem(new QSpacerItem(10,1,QSizePolicy::Fixed,QSizePolicy::Expanding), domain_grid->count()+1, 0, 1, 0); + + QGridLayout *grid = dynamic_cast(dom_attribs_tbw->widget(0)->layout()); + grid->addWidget(data_type, 1, 0, 1, 2); + grid->addItem(new QSpacerItem(10, 1, QSizePolicy::Fixed,QSizePolicy::Expanding), 2, 0, 1, 1); + + constr_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ (ObjectsTableWidget::DUPLICATE_BUTTON), true, this); + constr_tab->setColumnCount(2); + + constr_tab->setHeaderLabel(trUtf8("Name"), 0); + constr_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("constraint_ck")), 0); + + constr_tab->setHeaderLabel(trUtf8("Expression"), 1); + constr_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("codigofonte")), 1); + + grid = dynamic_cast(dom_attribs_tbw->widget(1)->layout()); + grid->addWidget(constr_tab, 2, 0, 1, 2); + + connect(constr_tab, SIGNAL(s_rowAdded(int)), this, SLOT(handleConstraint(int))); + connect(constr_tab, SIGNAL(s_rowUpdated(int)), this, SLOT(handleConstraint(int))); + connect(constr_tab, SIGNAL(s_rowEdited(int)), this, SLOT(editConstraint(int))); configureFormLayout(domain_grid, OBJ_DOMAIN); setRequiredField(data_type); - configureTabOrder({ def_value_edt, constr_name_edt, not_null_chk, - check_expr_txt, data_type }); + configureTabOrder({ def_value_edt, not_null_chk, data_type, constr_name_edt, check_expr_txt }); - setMinimumSize(580, 530); + setMinimumSize(580, 580); } catch(Exception &e) { @@ -47,15 +64,6 @@ DomainWidget::DomainWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_DOMAIN } } -void DomainWidget::hideEvent(QHideEvent *event) -{ - def_value_edt->clear(); - check_expr_txt->clear(); - constr_name_edt->clear(); - not_null_chk->setChecked(false); - BaseObjectWidget::hideEvent(event); -} - void DomainWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Domain *domain) { PgSQLType type; @@ -66,14 +74,43 @@ void DomainWidget::setAttributes(DatabaseModel *model, OperationList *op_list, S { type=domain->getType(); def_value_edt->setText(domain->getDefaultValue()); - check_expr_txt->setPlainText(domain->getExpression()); - constr_name_edt->setText(domain->getConstraintName()); not_null_chk->setChecked(domain->isNotNull()); + + constr_tab->blockSignals(true); + + for(auto itr : domain->getCheckConstraints()) + { + constr_tab->addRow(); + constr_tab->setCellText(itr.first, constr_tab->getRowCount() - 1, 0); + constr_tab->setCellText(itr.second, constr_tab->getRowCount() - 1, 1); + } + + constr_tab->clearSelection(); + constr_tab->blockSignals(false); } data_type->setAttributes(type, model); } +void DomainWidget::handleConstraint(int row) +{ + if(!constr_name_edt->text().isEmpty() && !check_expr_txt->toPlainText().isEmpty()) + { + constr_tab->setCellText(constr_name_edt->text(), row, 0); + constr_tab->setCellText(check_expr_txt->toPlainText(), row, 1); + constr_name_edt->clear(); + check_expr_txt->clear(); + } + else if(constr_tab->getCellText(row, 0).isEmpty()) + constr_tab->removeRow(row); +} + +void DomainWidget::editConstraint(int row) +{ + constr_name_edt->setText(constr_tab->getCellText(row, 0)); + check_expr_txt->setPlainText(constr_tab->getCellText(row, 1)); +} + void DomainWidget::applyConfiguration(void) { try @@ -84,9 +121,11 @@ void DomainWidget::applyConfiguration(void) domain=dynamic_cast(this->object); domain->setType(data_type->getPgSQLType()); domain->setDefaultValue(def_value_edt->text()); - domain->setExpression(check_expr_txt->toPlainText()); - domain->setConstraintName(constr_name_edt->text()); domain->setNotNull(not_null_chk->isChecked()); + domain->removeCheckConstraints(); + + for(unsigned row = 0; row < constr_tab->getRowCount(); row++) + domain->addCheckConstraint(constr_tab->getCellText(row, 0), constr_tab->getCellText(row, 1)); BaseObjectWidget::applyConfiguration(); finishConfiguration(); diff --git a/libpgmodeler_ui/src/domainwidget.h b/libpgmodeler_ui/src/domainwidget.h index 7c4ffa26c..1f538bc85 100644 --- a/libpgmodeler_ui/src/domainwidget.h +++ b/libpgmodeler_ui/src/domainwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -28,6 +28,7 @@ #include "baseobjectwidget.h" #include "ui_domainwidget.h" #include "pgsqltypewidget.h" +#include "objectstablewidget.h" class DomainWidget: public BaseObjectWidget, public Ui::DomainWidget { private: @@ -35,14 +36,16 @@ class DomainWidget: public BaseObjectWidget, public Ui::DomainWidget { SyntaxHighlighter *check_expr_hl; PgSQLTypeWidget *data_type; + ObjectsTableWidget *constr_tab; public: DomainWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Domain *domain); private slots: - void hideEvent(QHideEvent *event); - + void handleConstraint(int row); + void editConstraint(int row); + public slots: void applyConfiguration(void); }; diff --git a/libpgmodeler_ui/src/donatewidget.cpp b/libpgmodeler_ui/src/donatewidget.cpp index a5c2a33bc..41371f6f9 100644 --- a/libpgmodeler_ui/src/donatewidget.cpp +++ b/libpgmodeler_ui/src/donatewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/donatewidget.h b/libpgmodeler_ui/src/donatewidget.h index 997719f97..764e94537 100644 --- a/libpgmodeler_ui/src/donatewidget.h +++ b/libpgmodeler_ui/src/donatewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/elementswidget.cpp b/libpgmodeler_ui/src/elementswidget.cpp index 4c8c31c86..e4f7b3479 100644 --- a/libpgmodeler_ui/src/elementswidget.cpp +++ b/libpgmodeler_ui/src/elementswidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -30,7 +30,7 @@ ElementsWidget::ElementsWidget(QWidget *parent) : QWidget(parent) elem_expr_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); parent_obj=nullptr; - elements_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ ObjectTableWidget::DUPLICATE_BUTTON, true, this); + elements_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ ObjectsTableWidget::DUPLICATE_BUTTON, true, this); op_class_sel=new ObjectSelectorWidget(OBJ_OPCLASS, true, this); collation_sel=new ObjectSelectorWidget(OBJ_COLLATION, true, this); operator_sel=new ObjectSelectorWidget(OBJ_OPERATOR, true, this); diff --git a/libpgmodeler_ui/src/elementswidget.h b/libpgmodeler_ui/src/elementswidget.h index a9e7ef055..a14045141 100644 --- a/libpgmodeler_ui/src/elementswidget.h +++ b/libpgmodeler_ui/src/elementswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include #include "ui_elementswidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "objectselectorwidget.h" #include "baseobjectwidget.h" @@ -47,7 +47,7 @@ class ElementsWidget: public QWidget, public Ui::ElementsWidget { SyntaxHighlighter *elem_expr_hl; //! \brief Table widget used to control the index elements - ObjectTableWidget *elements_tab; + ObjectsTableWidget *elements_tab; //! \brief Operator class selector ObjectSelectorWidget *op_class_sel, diff --git a/libpgmodeler_ui/src/eventtriggerwidget.cpp b/libpgmodeler_ui/src/eventtriggerwidget.cpp index 5b1137504..5286c6c49 100644 --- a/libpgmodeler_ui/src/eventtriggerwidget.cpp +++ b/libpgmodeler_ui/src/eventtriggerwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,12 +27,12 @@ EventTriggerWidget::EventTriggerWidget(QWidget *parent): BaseObjectWidget(parent Ui_EventTriggerWidget::setupUi(this); function_sel=new ObjectSelectorWidget(OBJ_FUNCTION, true, this); - filter_tab=new ObjectTableWidget(ObjectTableWidget::ADD_BUTTON | - ObjectTableWidget::EDIT_BUTTON | - ObjectTableWidget::UPDATE_BUTTON | - ObjectTableWidget::REMOVE_BUTTON | - ObjectTableWidget::REMOVE_ALL_BUTTON | - ObjectTableWidget::MOVE_BUTTONS, false, this); + filter_tab=new ObjectsTableWidget(ObjectsTableWidget::ADD_BUTTON | + ObjectsTableWidget::EDIT_BUTTON | + ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::REMOVE_BUTTON | + ObjectsTableWidget::REMOVE_ALL_BUTTON | + ObjectsTableWidget::MOVE_BUTTONS, false, this); filter_tab->setColumnCount(1); filter_tab->setHeaderLabel(trUtf8("Tag command"), 0); @@ -58,26 +58,19 @@ EventTriggerWidget::EventTriggerWidget(QWidget *parent): BaseObjectWidget(parent connect(filter_tab, SIGNAL(s_rowAdded(int)), this, SLOT(handleTagValue(int))); connect(filter_tab, SIGNAL(s_rowUpdated(int)), this, SLOT(handleTagValue(int))); - connect(filter_tab, &ObjectTableWidget::s_rowsRemoved, - [&](){ filter_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, false); }); + connect(filter_tab, &ObjectsTableWidget::s_rowsRemoved, + [&](){ filter_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, false); }); - connect(filter_tab, &ObjectTableWidget::s_rowEdited, + connect(filter_tab, &ObjectsTableWidget::s_rowEdited, [&](int row){ tag_edt->setText(filter_tab->getCellText(row, 0)); }); connect(tag_edt, &QLineEdit::textChanged, [&](){ - filter_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, !tag_edt->text().isEmpty()); - filter_tab->setButtonsEnabled(ObjectTableWidget::UPDATE_BUTTON, !tag_edt->text().isEmpty()); + filter_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, !tag_edt->text().isEmpty()); + filter_tab->setButtonsEnabled(ObjectsTableWidget::UPDATE_BUTTON, !tag_edt->text().isEmpty()); }); - setMinimumSize(500, 400); -} - -void EventTriggerWidget::hideEvent(QHideEvent *) -{ - filter_tab->removeRows(); - event_cmb->setCurrentIndex(0); - tag_edt->clear(); + setMinimumSize(500, 440); } void EventTriggerWidget::setAttributes(DatabaseModel *model, OperationList *op_list, EventTrigger *event_trig) @@ -107,7 +100,7 @@ void EventTriggerWidget::setAttributes(DatabaseModel *model, OperationList *op_l filter_tab->clearSelection(); } - filter_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, false); + filter_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, false); } void EventTriggerWidget::applyConfiguration(void) @@ -143,7 +136,7 @@ void EventTriggerWidget::handleTagValue(int row) filter_tab->setCellText(tag_edt->text().simplified(), row, 0); tag_edt->clear(); filter_tab->clearSelection(); - filter_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, false); + filter_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, false); } else if(filter_tab->getCellText(row, 0).isEmpty()) filter_tab->removeRow(row); diff --git a/libpgmodeler_ui/src/eventtriggerwidget.h b/libpgmodeler_ui/src/eventtriggerwidget.h index 4f10da30c..b6dfb1e41 100644 --- a/libpgmodeler_ui/src/eventtriggerwidget.h +++ b/libpgmodeler_ui/src/eventtriggerwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -26,19 +26,17 @@ #define EVENT_TRIGGER_WIDGET_H #include "baseobjectwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "ui_eventtriggerwidget.h" class EventTriggerWidget: public BaseObjectWidget, public Ui::EventTriggerWidget { private: Q_OBJECT - ObjectTableWidget *filter_tab; + ObjectsTableWidget *filter_tab; ObjectSelectorWidget *function_sel; - void hideEvent(QHideEvent*); - public: EventTriggerWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, EventTrigger *event_trig); diff --git a/libpgmodeler_ui/src/extensionwidget.cpp b/libpgmodeler_ui/src/extensionwidget.cpp index 0b46a7abb..80de47971 100644 --- a/libpgmodeler_ui/src/extensionwidget.cpp +++ b/libpgmodeler_ui/src/extensionwidget.cpp @@ -25,15 +25,6 @@ void ExtensionWidget::setAttributes(DatabaseModel *model, OperationList *op_list } } -void ExtensionWidget::hideEvent(QHideEvent *event) -{ - handles_type_chk->setEnabled(true); - handles_type_chk->setChecked(false); - cur_ver_edt->clear(); - old_ver_edt->clear(); - BaseObjectWidget::hideEvent(event); -} - void ExtensionWidget::applyConfiguration(void) { try diff --git a/libpgmodeler_ui/src/extensionwidget.h b/libpgmodeler_ui/src/extensionwidget.h index ddb67188e..a665234e3 100644 --- a/libpgmodeler_ui/src/extensionwidget.h +++ b/libpgmodeler_ui/src/extensionwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -37,9 +37,6 @@ class ExtensionWidget: public BaseObjectWidget, public Ui::ExtensionWidget { void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Extension *ext); - private slots: - void hideEvent(QHideEvent *event); - public slots: void applyConfiguration(void); }; diff --git a/libpgmodeler_ui/src/findreplacewidget.cpp b/libpgmodeler_ui/src/findreplacewidget.cpp index 6d8af3026..25726970e 100644 --- a/libpgmodeler_ui/src/findreplacewidget.cpp +++ b/libpgmodeler_ui/src/findreplacewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/findreplacewidget.h b/libpgmodeler_ui/src/findreplacewidget.h index fb44c0c4b..1c5fbcd17 100644 --- a/libpgmodeler_ui/src/findreplacewidget.h +++ b/libpgmodeler_ui/src/findreplacewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/functionwidget.cpp b/libpgmodeler_ui/src/functionwidget.cpp index db5161f95..329a66c00 100644 --- a/libpgmodeler_ui/src/functionwidget.cpp +++ b/libpgmodeler_ui/src/functionwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -47,16 +47,16 @@ FunctionWidget::FunctionWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_FU vlayout->addWidget(ret_type); vlayout->addSpacerItem(spacer); - return_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - ObjectTableWidget::UPDATE_BUTTON, true, this); + return_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + ObjectsTableWidget::UPDATE_BUTTON, true, this); return_tab->setColumnCount(2); return_tab->setHeaderLabel(trUtf8("Column"), 0); return_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("column")),0); return_tab->setHeaderLabel(trUtf8("Type"), 1); return_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("usertype")),1); - parameters_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - ObjectTableWidget::UPDATE_BUTTON, true, this); + parameters_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + ObjectsTableWidget::UPDATE_BUTTON, true, this); parameters_tab->setColumnCount(4); parameters_tab->setHeaderLabel(trUtf8("Name"),0); parameters_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("parameter")),0); @@ -125,7 +125,7 @@ FunctionWidget::FunctionWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_FU void FunctionWidget::handleParameter(Parameter param, int result) { int lin_cnt, lin; - ObjectTableWidget *table=nullptr; + ObjectsTableWidget *table=nullptr; //Selects the table to be handled according to its visibility if(parameters_tab->isVisible()) @@ -158,7 +158,7 @@ void FunctionWidget::handleParameter(Parameter param, int result) void FunctionWidget::duplicateParameter(int curr_row, int new_row) { Parameter new_param; - ObjectTableWidget *table=nullptr; + ObjectsTableWidget *table=nullptr; //Selects the table to be handled according to its visibility if(parameters_tab->isVisible()) @@ -173,7 +173,7 @@ void FunctionWidget::duplicateParameter(int curr_row, int new_row) void FunctionWidget::showParameterForm(void) { QObject *obj_sender=sender(); - ObjectTableWidget *table=nullptr; + ObjectsTableWidget *table=nullptr; Parameter aux_param; int lin_idx; ParameterWidget *parameter_wgt=new ParameterWidget; @@ -181,7 +181,7 @@ void FunctionWidget::showParameterForm(void) if(obj_sender==parameters_tab || obj_sender==return_tab) { - table=dynamic_cast(obj_sender); + table=dynamic_cast(obj_sender); parameter_wgt->param_in_chk->setEnabled(obj_sender==parameters_tab); parameter_wgt->param_out_chk->setEnabled(obj_sender==parameters_tab); @@ -202,7 +202,7 @@ void FunctionWidget::showParameterForm(void) } } -Parameter FunctionWidget::getParameter(ObjectTableWidget *tab, unsigned row) +Parameter FunctionWidget::getParameter(ObjectsTableWidget *tab, unsigned row) { Parameter param; QString str_aux; @@ -232,7 +232,7 @@ Parameter FunctionWidget::getParameter(ObjectTableWidget *tab, unsigned row) return(param); } -void FunctionWidget::showParameterData(Parameter param, ObjectTableWidget *tab, unsigned row) +void FunctionWidget::showParameterData(Parameter param, ObjectsTableWidget *tab, unsigned row) { if(tab) { @@ -347,19 +347,6 @@ void FunctionWidget::setAttributes(DatabaseModel *model, OperationList *op_list, ret_type->setAttributes(aux_type, model); } -void FunctionWidget::hideEvent(QHideEvent *event) -{ - language_cmb->clear(); - parameters_tab->removeRows(); - return_tab->removeRows(); - source_code_txt->clear(); - symbol_edt->clear(); - library_edt->clear(); - func_config_twg->setCurrentIndex(0); - - BaseObjectWidget::hideEvent(event); -} - void FunctionWidget::alternateReturnTypes(void) { QObject *obj_sender=sender(); diff --git a/libpgmodeler_ui/src/functionwidget.h b/libpgmodeler_ui/src/functionwidget.h index 05f6ab475..491863c28 100644 --- a/libpgmodeler_ui/src/functionwidget.h +++ b/libpgmodeler_ui/src/functionwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -28,7 +28,7 @@ #include "baseobjectwidget.h" #include "ui_functionwidget.h" #include "pgsqltypewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "codecompletionwidget.h" #include "parameterwidget.h" #include "numberedtexteditor.h" @@ -49,22 +49,20 @@ class FunctionWidget: public BaseObjectWidget, public Ui::FunctionWidget { PgSQLTypeWidget *ret_type; //! \brief Table that represents the table returned by the function - ObjectTableWidget *return_tab, + ObjectsTableWidget *return_tab, //! \brief Table used to store the function's parameters *parameters_tab; //! \brief Returns a parameter configured based upon the specified table and line - Parameter getParameter(ObjectTableWidget *tab, unsigned row); + Parameter getParameter(ObjectsTableWidget *tab, unsigned row); //! \brief Shows the parameter data on the specified table at the specified line - void showParameterData(Parameter param, ObjectTableWidget *tab, unsigned row); + void showParameterData(Parameter param, ObjectsTableWidget *tab, unsigned row); //! \brief Validates the new function configuration in relation to the other objects that references it. void validateConfiguredFunction(void); - void hideEvent(QHideEvent *event); - public: FunctionWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/generalconfigwidget.cpp b/libpgmodeler_ui/src/generalconfigwidget.cpp index eb38cc611..b9dada0f9 100644 --- a/libpgmodeler_ui/src/generalconfigwidget.cpp +++ b/libpgmodeler_ui/src/generalconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -524,9 +524,9 @@ void GeneralConfigWidget::applyConfiguration(void) ObjectsScene::setInvertRangeSelectionTrigger(invert_rangesel_chk->isChecked()); ObjectsScene::setGridSize(grid_size_spb->value()); - ObjectsScene::setGridOptions(config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::SHOW_CANVAS_GRID]!=ParsersAttributes::_FALSE_, - config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::ALIGN_OBJS_TO_GRID]!=ParsersAttributes::_FALSE_, - config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::SHOW_PAGE_DELIMITERS]!=ParsersAttributes::_FALSE_); + ObjectsScene::setGridOptions(config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::SHOW_CANVAS_GRID]==ParsersAttributes::_TRUE_, + config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::ALIGN_OBJS_TO_GRID]==ParsersAttributes::_TRUE_, + config_params[ParsersAttributes::CONFIGURATION][ParsersAttributes::SHOW_PAGE_DELIMITERS]==ParsersAttributes::_TRUE_); OperationList::setMaximumSize(oplist_size_spb->value()); BaseTableView::setHideExtAttributes(hide_ext_attribs_chk->isChecked()); @@ -557,7 +557,10 @@ void GeneralConfigWidget::restoreDefaults(void) { try { - BaseConfigWidget::restoreDefaults(GlobalAttributes::GENERAL_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); @@ -639,8 +642,3 @@ void GeneralConfigWidget::selectSourceEditor(void) if(sel_editor_dlg.result()==QDialog::Accepted) source_editor_edt->setText(sel_editor_dlg.selectedFiles().at(0)); } - -void GeneralConfigWidget::hideEvent(QHideEvent *) -{ - settings_twg->setCurrentIndex(0); -} diff --git a/libpgmodeler_ui/src/generalconfigwidget.h b/libpgmodeler_ui/src/generalconfigwidget.h index 5ccd9d1c2..48fbc0128 100644 --- a/libpgmodeler_ui/src/generalconfigwidget.h +++ b/libpgmodeler_ui/src/generalconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -51,12 +51,11 @@ class GeneralConfigWidget: public BaseConfigWidget, public Ui::GeneralConfigWidg *save_last_pos_ht, *invert_rangesel_ht, *disable_smooth_ht, *hide_ext_attribs_ht, *hide_table_tags_ht, *hide_rel_name_ht, *code_completion_ht, *use_placeholders_ht, *min_obj_opacity_ht, - *autosave_ht, *op_history_ht, *ui_language_ht, *grid_size_ht, *use_curved_lines_ht; + *autosave_ht, *op_history_ht, *ui_language_ht, *grid_size_ht, + *use_curved_lines_ht, *max_result_rows_ht; ColorPickerWidget *line_numbers_cp, *line_numbers_bg_cp, *line_highlight_cp; - void hideEvent(QHideEvent *); - public: GeneralConfigWidget(QWidget * parent=0); diff --git a/libpgmodeler_ui/src/genericsqlwidget.cpp b/libpgmodeler_ui/src/genericsqlwidget.cpp index 9d3613561..e68af13bb 100644 --- a/libpgmodeler_ui/src/genericsqlwidget.cpp +++ b/libpgmodeler_ui/src/genericsqlwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/genericsqlwidget.h b/libpgmodeler_ui/src/genericsqlwidget.h index df1b4e724..41586fdcf 100644 --- a/libpgmodeler_ui/src/genericsqlwidget.h +++ b/libpgmodeler_ui/src/genericsqlwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/hinttextwidget.cpp b/libpgmodeler_ui/src/hinttextwidget.cpp index cf83ed413..2ff0e363b 100644 --- a/libpgmodeler_ui/src/hinttextwidget.cpp +++ b/libpgmodeler_ui/src/hinttextwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/hinttextwidget.h b/libpgmodeler_ui/src/hinttextwidget.h index 06691cdc8..d49c5bf8b 100644 --- a/libpgmodeler_ui/src/hinttextwidget.h +++ b/libpgmodeler_ui/src/hinttextwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/htmlitemdelegate.cpp b/libpgmodeler_ui/src/htmlitemdelegate.cpp index 32cc1ae1d..7374ab006 100644 --- a/libpgmodeler_ui/src/htmlitemdelegate.cpp +++ b/libpgmodeler_ui/src/htmlitemdelegate.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/htmlitemdelegate.h b/libpgmodeler_ui/src/htmlitemdelegate.h index 52eb91e04..902e9d2ee 100644 --- a/libpgmodeler_ui/src/htmlitemdelegate.h +++ b/libpgmodeler_ui/src/htmlitemdelegate.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/indexwidget.cpp b/libpgmodeler_ui/src/indexwidget.cpp index 023dece36..fe8fb3a1c 100644 --- a/libpgmodeler_ui/src/indexwidget.cpp +++ b/libpgmodeler_ui/src/indexwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -69,20 +69,6 @@ IndexWidget::IndexWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_INDEX) } } -void IndexWidget::hideEvent(QHideEvent *event) -{ - BaseObjectWidget::hideEvent(event); - - predicate_txt->clear(); - concurrent_chk->setChecked(false); - unique_chk->setChecked(false); - buffering_chk->setChecked(false); - indexing_cmb->setCurrentIndex(0); - fill_factor_sb->setValue(90); - tabWidget->setCurrentIndex(0); - elements_wgt->clear(); -} - void IndexWidget::selectIndexingType(void) { fast_update_chk->setEnabled(IndexingType(indexing_cmb->currentText())==IndexingType::gin); diff --git a/libpgmodeler_ui/src/indexwidget.h b/libpgmodeler_ui/src/indexwidget.h index f85e9002b..2a52493e3 100644 --- a/libpgmodeler_ui/src/indexwidget.h +++ b/libpgmodeler_ui/src/indexwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_indexwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "elementswidget.h" class IndexWidget: public BaseObjectWidget, public Ui::IndexWidget { @@ -44,7 +44,6 @@ class IndexWidget: public BaseObjectWidget, public Ui::IndexWidget { void setAttributes(DatabaseModel *model, OperationList *op_list, BaseTable *parent_obj, Index *index); private slots: - void hideEvent(QHideEvent *event); void selectIndexingType(void); void enableSortingOptions(void); diff --git a/libpgmodeler_ui/src/languagewidget.cpp b/libpgmodeler_ui/src/languagewidget.cpp index c434eb7a4..146fa04c1 100644 --- a/libpgmodeler_ui/src/languagewidget.cpp +++ b/libpgmodeler_ui/src/languagewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -47,7 +47,7 @@ LanguageWidget::LanguageWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_LA configureTabOrder({ trusted_chk, func_handler_sel, func_validator_sel, func_inline_sel }); - setMinimumSize(600, 380); + setMinimumSize(600, 420); } catch(Exception &e) { @@ -55,15 +55,6 @@ LanguageWidget::LanguageWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_LA } } -void LanguageWidget::hideEvent(QHideEvent *event) -{ - func_handler_sel->clearSelector(); - func_validator_sel->clearSelector(); - func_inline_sel->clearSelector(); - trusted_chk->setChecked(false); - BaseObjectWidget::hideEvent(event); -} - void LanguageWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Language *language) { BaseObjectWidget::setAttributes(model, op_list, language); diff --git a/libpgmodeler_ui/src/languagewidget.h b/libpgmodeler_ui/src/languagewidget.h index e9c4f354e..dad398593 100644 --- a/libpgmodeler_ui/src/languagewidget.h +++ b/libpgmodeler_ui/src/languagewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,8 +36,6 @@ class LanguageWidget: public BaseObjectWidget, public Ui::LanguageWidget { *func_validator_sel, *func_inline_sel; - void hideEvent(QHideEvent *event); - public: LanguageWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/linenumberswidget.cpp b/libpgmodeler_ui/src/linenumberswidget.cpp index 9193feefd..eb8ffb76b 100644 --- a/libpgmodeler_ui/src/linenumberswidget.cpp +++ b/libpgmodeler_ui/src/linenumberswidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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 5b1f18d88..420f63b2c 100644 --- a/libpgmodeler_ui/src/linenumberswidget.h +++ b/libpgmodeler_ui/src/linenumberswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/mainwindow.cpp b/libpgmodeler_ui/src/mainwindow.cpp index 16badb8b9..d7ce6e8b0 100644 --- a/libpgmodeler_ui/src/mainwindow.cpp +++ b/libpgmodeler_ui/src/mainwindow.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -43,6 +43,13 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(par hbox->setContentsMargins(4,4,4,4); canvas_info_parent->setLayout(hbox); + QToolButton *tool_btn = qobject_cast(control_tb->widgetForAction(action_arrange_objects)); + tool_btn->setMenu(&arrange_menu); + tool_btn->setPopupMode(QToolButton::InstantPopup); + arrange_menu.addAction(trUtf8("Grid"), this, SLOT(arrangeObjects())); + arrange_menu.addAction(trUtf8("Hierarchical"), this, SLOT(arrangeObjects())); + arrange_menu.addAction(trUtf8("Scattered"), this, SLOT(arrangeObjects())); + try { models_tbw->tabBar()->setVisible(false); @@ -66,7 +73,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(par grid->addWidget(sql_tool_wgt, 0, 0); views_stw->widget(MANAGE_VIEW)->setLayout(grid); - configuration_form=new ConfigurationForm(nullptr, Qt::WindowTitleHint | Qt::WindowSystemMenuHint); + configuration_form=new ConfigurationForm(nullptr, Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); PgModelerUiNS::resizeDialog(configuration_form); configuration_form->loadConfiguration(); @@ -196,7 +203,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(par connect(action_redo,SIGNAL(triggered(bool)),oper_list_wgt,SLOT(redoOperation(void))); connect(model_nav_wgt, SIGNAL(s_modelCloseRequested(int)), this, SLOT(closeModel(int))); - connect(model_nav_wgt, SIGNAL(s_currentModelChanged(int)), this, SLOT(setCurrentModel())); + connect(model_nav_wgt, SIGNAL(s_currentModelChanged(int)), this, SLOT(setCurrentModel())); connect(action_print, SIGNAL(triggered(bool)), this, SLOT(printModel(void))); connect(action_configuration, SIGNAL(triggered(bool)), configuration_form, SLOT(show())); @@ -220,8 +227,6 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(par connect(model_valid_wgt, &ModelValidationWidget::s_connectionsUpdateRequest, [&](){ updateConnections(true); }); connect(sql_tool_wgt, &SQLToolWidget::s_connectionsUpdateRequest, [&](){ updateConnections(true); }); - connect(action_arrange_objects, SIGNAL(triggered(bool)), this, SLOT(arrangeObjects())); - window_title=this->windowTitle() + QString(" ") + GlobalAttributes::PGMODELER_VERSION; #ifdef DEMO_VERSION @@ -420,7 +425,6 @@ MainWindow::~MainWindow(void) { //This fix the crash on exit at Mac OSX system (but not sure why) (???) file_menu->clear(); - delete(restoration_form); delete(overview_wgt); delete(configuration_form); @@ -834,6 +838,7 @@ void MainWindow::addModel(const QString &filename) obj_name=model_tab->db_model->getName(); models_tbw->blockSignals(true); + models_tbw->setUpdatesEnabled(false); models_tbw->addTab(model_tab, obj_name); models_tbw->setCurrentIndex(models_tbw->count()-1); models_tbw->blockSignals(false); @@ -858,13 +863,15 @@ void MainWindow::addModel(const QString &filename) } catch(Exception &e) { + models_tbw->setUpdatesEnabled(true); central_wgt->update(); + models_tbw->removeTab(models_tbw->indexOf(model_tab)); model_tab->setParent(nullptr); //Destroy the temp file generated by allocating a new model widget restoration_form->removeTemporaryModel(model_tab->getTempFilename()); - delete(model_tab); + //delete(model_tab); updateToolsState(true); throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); @@ -872,20 +879,23 @@ void MainWindow::addModel(const QString &filename) } model_nav_wgt->addModel(model_tab); + models_tbw->setUpdatesEnabled(true); setCurrentModel(); - if(start_timers) + if(start_timers) { - if(model_save_timer.interval() > 0) + if(model_save_timer.interval() > 0) model_save_timer.start(); tmpmodel_save_timer.start(); - } + } model_tab->setModified(false); if(action_alin_objs_grade->isChecked()) current_model->scene->alignObjectsToGrid(); + + models_tbw->update(); } catch(Exception &e) { @@ -956,10 +966,10 @@ void MainWindow::setCurrentModel(void) removeModelActions(); - edit_menu->clear(); - edit_menu->addAction(action_undo); - edit_menu->addAction(action_redo); - edit_menu->addSeparator(); + edit_menu->clear(); + edit_menu->addAction(action_undo); + edit_menu->addAction(action_redo); + edit_menu->addSeparator(); //Avoids the tree state saving in order to restore the current model tree state model_objs_wgt->saveTreeState(false); @@ -968,7 +978,7 @@ void MainWindow::setCurrentModel(void) if(current_model) model_objs_wgt->saveTreeState(model_tree_states[current_model]); - models_tbw->setCurrentIndex(model_nav_wgt->getCurrentIndex()); + models_tbw->setCurrentIndex(model_nav_wgt->getCurrentIndex()); current_model=dynamic_cast(models_tbw->currentWidget()); action_arrange_objects->setEnabled(current_model != nullptr); @@ -980,7 +990,7 @@ void MainWindow::setCurrentModel(void) current_model->setFocus(Qt::OtherFocusReason); current_model->cancelObjectAddition(); - general_tb->addAction(current_model->action_new_object); + general_tb->addAction(current_model->action_new_object); tool_btn=qobject_cast(general_tb->widgetForAction(current_model->action_new_object)); tool_btn->setPopupMode(QToolButton::InstantPopup); btns.push_back(tool_btn); @@ -1016,14 +1026,14 @@ void MainWindow::setCurrentModel(void) { PgModelerUiNS::configureWidgetFont(btn, PgModelerUiNS::SMALL_FONT_FACTOR); btn->setGraphicsEffect(createDropShadow(tool_btn)); - } + } - edit_menu->addAction(current_model->action_copy); - edit_menu->addAction(current_model->action_cut); - edit_menu->addAction(current_model->action_duplicate); - edit_menu->addAction(current_model->action_paste); - edit_menu->addAction(current_model->action_remove); - edit_menu->addAction(current_model->action_cascade_del); + edit_menu->addAction(current_model->action_copy); + edit_menu->addAction(current_model->action_cut); + edit_menu->addAction(current_model->action_duplicate); + edit_menu->addAction(current_model->action_paste); + edit_menu->addAction(current_model->action_remove); + edit_menu->addAction(current_model->action_cascade_del); if(current_model->getFilename().isEmpty()) this->setWindowTitle(window_title); @@ -1080,20 +1090,34 @@ void MainWindow::setCurrentModel(void) void MainWindow::setGridOptions(void) { + GeneralConfigWidget *conf_wgt = dynamic_cast(configuration_form->getConfigurationWidget(ConfigurationForm::GENERAL_CONF_WGT)); + map attribs = conf_wgt->getConfigurationParams(); + //Configures the global settings for the scene grid ObjectsScene::setGridOptions(action_show_grid->isChecked(), action_alin_objs_grade->isChecked(), action_show_delimiters->isChecked()); + attribs[ParsersAttributes::CONFIGURATION][ParsersAttributes::ALIGN_OBJS_TO_GRID] = (action_alin_objs_grade->isChecked() ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); + attribs[ParsersAttributes::CONFIGURATION][ParsersAttributes::SHOW_CANVAS_GRID] = (action_show_grid->isChecked() ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); + attribs[ParsersAttributes::CONFIGURATION][ParsersAttributes::SHOW_PAGE_DELIMITERS] = (action_show_delimiters->isChecked() ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); + if(current_model) { //Align the object to grid is the option is checked if(action_alin_objs_grade->isChecked()) + { current_model->scene->alignObjectsToGrid(); + //Forcing the relationship updating to fit the new position of the tables + current_model->getDatabaseModel()->setObjectsModified({ OBJ_RELATIONSHIP, BASE_RELATIONSHIP }); + } + //Redraw the scene to apply the new grid options current_model->scene->update(); } + + conf_wgt->addConfigurationParam(ParsersAttributes::CONFIGURATION, attribs[ParsersAttributes::CONFIGURATION]); } void MainWindow::applyZoom(void) @@ -1156,6 +1180,7 @@ void MainWindow::closeModel(int model_id) if(!model->isModified() || (model->isModified() && msg_box.result()==QDialog::Accepted)) { + QApplication::setOverrideCursor(Qt::WaitCursor); model_nav_wgt->removeModel(model_id); model_tree_states.erase(model); @@ -1179,6 +1204,7 @@ void MainWindow::closeModel(int model_id) models_tbw->removeTab(models_tbw->currentIndex()); delete(model); + QApplication::restoreOverrideCursor(); } } @@ -1282,8 +1308,8 @@ void MainWindow::saveModel(ModelWidget *model) msg_box.show(trUtf8("Confirmation"), trUtf8(" WARNING: The model %1 is invalidated! It's recommended to validate it before save in order to create a consistent model otherwise the generated file will be broken demanding manual fixes to be loadable again!").arg(db_model->getName()), Messagebox::ALERT_ICON, Messagebox::ALL_BUTTONS, - trUtf8("Save anyway"), trUtf8("Validate"),QString(), - PgModelerUiNS::getIconPath("salvar"), PgModelerUiNS::getIconPath("validation")); + trUtf8("Validate"), trUtf8("Save anyway"), QString(), + PgModelerUiNS::getIconPath("validation"), PgModelerUiNS::getIconPath("salvar")); //If the user cancel the saving force the stopping of autosave timer to give user the chance to validate the model if(msg_box.isCancelled()) @@ -1293,7 +1319,7 @@ void MainWindow::saveModel(ModelWidget *model) //The autosave timer will be reactivated in 5 minutes QTimer::singleShot(300000, &model_save_timer, SLOT(start())); } - else if(msg_box.result()==QDialog::Rejected) + else if(msg_box.result()==QDialog::Accepted) { validation_btn->setChecked(true); this->pending_op=(sender()==action_save_as ? PENDING_SAVE_AS_OPER : PENDING_SAVE_OPER); @@ -1302,8 +1328,11 @@ void MainWindow::saveModel(ModelWidget *model) } } + stopTimers(true); + if((!confirm_validation || - (!db_model->isInvalidated() || (confirm_validation && db_model->isInvalidated() && msg_box.result()==QDialog::Accepted))) + (!db_model->isInvalidated() || + (confirm_validation && db_model->isInvalidated() && !msg_box.isCancelled() && msg_box.result()==QDialog::Rejected))) && (model->isModified() || sender()==action_save_as)) { //If the action that calls the slot were the 'save as' or the model filename isn't set @@ -1332,10 +1361,13 @@ void MainWindow::saveModel(ModelWidget *model) this->setWindowTitle(window_title + QString(" - ") + QDir::toNativeSeparators(model->getFilename())); model_valid_wgt->clearOutput(); } + + stopTimers(false); } } catch(Exception &e) { + stopTimers(false); throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); } #endif @@ -1354,10 +1386,10 @@ void MainWindow::exportModel(void) msg_box.show(trUtf8("Confirmation"), trUtf8(" WARNING: The model %1 is invalidated! Before run the export process it's recommended to validate in order to correctly create the objects on database server!").arg(db_model->getName()), Messagebox::ALERT_ICON, Messagebox::ALL_BUTTONS, - trUtf8("Export anyway"), trUtf8("Validate"), QString(), - PgModelerUiNS::getIconPath("exportar"), PgModelerUiNS::getIconPath("validation")); + trUtf8("Validate"), trUtf8("Export anyway"), QString(), + PgModelerUiNS::getIconPath("validation"), PgModelerUiNS::getIconPath("exportar")); - if(!msg_box.isCancelled() && msg_box.result()==QDialog::Rejected) + if(msg_box.result()==QDialog::Accepted) { validation_btn->setChecked(true); this->pending_op=PENDING_EXPORT_OPER; @@ -1366,7 +1398,7 @@ void MainWindow::exportModel(void) } if(!confirm_validation || - (!db_model->isInvalidated() || (confirm_validation && msg_box.result()==QDialog::Accepted))) + (!db_model->isInvalidated() || (confirm_validation && !msg_box.isCancelled() && msg_box.result()==QDialog::Rejected))) { stopTimers(true); connect(&model_export_form, &ModelExportForm::s_connectionsUpdateRequest, [&](){ updateConnections(true); }); @@ -1398,19 +1430,20 @@ void MainWindow::diffModelDatabase(void) { ModelDatabaseDiffForm modeldb_diff_frm(nullptr, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); Messagebox msg_box; - DatabaseModel *db_model=current_model->getDatabaseModel(); + DatabaseModel *db_model=(current_model ? current_model->getDatabaseModel() : nullptr); - action_design->setChecked(true); + if(current_model) + action_design->setChecked(true); - if(confirm_validation && db_model->isInvalidated()) + if(confirm_validation && db_model && db_model->isInvalidated()) { msg_box.show(trUtf8("Confirmation"), trUtf8(" WARNING: The model %1 is invalidated! Before run the diff process it's recommended to validate in order to correctly analyze and generate the difference between the model and a database!").arg(db_model->getName()), Messagebox::ALERT_ICON, Messagebox::ALL_BUTTONS, - trUtf8("Diff anyway"), trUtf8("Validate"), QString(), - PgModelerUiNS::getIconPath("diff"), PgModelerUiNS::getIconPath("validation")); + trUtf8("Validate"), trUtf8("Diff anyway"), QString(), + PgModelerUiNS::getIconPath("validation"), PgModelerUiNS::getIconPath("diff")); - if(!msg_box.isCancelled() && msg_box.result()==QDialog::Rejected) + if(msg_box.result()==QDialog::Accepted) { validation_btn->setChecked(true); this->pending_op=PENDING_DIFF_OPER; @@ -1418,10 +1451,10 @@ void MainWindow::diffModelDatabase(void) } } - if(!confirm_validation || - (!db_model->isInvalidated() || (confirm_validation && msg_box.result()==QDialog::Accepted))) + if(!confirm_validation || !db_model || + ((db_model && !db_model->isInvalidated()) || (confirm_validation && !msg_box.isCancelled() && msg_box.result()==QDialog::Rejected))) { - modeldb_diff_frm.setDatabaseModel(db_model); + modeldb_diff_frm.setModelWidget(current_model); stopTimers(true); connect(&modeldb_diff_frm, &ModelDatabaseDiffForm::s_connectionsUpdateRequest, [&](){ updateConnections(true); }); @@ -1569,7 +1602,7 @@ void MainWindow::updateToolsState(bool model_closed) action_save_model->setEnabled(enabled); action_save_all->setEnabled(enabled); action_export->setEnabled(enabled); - action_diff->setEnabled(enabled); + //action_diff->setEnabled(enabled); action_close_model->setEnabled(enabled); action_show_grid->setEnabled(enabled); action_show_delimiters->setEnabled(enabled); @@ -1748,7 +1781,8 @@ void MainWindow::storeDockWidgetsSettings(void) params.clear(); params[ParsersAttributes::OBJECT_FINDER]=ParsersAttributes::_TRUE_; - params[ParsersAttributes::HIGHLIGHT_OBJECTS]=(obj_finder_wgt->highlight_btn->isChecked() ? ParsersAttributes::_TRUE_ : QString()); + params[ParsersAttributes::SELECT_OBJECTS]=(obj_finder_wgt->select_btn->isChecked() ? ParsersAttributes::_TRUE_ : QString()); + params[ParsersAttributes::FADEIN_OBJECTS]=(obj_finder_wgt->fade_btn->isChecked() ? ParsersAttributes::_TRUE_ : QString()); params[ParsersAttributes::REGULAR_EXP]=(obj_finder_wgt->regexp_chk->isChecked() ? ParsersAttributes::_TRUE_ : QString()); params[ParsersAttributes::CASE_SENSITIVE]=(obj_finder_wgt->case_sensitive_chk->isChecked() ? ParsersAttributes::_TRUE_ : QString()); params[ParsersAttributes::EXACT_MATCH]=(obj_finder_wgt->exact_match_chk->isChecked() ? ParsersAttributes::_TRUE_ : QString()); @@ -1776,7 +1810,8 @@ void MainWindow::restoreDockWidgetsSettings(void) if(confs.count(ParsersAttributes::OBJECT_FINDER)) { - obj_finder_wgt->highlight_btn->setChecked(confs[ParsersAttributes::OBJECT_FINDER][ParsersAttributes::HIGHLIGHT_OBJECTS]==ParsersAttributes::_TRUE_); + obj_finder_wgt->select_btn->setChecked(confs[ParsersAttributes::OBJECT_FINDER][ParsersAttributes::SELECT_OBJECTS]==ParsersAttributes::_TRUE_); + obj_finder_wgt->fade_btn->setChecked(confs[ParsersAttributes::OBJECT_FINDER][ParsersAttributes::FADEIN_OBJECTS]==ParsersAttributes::_TRUE_); obj_finder_wgt->regexp_chk->setChecked(confs[ParsersAttributes::OBJECT_FINDER][ParsersAttributes::REGULAR_EXP]==ParsersAttributes::_TRUE_); obj_finder_wgt->case_sensitive_chk->setChecked(confs[ParsersAttributes::OBJECT_FINDER][ParsersAttributes::CASE_SENSITIVE]==ParsersAttributes::_TRUE_); obj_finder_wgt->exact_match_chk->setChecked(confs[ParsersAttributes::OBJECT_FINDER][ParsersAttributes::EXACT_MATCH]==ParsersAttributes::_TRUE_); @@ -1849,8 +1884,16 @@ void MainWindow::changeCurrentView(bool checked) actions=general_tb->actions(); for(int i=GENERAL_ACTIONS_COUNT; i < actions.count(); i++) + { actions[i]->setEnabled(enable); + if(actions[i]->menu()) + { + for(auto action : actions[i]->menu()->actions()) + action->setEnabled(enable); + } + } + if(!enable) overview_wgt->close(); @@ -1910,5 +1953,16 @@ void MainWindow::arrangeObjects(void) msgbox.show(trUtf8("Rearrange objects over the canvas is an irreversible operation! Would like to proceed?"), Messagebox::CONFIRM_ICON, Messagebox::YES_NO_BUTTONS); if(msgbox.result() == QDialog::Accepted) - current_model->rearrangeObjects(); + { + QApplication::setOverrideCursor(Qt::WaitCursor); + + if(sender() == arrange_menu.actions().at(0)) + current_model->rearrangeSchemasInGrid(); + else if(sender() == arrange_menu.actions().at(1)) + current_model->rearrangeTablesHierarchically(); + else + current_model->rearrangeTablesInSchemas(); + + QApplication::restoreOverrideCursor(); + } } diff --git a/libpgmodeler_ui/src/mainwindow.h b/libpgmodeler_ui/src/mainwindow.h index 8b9de3be2..6acf2f6de 100644 --- a/libpgmodeler_ui/src/mainwindow.h +++ b/libpgmodeler_ui/src/mainwindow.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -141,7 +141,9 @@ class MainWindow: public QMainWindow, public Ui::MainWindow { main_menu, - sample_mdls_menu; + sample_mdls_menu, + + arrange_menu; //! \brief QMainWindow::closeEvent() overload: Saves the configurations before close the application void closeEvent(QCloseEvent *event); diff --git a/libpgmodeler_ui/src/messagebox.cpp b/libpgmodeler_ui/src/messagebox.cpp index 3e53f1003..4120492e6 100644 --- a/libpgmodeler_ui/src/messagebox.cpp +++ b/libpgmodeler_ui/src/messagebox.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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 2fc6fd1da..69228e1c3 100644 --- a/libpgmodeler_ui/src/messagebox.h +++ b/libpgmodeler_ui/src/messagebox.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/metadatahandlingform.cpp b/libpgmodeler_ui/src/metadatahandlingform.cpp index c9df35df8..2bb8f8f70 100644 --- a/libpgmodeler_ui/src/metadatahandlingform.cpp +++ b/libpgmodeler_ui/src/metadatahandlingform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/metadatahandlingform.h b/libpgmodeler_ui/src/metadatahandlingform.h index 47f40cd67..32a6e17f6 100644 --- a/libpgmodeler_ui/src/metadatahandlingform.h +++ b/libpgmodeler_ui/src/metadatahandlingform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modeldatabasediffform.cpp b/libpgmodeler_ui/src/modeldatabasediffform.cpp index 8f99cd8be..fa395531a 100644 --- a/libpgmodeler_ui/src/modeldatabasediffform.cpp +++ b/libpgmodeler_ui/src/modeldatabasediffform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -32,15 +32,15 @@ ModelDatabaseDiffForm::ModelDatabaseDiffForm(QWidget *parent, Qt::WindowFlags f) htmlitem_del=new HtmlItemDelegate(this); output_trw->setItemDelegateForColumn(0, htmlitem_del); - imported_model=nullptr; - import_helper=nullptr; + imported_model=loaded_model=source_model=nullptr; + src_import_helper=import_helper=nullptr; diff_helper=nullptr; export_helper=nullptr; - import_thread=diff_thread=export_thread=nullptr; - import_item=diff_item=export_item=nullptr; + src_import_thread=import_thread=diff_thread=export_thread=nullptr; + src_import_item=import_item=diff_item=export_item=nullptr; export_conn=nullptr; process_paused=false; - diff_progress=0; + diff_progress=curr_step=total_steps=0; apply_on_server_ht=new HintTextWidget(apply_on_server_hint, this); apply_on_server_ht->setText(apply_on_server_rb->statusTip()); @@ -88,8 +88,11 @@ ModelDatabaseDiffForm::ModelDatabaseDiffForm(QWidget *parent, Qt::WindowFlags f) preserve_db_name_ht=new HintTextWidget(preserve_db_name_hint, this); preserve_db_name_ht->setText(preserve_db_name_chk->statusTip()); - keep_not_imported_objs_ht=new HintTextWidget(keep_not_imported_objs_hint, this); - keep_not_imported_objs_ht->setText(keep_not_imported_objs_chk->statusTip()); + dont_drop_missing_objs_ht=new HintTextWidget(dont_drop_missing_objs_hint, this); + dont_drop_missing_objs_ht->setText(dont_drop_missing_objs_chk->statusTip()); + + drop_missing_cols_constr_ht=new HintTextWidget(drop_missing_cols_constr_hint, this); + drop_missing_cols_constr_ht->setText(drop_missing_cols_constr_chk->statusTip()); ignore_error_codes_ht=new HintTextWidget(ignore_extra_errors_hint, this); ignore_error_codes_ht->setText(ignore_error_codes_chk->statusTip()); @@ -114,11 +117,18 @@ ModelDatabaseDiffForm::ModelDatabaseDiffForm(QWidget *parent, Qt::WindowFlags f) connect(select_file_tb, SIGNAL(clicked()), this, SLOT(selectOutputFile())); connect(file_edt, SIGNAL(textChanged(QString)), this, SLOT(enableDiffMode())); connect(force_recreation_chk, SIGNAL(toggled(bool)), recreate_unmod_chk, SLOT(setEnabled(bool))); + connect(dont_drop_missing_objs_chk, SIGNAL(toggled(bool)), drop_missing_cols_constr_chk, SLOT(setEnabled(bool))); connect(create_tb, SIGNAL(toggled(bool)), this, SLOT(filterDiffInfos())); connect(drop_tb, SIGNAL(toggled(bool)), this, SLOT(filterDiffInfos())); connect(alter_tb, SIGNAL(toggled(bool)), this, SLOT(filterDiffInfos())); connect(ignore_tb, SIGNAL(toggled(bool)), this, SLOT(filterDiffInfos())); connect(ignore_error_codes_chk, SIGNAL(toggled(bool)), error_codes_edt, SLOT(setEnabled(bool))); + connect(src_database_rb, SIGNAL(toggled(bool)), src_database_wgt, SLOT(setEnabled(bool))); + connect(src_model_rb, SIGNAL(toggled(bool)), src_model_name_lbl, SLOT(setEnabled(bool))); + connect(src_connections_cmb, SIGNAL(activated(int)), this, SLOT(listDatabases())); + connect(src_database_cmb, SIGNAL(currentIndexChanged(int)), this, SLOT(enableDiffMode())); + connect(src_model_rb, SIGNAL(toggled(bool)), this, SLOT(enableDiffMode())); + connect(src_database_rb, SIGNAL(toggled(bool)), this, SLOT(enableDiffMode())); #ifdef DEMO_VERSION #warning "DEMO VERSION: forcing ignore errors in diff due to the object count limit." @@ -146,16 +156,33 @@ ModelDatabaseDiffForm::~ModelDatabaseDiffForm(void) destroyModel(); } -void ModelDatabaseDiffForm::setDatabaseModel(DatabaseModel *model) +void ModelDatabaseDiffForm::setModelWidget(ModelWidget *model_wgt) { - source_model=model; + if(model_wgt) + { + source_model=loaded_model=model_wgt->getDatabaseModel(); + src_model_name_lbl->setText(QString("%1 [%2]").arg(source_model->getName()).arg(QFileInfo(model_wgt->getFilename()).fileName())); + src_model_name_lbl->setToolTip(model_wgt->getFilename().isEmpty() ? trUtf8("model not saved yet") : model_wgt->getFilename()); + } + else + { + src_model_name_lbl->setText(trUtf8("(none)")); + src_model_name_lbl->setToolTip(""); + src_database_rb->setChecked(true); + src_model_rb->setEnabled(false); + } } void ModelDatabaseDiffForm::resetForm(void) { + ConnectionsConfigWidget::fillConnectionsComboBox(src_connections_cmb, true); + src_connections_cmb->setEnabled(src_connections_cmb->count() > 0); + src_connection_lbl->setEnabled(src_connections_cmb->isEnabled()); + ConnectionsConfigWidget::fillConnectionsComboBox(connections_cmb, true, Connection::OP_DIFF); connections_cmb->setEnabled(connections_cmb->count() > 0); connection_lbl->setEnabled(connections_cmb->isEnabled()); + enableDiffMode(); settings_tbw->setTabEnabled(1, false); settings_tbw->setTabEnabled(2, false); @@ -181,7 +208,20 @@ void ModelDatabaseDiffForm::showEvent(QShowEvent *) void ModelDatabaseDiffForm::createThread(unsigned thread_id) { - if(thread_id==IMPORT_THREAD) + if(thread_id==SRC_IMPORT_THREAD) + { + src_import_thread=new QThread; + src_import_helper=new DatabaseImportHelper; + src_import_helper->moveToThread(src_import_thread); + + output_trw->setUniformRowHeights(true); + + connect(src_import_thread, SIGNAL(started(void)), src_import_helper, SLOT(importDatabase())); + connect(src_import_helper, SIGNAL(s_progressUpdated(int,QString,ObjectType)), this, SLOT(updateProgress(int,QString,ObjectType)), Qt::BlockingQueuedConnection); + connect(src_import_helper, SIGNAL(s_importFinished(Exception)), this, SLOT(handleImportFinished(Exception))); + connect(src_import_helper, SIGNAL(s_importAborted(Exception)), this, SLOT(captureThreadError(Exception))); + } + else if(thread_id==IMPORT_THREAD) { import_thread=new QThread; import_helper=new DatabaseImportHelper; @@ -235,7 +275,14 @@ void ModelDatabaseDiffForm::createThread(unsigned thread_id) void ModelDatabaseDiffForm::destroyThread(unsigned thread_id) { - if(thread_id==IMPORT_THREAD && import_thread) + if(thread_id==SRC_IMPORT_THREAD && src_import_thread) + { + delete(src_import_thread); + delete(src_import_helper); + src_import_thread=nullptr; + src_import_helper=nullptr; + } + else if(thread_id==IMPORT_THREAD && import_thread) { delete(import_thread); delete(import_helper); @@ -269,13 +316,19 @@ void ModelDatabaseDiffForm::destroyModel(void) if(imported_model) delete(imported_model); + if(source_model && source_model != loaded_model && src_database_rb->isChecked()) + { + delete(source_model); + source_model = nullptr; + } + imported_model=nullptr; } void ModelDatabaseDiffForm::clearOutput(void) { output_trw->clear(); - import_item=diff_item=export_item=nullptr; + src_import_item=import_item=diff_item=export_item=nullptr; step_lbl->setText(trUtf8("Waiting process to start...")); step_ico_lbl->setPixmap(QPixmap()); @@ -293,33 +346,38 @@ void ModelDatabaseDiffForm::clearOutput(void) void ModelDatabaseDiffForm::listDatabases(void) { + QComboBox *conn_cmb = (sender() == src_connections_cmb ? src_connections_cmb : connections_cmb), + *db_cmb = (conn_cmb == src_connections_cmb ? src_database_cmb : database_cmb); + QLabel *db_lbl = (conn_cmb == src_connections_cmb ? src_database_lbl : database_lbl); + try { - if(connections_cmb->currentIndex()==connections_cmb->count()-1 && - ConnectionsConfigWidget::openConnectionsConfiguration(connections_cmb, true)) + if(conn_cmb->currentIndex()==conn_cmb->count()-1 && + ConnectionsConfigWidget::openConnectionsConfiguration(conn_cmb, true)) { emit s_connectionsUpdateRequest(); + resetForm(); } - Connection *conn=reinterpret_cast(connections_cmb->itemData(connections_cmb->currentIndex()).value()); + Connection *conn=reinterpret_cast(conn_cmb->itemData(conn_cmb->currentIndex()).value()); if(conn) { DatabaseImportHelper imp_helper; imp_helper.setConnection(*conn); - DatabaseImportForm::listDatabases(imp_helper, database_cmb); + DatabaseImportForm::listDatabases(imp_helper, db_cmb); } else - database_cmb->clear(); + db_cmb->clear(); - database_cmb->setEnabled(database_cmb->count() > 0); - database_lbl->setEnabled(database_cmb->isEnabled()); + db_cmb->setEnabled(db_cmb->count() > 0); + db_lbl->setEnabled(db_cmb->isEnabled()); } catch(Exception &e) { - database_cmb->clear(); - database_cmb->setEnabled(false); - database_lbl->setEnabled(false); + db_cmb->clear(); + db_cmb->setEnabled(false); + db_lbl->setEnabled(false); throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); } } @@ -329,20 +387,33 @@ void ModelDatabaseDiffForm::enableDiffMode(void) store_in_file_wgt->setEnabled(store_in_file_rb->isChecked()); generate_btn->setEnabled(database_cmb->currentIndex() > 0 && - ((store_in_file_rb->isChecked() && !file_edt->text().isEmpty()) || - (apply_on_server_rb->isChecked()))); + ((src_database_rb->isChecked() && src_database_cmb->currentIndex() > 0) || + (src_model_rb->isChecked() && loaded_model)) && + ((store_in_file_rb->isChecked() && !file_edt->text().isEmpty()) || + (apply_on_server_rb->isChecked()))); } void ModelDatabaseDiffForm::generateDiff(void) { //Destroy previously allocated threads and helper before start over. destroyModel(); + destroyThread(SRC_IMPORT_THREAD); destroyThread(IMPORT_THREAD); destroyThread(DIFF_THREAD); destroyThread(EXPORT_THREAD); clearOutput(); - importDatabase(); + curr_step = 1; + + if(src_model_rb->isChecked()) + { + source_model = loaded_model; + total_steps=3; + } + else + total_steps=4; + + importDatabase(src_database_rb->isChecked() ? SRC_IMPORT_THREAD : IMPORT_THREAD); buttons_wgt->setEnabled(false); cancel_btn->setEnabled(true); @@ -354,24 +425,39 @@ void ModelDatabaseDiffForm::generateDiff(void) settings_tbw->setCurrentIndex(1); } -void ModelDatabaseDiffForm::importDatabase(void) +void ModelDatabaseDiffForm::importDatabase(unsigned thread_id) { try { - createThread(IMPORT_THREAD); + if(thread_id != SRC_IMPORT_THREAD && thread_id != IMPORT_THREAD) + throw Exception(ERR_ALOC_OBJECT_INV_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + createThread(thread_id); - Connection conn=(*reinterpret_cast(connections_cmb->itemData(connections_cmb->currentIndex()).value())), conn1; + QThread *thread = (thread_id == SRC_IMPORT_THREAD ? src_import_thread : import_thread); + DatabaseImportHelper *import_hlp = (thread_id == SRC_IMPORT_THREAD ? src_import_helper : import_helper); + QComboBox *conn_cmb = (thread_id == SRC_IMPORT_THREAD ? src_connections_cmb : connections_cmb), + *db_cmb = (thread_id == SRC_IMPORT_THREAD ? src_database_cmb : database_cmb); + Connection conn=(*reinterpret_cast(conn_cmb->itemData(conn_cmb->currentIndex()).value())), conn1; map> obj_oids; map> col_oids; Catalog catalog; + DatabaseModel *db_model = nullptr; conn1=conn; - step_lbl->setText(trUtf8("Importing database %1...").arg(database_cmb->currentText())); + step_lbl->setText(trUtf8("Step %1/%2: Importing database %3...") + .arg(curr_step) + .arg(total_steps) + .arg(db_cmb->currentText())); + step_ico_lbl->setPixmap(QPixmap(PgModelerUiNS::getIconPath("import"))); - import_item=PgModelerUiNS::createOutputTreeItem(output_trw, step_lbl->text(), *step_ico_lbl->pixmap(), nullptr); + if(thread_id == SRC_IMPORT_THREAD) + src_import_item=PgModelerUiNS::createOutputTreeItem(output_trw, step_lbl->text(), *step_ico_lbl->pixmap(), nullptr); + else + import_item=PgModelerUiNS::createOutputTreeItem(output_trw, step_lbl->text(), *step_ico_lbl->pixmap(), nullptr); - conn.switchToDatabase(database_cmb->currentText()); + conn.switchToDatabase(db_cmb->currentText()); pgsql_ver=conn.getPgSQLVersion(true); catalog.setConnection(conn); @@ -380,18 +466,27 @@ void ModelDatabaseDiffForm::importDatabase(void) catalog.setFilter(Catalog::LIST_ALL_OBJS | Catalog::EXCL_BUILTIN_ARRAY_TYPES | Catalog::EXCL_EXTENSION_OBJS | Catalog::EXCL_SYSTEM_OBJS); catalog.getObjectsOIDs(obj_oids, col_oids, {{ParsersAttributes::FILTER_TABLE_TYPES, ParsersAttributes::_TRUE_}}); - obj_oids[OBJ_DATABASE].push_back(database_cmb->currentData().value()); + obj_oids[OBJ_DATABASE].push_back(db_cmb->currentData().value()); - imported_model=new DatabaseModel; - imported_model->createSystemObjects(true); + if(thread_id == SRC_IMPORT_THREAD) + { + source_model=new DatabaseModel; + source_model->createSystemObjects(true); + db_model = source_model; + } + else + { + imported_model=new DatabaseModel; + imported_model->createSystemObjects(true); + db_model = imported_model; + } - import_helper->setConnection(conn1); - import_helper->setSelectedOIDs(imported_model, obj_oids, col_oids); - import_helper->setCurrentDatabase(database_cmb->currentText()); - import_helper->setImportOptions(import_sys_objs_chk->isChecked(), import_ext_objs_chk->isChecked(), true, + import_hlp->setConnection(conn1); + import_hlp->setSelectedOIDs(db_model, obj_oids, col_oids); + import_hlp->setCurrentDatabase(db_cmb->currentText()); + import_hlp->setImportOptions(import_sys_objs_chk->isChecked(), import_ext_objs_chk->isChecked(), true, ignore_errors_chk->isChecked(), false, false, false); - - import_thread->start(); + thread->start(); } catch(Exception &e) { @@ -403,7 +498,9 @@ void ModelDatabaseDiffForm::diffModels(void) { createThread(DIFF_THREAD); - step_lbl->setText(trUtf8("Comparing the model %1 and database %2...") + step_lbl->setText(trUtf8("Step %1/%2: Comparing %3 and %4...") + .arg(curr_step) + .arg(total_steps) .arg(source_model->getName()) .arg(imported_model->getName())); step_ico_lbl->setPixmap(QPixmap(PgModelerUiNS::getIconPath("diff"))); @@ -421,7 +518,8 @@ void ModelDatabaseDiffForm::diffModels(void) diff_helper->setDiffOption(ModelsDiffHelper::OPT_KEEP_OBJ_PERMS, keep_obj_perms_chk->isChecked()); diff_helper->setDiffOption(ModelsDiffHelper::OPT_REUSE_SEQUENCES, reuse_sequences_chk->isChecked()); diff_helper->setDiffOption(ModelsDiffHelper::OPT_PRESERVE_DB_NAME, preserve_db_name_chk->isChecked()); - diff_helper->setDiffOption(ModelsDiffHelper::OPT_KEEP_NOT_IMPORTED_OBJS, keep_not_imported_objs_chk->isChecked()); + diff_helper->setDiffOption(ModelsDiffHelper::OPT_DONT_DROP_MISSING_OBJS, dont_drop_missing_objs_chk->isChecked()); + diff_helper->setDiffOption(ModelsDiffHelper::OPT_DROP_MISSING_COLS_CONSTR, drop_missing_cols_constr_chk->isChecked()); diff_helper->setModels(source_model, imported_model); @@ -451,8 +549,10 @@ void ModelDatabaseDiffForm::exportDiff(bool confirm) settings_tbw->setCurrentIndex(1); apply_on_server_btn->setEnabled(true); - step_lbl->setText(trUtf8("Exporting diff to database %1...") - .arg(imported_model->getName())); + step_lbl->setText(trUtf8("Step %1/%2: Exporting diff to database %3...") + .arg(curr_step) + .arg(total_steps) + .arg(imported_model->getName())); step_ico_lbl->setPixmap(QPixmap(PgModelerUiNS::getIconPath("exportar"))); output_trw->collapseItem(diff_item); @@ -559,6 +659,12 @@ void ModelDatabaseDiffForm::cancelOperation(bool cancel_by_user) PgModelerUiNS::createOutputTreeItem(output_trw, step_lbl->text(), *step_ico_lbl->pixmap(), nullptr); } + if(src_import_helper && src_import_thread->isRunning()) + { + src_import_helper->cancelImport(); + src_import_thread->quit(); + } + if(import_helper && import_thread->isRunning()) { import_helper->cancelImport(); @@ -603,13 +709,24 @@ void ModelDatabaseDiffForm::handleImportFinished(Exception e) msgbox.show(e, e.getErrorMessage(), Messagebox::ALERT_ICON); } - import_thread->quit(); - step_pb->setValue(30); - diffModels(); + curr_step++; + + if(src_import_thread && src_import_thread->isRunning()) + { + src_import_thread->quit(); + src_import_item->setExpanded(false); + importDatabase(IMPORT_THREAD); + } + else + { + import_thread->quit(); + diffModels(); + } } void ModelDatabaseDiffForm::handleDiffFinished(void) { + curr_step++; sqlcode_txt->setPlainText(diff_helper->getDiffDefinition()); #ifdef DEMO_VERSION @@ -664,12 +781,25 @@ void ModelDatabaseDiffForm::handleErrorIgnored(QString err_code, QString err_msg void ModelDatabaseDiffForm::updateProgress(int progress, QString msg, ObjectType obj_type, QString cmd) { + int progress_aux = 0; + msg=PgModelerUiNS::formatMessage(msg); - if(import_thread && import_thread->isRunning()) + + if(src_import_thread && src_import_thread->isRunning()) + { + progress_aux = progress/5; + + PgModelerUiNS::createOutputTreeItem(output_trw, msg, + QPixmap(PgModelerUiNS::getIconPath(obj_type)), + src_import_item); + } + else if(import_thread && import_thread->isRunning()) { - if(progress > 90) - step_pb->setValue(step_pb->value() + 5); + if(src_model_rb->isChecked()) + progress_aux = progress/4; + else + progress_aux = 20 + (progress/5); PgModelerUiNS::createOutputTreeItem(output_trw, msg, QPixmap(PgModelerUiNS::getIconPath(obj_type)), @@ -684,13 +814,14 @@ void ModelDatabaseDiffForm::updateProgress(int progress, QString msg, ObjectType diff_item); } - step_pb->setValue(diff_progress + (progress/3)); + progress_aux = diff_progress + (progress/3); } else if(export_thread && export_thread->isRunning()) { QTreeWidgetItem *item=nullptr; QPixmap ico; - step_pb->setValue(diff_progress + (progress/3)); + + progress_aux = diff_progress + (progress/3); if(obj_type==BASE_OBJECT) ico=QPixmap(PgModelerUiNS::getIconPath("codigosql")); @@ -703,6 +834,9 @@ void ModelDatabaseDiffForm::updateProgress(int progress, QString msg, ObjectType PgModelerUiNS::createOutputTreeItem(output_trw, cmd, QPixmap(), item, false); } + if(progress_aux > step_pb->value()) + step_pb->setValue(progress_aux); + progress_lbl->setText(msg); progress_pb->setValue(progress); @@ -745,7 +879,9 @@ void ModelDatabaseDiffForm::selectOutputFile(void) file_dlg.setAcceptMode(QFileDialog::AcceptSave); file_dlg.setModal(true); file_dlg.setNameFilter(trUtf8("SQL code (*.sql);;All files (*.*)")); - file_dlg.selectFile(source_model->getName() + QString("-diff.sql")); + + if(source_model) + file_dlg.selectFile(source_model->getName() + QString("-diff.sql")); if(file_dlg.exec()==QFileDialog::Accepted) { @@ -757,4 +893,3 @@ void ModelDatabaseDiffForm::selectOutputFile(void) file_edt->setText(file); } } - diff --git a/libpgmodeler_ui/src/modeldatabasediffform.h b/libpgmodeler_ui/src/modeldatabasediffform.h index bb12a70dc..0094bad29 100644 --- a/libpgmodeler_ui/src/modeldatabasediffform.h +++ b/libpgmodeler_ui/src/modeldatabasediffform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -50,8 +50,8 @@ class ModelDatabaseDiffForm: public QDialog, public Ui::ModelDatabaseDiffForm { *trunc_tables_ht, *ignore_errors_ht, *force_recreation_ht, *cascade_mode_ht, *pgsql_ver_ht, *recreate_unmod_ht, *keep_obj_perms_ht, *ignore_duplic_ht, *reuse_sequences_ht, - *preserve_db_name_ht, *keep_not_imported_objs_ht, - *ignore_error_codes_ht; + *preserve_db_name_ht, *dont_drop_missing_objs_ht, + *ignore_error_codes_ht, *drop_missing_cols_constr_ht; //! \brief Syntax highlighter used on the diff preview tab SyntaxHighlighter *sqlcode_hl; @@ -60,20 +60,24 @@ class ModelDatabaseDiffForm: public QDialog, public Ui::ModelDatabaseDiffForm { ModelsDiffHelper *diff_helper; //! \brief Helper that will execute the database import - DatabaseImportHelper *import_helper; + DatabaseImportHelper *import_helper, *src_import_helper; //! \brief Helper that will execute the diff export to database ModelExportHelper *export_helper; //! \brief Threads that will execute each step: import, diff, export - QThread *import_thread, *diff_thread, *export_thread; + QThread *import_thread, *diff_thread, *export_thread, *src_import_thread; //! \brief Tree items generated in each diff step - QTreeWidgetItem *import_item, *diff_item, *export_item; + QTreeWidgetItem *import_item, *diff_item, *export_item, *src_import_item; - //! \brief This is the model loaded from file + /*! \brief This is the model used in the diff process representing the source. + * It can be the modelo loaded from file or a representation of the source database (when comparing two dbs) */ DatabaseModel *source_model, + //! \brief This is the model loaded from file + *loaded_model, + //! \brief This is the model generated by the reverse engineering step *imported_model; @@ -83,7 +87,7 @@ class ModelDatabaseDiffForm: public QDialog, public Ui::ModelDatabaseDiffForm { //! \brief PostgreSQL version used by the diff process QString pgsql_ver; - int diff_progress; + int diff_progress, curr_step, total_steps; bool process_paused; @@ -106,14 +110,16 @@ class ModelDatabaseDiffForm: public QDialog, public Ui::ModelDatabaseDiffForm { void finishDiff(void); //! \brief Constants used to reference the thread/helper to be handled in createThread() and destroyThread() - static const unsigned IMPORT_THREAD=0, - DIFF_THREAD=1, - EXPORT_THREAD=2; + static const unsigned SRC_IMPORT_THREAD=0, + IMPORT_THREAD=1, + DIFF_THREAD=2, + EXPORT_THREAD=3; public: ModelDatabaseDiffForm(QWidget * parent = 0, Qt::WindowFlags f = 0); ~ModelDatabaseDiffForm(void); - void setDatabaseModel(DatabaseModel *model); + + void setModelWidget(ModelWidget *model_wgt); private slots: void listDatabases(void); @@ -128,7 +134,7 @@ class ModelDatabaseDiffForm: public QDialog, public Ui::ModelDatabaseDiffForm { void handleExportFinished(void); void handleErrorIgnored(QString err_code, QString err_msg, QString cmd); void selectOutputFile(void); - void importDatabase(void); + void importDatabase(unsigned thread_id); void diffModels(void); void exportDiff(bool confirm=true); void filterDiffInfos(void); diff --git a/libpgmodeler_ui/src/modelexportform.cpp b/libpgmodeler_ui/src/modelexportform.cpp index 3f79972ac..1442cc6b0 100644 --- a/libpgmodeler_ui/src/modelexportform.cpp +++ b/libpgmodeler_ui/src/modelexportform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelexportform.h b/libpgmodeler_ui/src/modelexportform.h index 2ea1aae34..ecc520605 100644 --- a/libpgmodeler_ui/src/modelexportform.h +++ b/libpgmodeler_ui/src/modelexportform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelexporthelper.cpp b/libpgmodeler_ui/src/modelexporthelper.cpp index 828f0b7d2..6953a39db 100644 --- a/libpgmodeler_ui/src/modelexporthelper.cpp +++ b/libpgmodeler_ui/src/modelexporthelper.cpp @@ -247,7 +247,7 @@ void ModelExportHelper::exportToSVG(ObjectsScene *scene, const QString &filename bool shw_dlm=false, shw_grd=false, align_objs=false; QSvgGenerator svg_gen; - QRectF scene_rect=scene->itemsBoundingRect(); + QRectF scene_rect=scene->itemsBoundingRect(true); QFileInfo fi(filename); //Making a backup of the current scene options @@ -261,8 +261,6 @@ void ModelExportHelper::exportToSVG(ObjectsScene *scene, const QString &filename emit s_progressUpdated(0, trUtf8("Exporting model to SVG file.")); svg_gen.setFileName(filename); - svg_gen.setSize(scene_rect.size().toSize()); - svg_gen.setViewBox(scene_rect.toRect()); svg_gen.setTitle(trUtf8("SVG representation of database model")); svg_gen.setDescription(trUtf8("SVG file generated by pgModeler")); @@ -312,12 +310,14 @@ void ModelExportHelper::exportToSVG(ObjectsScene *scene, const QString &filename void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, Connection conn, const QString &pgsql_ver, bool ignore_dup, bool drop_db, bool drop_objs, bool simulate, bool use_tmp_names) { - int type_id; - QString version, sql_cmd, buf; + int type_id = 0, pos = -1; + QString version, sql_cmd, buf, sql_cmd_comment; Connection new_db_conn; unsigned i, count; ObjectType types[]={OBJ_ROLE, OBJ_TABLESPACE}; BaseObject *object=nullptr; + QString tmpl_comm_regexp = QString("(COMMENT)( )+(ON)( )+(%1)(.)+(\n)(") + ParsersAttributes::DDL_END_TOKEN + QString(")"); + QRegExp comm_regexp; try { @@ -428,7 +428,26 @@ void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, Connection conn, c object->getObjectType()); sql_cmd=object->getCodeDefinition(SchemaParser::SQL_DEFINITION); + + if(types[type_id] == OBJ_TABLESPACE) + { + comm_regexp = QRegExp(tmpl_comm_regexp.arg(object->getSQLName())); + pos = comm_regexp.indexIn(sql_cmd); + + /* If we find a comment on statement we should strip it from the tablespace definition in + * order to execute it after creating the db */ + if(pos >= 0) + { + sql_cmd_comment = sql_cmd.mid(pos, comm_regexp.matchedLength()); + sql_cmd.remove(pos, comm_regexp.matchedLength()); + pos = -1; + } + } + conn.executeDDLCommand(sql_cmd); + + if(!sql_cmd_comment.isEmpty()) + conn.executeDDLCommand(sql_cmd_comment); } } catch(Exception &e) @@ -444,6 +463,8 @@ void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, Connection conn, c { if(!db_model->isSQLDisabled() && !export_canceled) { + comm_regexp = QRegExp(tmpl_comm_regexp.arg(db_model->getSQLName())); + //Creating the database on the DBMS emit s_progressUpdated(progress, trUtf8("Creating database `%1'") @@ -451,8 +472,21 @@ void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, Connection conn, c OBJ_DATABASE); sql_cmd=db_model->__getCodeDefinition(SchemaParser::SQL_DEFINITION); + pos = comm_regexp.indexIn(sql_cmd); + + /* If we find a comment on statment we should strip it from the DB definition in + * order to execute it after creating the db */ + if(pos >= 0) + { + sql_cmd_comment = sql_cmd.mid(pos, comm_regexp.matchedLength()); + sql_cmd.remove(pos, comm_regexp.matchedLength()); + } + conn.executeDDLCommand(sql_cmd); db_created=true; + + if(!sql_cmd_comment.isEmpty()) + conn.executeDDLCommand(sql_cmd_comment); } } catch(Exception &e) @@ -474,8 +508,7 @@ void ModelExportHelper::exportToDBMS(DatabaseModel *db_model, Connection conn, c progress=30; //Creating the other object types - emit s_progressUpdated(progress, - trUtf8("Generating SQL for `%1' objects...").arg(db_model->getObjectCount())); + emit s_progressUpdated(progress, trUtf8("Generating SQL for `%1' objects...").arg(db_model->getObjectCount())); //Exporting the database model definition using the opened connection buf=db_model->getCodeDefinition(SchemaParser::SQL_DEFINITION, false); @@ -698,7 +731,8 @@ void ModelExportHelper::restoreObjectNames(void) /* Invalidates the codes of all objects on database model in order to generate the SQL referencing the object's with their original names */ - db_model->setCodesInvalidated(); + if(db_model) + db_model->setCodesInvalidated(); } bool ModelExportHelper::isDuplicationError(const QString &error_code) @@ -725,9 +759,8 @@ void ModelExportHelper::exportBufferToDBMS(const QString &buffer, Connection &co { Connection aux_conn; QString sql_buf=buffer, sql_cmd, aux_cmd, lin, msg, - obj_name, obj_tp_name, tab_name, + obj_name, obj_tp_name, tab_name, orig_conn_db_name, alter_tab=QString("ALTER TABLE"); - //vector errors; vector db_sql_cmds; QTextStream ts; ObjectType obj_type=BASE_OBJECT; @@ -743,7 +776,7 @@ void ModelExportHelper::exportBufferToDBMS(const QString &buffer, Connection &co drop_tab_obj_reg(QString("^((\\-\\-)+( )*)+(%1)(.)+(DROP)(.)+").arg(alter_tab)), reg_aux; - vector obj_types={ OBJ_ROLE, OBJ_FUNCTION, OBJ_TRIGGER, OBJ_INDEX, + vector obj_types={ OBJ_ROLE, OBJ_FUNCTION, OBJ_TRIGGER, OBJ_INDEX, OBJ_POLICY, OBJ_RULE, OBJ_TABLE, OBJ_VIEW, OBJ_DOMAIN, OBJ_SCHEMA, OBJ_AGGREGATE, OBJ_OPFAMILY, OBJ_OPCLASS, OBJ_OPERATOR, OBJ_SEQUENCE, @@ -758,6 +791,8 @@ void ModelExportHelper::exportBufferToDBMS(const QString &buffer, Connection &co if(!conn.isStablished()) { + orig_conn_db_name = conn.getConnectionParam(Connection::PARAM_DB_NAME); + if(!db_name.isEmpty()) conn.setConnectionParam(Connection::PARAM_DB_NAME, db_name); @@ -956,6 +991,7 @@ void ModelExportHelper::exportBufferToDBMS(const QString &buffer, Connection &co { conn.close(); aux_conn=conn; + aux_conn.setConnectionParam(Connection::PARAM_DB_NAME, orig_conn_db_name); aux_conn.connect(); for(QString cmd : db_sql_cmds) aux_conn.executeDDLCommand(cmd); @@ -964,9 +1000,7 @@ void ModelExportHelper::exportBufferToDBMS(const QString &buffer, Connection &co catch(Exception &e) { if(ddl_tk_found) ddl_tk_found=false; - handleSQLError(e, sql_cmd, ignore_dup); - sql_cmd.clear(); } } diff --git a/libpgmodeler_ui/src/modelexporthelper.h b/libpgmodeler_ui/src/modelexporthelper.h index 918f11844..2ad9382f0 100644 --- a/libpgmodeler_ui/src/modelexporthelper.h +++ b/libpgmodeler_ui/src/modelexporthelper.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelfixform.cpp b/libpgmodeler_ui/src/modelfixform.cpp index eaa5fc4cf..227188a84 100644 --- a/libpgmodeler_ui/src/modelfixform.cpp +++ b/libpgmodeler_ui/src/modelfixform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelfixform.h b/libpgmodeler_ui/src/modelfixform.h index d6f8cadd3..fe008ac2c 100644 --- a/libpgmodeler_ui/src/modelfixform.h +++ b/libpgmodeler_ui/src/modelfixform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelnavigationwidget.cpp b/libpgmodeler_ui/src/modelnavigationwidget.cpp index 26882f269..7dd94f140 100644 --- a/libpgmodeler_ui/src/modelnavigationwidget.cpp +++ b/libpgmodeler_ui/src/modelnavigationwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -114,12 +114,12 @@ void ModelNavigationWidget::removeModel(int idx) void ModelNavigationWidget::setCurrentModel(void) { - models_cmb->setToolTip(models_cmb->currentData().toString()); + models_cmb->setToolTip(models_cmb->currentData().toString()); - enableNavigationButtons(); + enableNavigationButtons(); - if(models_cmb->currentIndex() >= 0) - emit s_currentModelChanged(models_cmb->currentIndex()); + if(models_cmb->currentIndex() >= 0) + emit s_currentModelChanged(models_cmb->currentIndex()); } void ModelNavigationWidget::enableNavigationButtons(void) diff --git a/libpgmodeler_ui/src/modelnavigationwidget.h b/libpgmodeler_ui/src/modelnavigationwidget.h index 080474fe9..900573849 100644 --- a/libpgmodeler_ui/src/modelnavigationwidget.h +++ b/libpgmodeler_ui/src/modelnavigationwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelobjectswidget.cpp b/libpgmodeler_ui/src/modelobjectswidget.cpp index b8536adc8..b7aa3839f 100644 --- a/libpgmodeler_ui/src/modelobjectswidget.cpp +++ b/libpgmodeler_ui/src/modelobjectswidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,6 +36,7 @@ ModelObjectsWidget::ModelObjectsWidget(bool simplified_view, QWidget *parent) : cancel_tb->setVisible(simplified_view); options_tb->setVisible(!simplified_view); visibleobjects_grp->setVisible(false); + filter_wgt->setVisible(simplified_view); selected_object=nullptr; splitter->handle(1)->setEnabled(false); @@ -380,6 +381,7 @@ void ModelObjectsWidget::changeObjectsView(void) } else if(sender()==options_tb) { + filter_wgt->setVisible(options_tb->isChecked()); visibleobjects_grp->setVisible(options_tb->isChecked()); splitter->handle(1)->setEnabled(options_tb->isChecked()); @@ -459,18 +461,18 @@ void ModelObjectsWidget::updateSchemaTree(QTreeWidgetItem *root) { if(db_model && visible_objs_map[OBJ_SCHEMA]) { - BaseObject *object=nullptr, *schema=nullptr; + BaseObject *schema=nullptr; vector obj_list; QFont font; QTreeWidgetItem *item=nullptr, *item1=nullptr, *item2=nullptr, *item3=nullptr; - ObjectType types[]={ OBJ_FUNCTION, OBJ_AGGREGATE, - OBJ_DOMAIN, OBJ_TYPE, OBJ_CONVERSION, - OBJ_OPERATOR, OBJ_OPFAMILY, OBJ_OPCLASS, - OBJ_SEQUENCE, OBJ_COLLATION, OBJ_EXTENSION }; - int count, count2, type_cnt=sizeof(types)/sizeof(ObjectType), i, i1, i2; - + vector types = BaseObject::getChildObjectTypes(OBJ_SCHEMA); + int count, count2, i; QPixmap group_icon=QPixmap(PgModelerUiNS::getIconPath(QString(BaseObject::getSchemaName(OBJ_SCHEMA)) + QString("_grp"))); + //Removing the OBJ_TABLE and OBJ_VIEW types since they are handled separetedly + types.erase(std::find(types.begin(), types.end(), OBJ_TABLE)); + types.erase(std::find(types.begin(), types.end(), OBJ_VIEW)); + //Get the current schema count on database count=(db_model->getObjectCount(OBJ_SCHEMA)); item=new QTreeWidgetItem(root); @@ -478,8 +480,7 @@ void ModelObjectsWidget::updateSchemaTree(QTreeWidgetItem *root) item->setData(1, Qt::UserRole, QVariant::fromValue(OBJ_SCHEMA)); //Create the schema group item - item->setText(0,BaseObject::getTypeName(OBJ_SCHEMA) + - QString(" (%1)").arg(count)); + item->setText(0, QString("%1 (%2)").arg(BaseObject::getTypeName(OBJ_SCHEMA)).arg(count)); font=item->font(0); font.setItalic(true); item->setFont(0, font); @@ -497,7 +498,7 @@ void ModelObjectsWidget::updateSchemaTree(QTreeWidgetItem *root) } else { - schema=db_model->getObject(i,OBJ_SCHEMA); + schema=db_model->getObject(i, OBJ_SCHEMA); item2=createItemForObject(schema, item); } @@ -508,31 +509,26 @@ void ModelObjectsWidget::updateSchemaTree(QTreeWidgetItem *root) updateViewTree(item2, schema); //Creates the object group at schema level (function, domain, sequences, etc) - for(i1=0; i1 < type_cnt; i1++) + for(auto type : types) { - if(visible_objs_map[types[i1]]) + if(visible_objs_map[type]) { item3=new QTreeWidgetItem(item2); - item3->setIcon(0,QPixmap(PgModelerUiNS::getIconPath(BaseObject::getSchemaName(types[i1]) + QString("_grp")))); + item3->setIcon(0,QPixmap(PgModelerUiNS::getIconPath(BaseObject::getSchemaName(type) + QString("_grp")))); //Get the objects that belongs to the current schema - obj_list=db_model->getObjects(types[i1], schema); + obj_list=db_model->getObjects(type, schema); count2=obj_list.size(); - item3->setText(0, - BaseObject::getTypeName(types[i1]) + - QString(" (%1)").arg(count2)); - item3->setData(1, Qt::UserRole, QVariant::fromValue(types[i1])); + item3->setText(0, QString("%1 (%2)").arg(BaseObject::getTypeName(type)).arg(count2)); + item3->setData(1, Qt::UserRole, QVariant::fromValue(type)); font=item3->font(0); font.setItalic(true); item3->setFont(0, font); - for(i2=0; i2 < count2; i2++) - { - object=obj_list[i2]; - createItemForObject(object, item3); - } + for(auto obj : obj_list) + createItemForObject(obj, item3); } } } @@ -548,14 +544,11 @@ void ModelObjectsWidget::updateTableTree(QTreeWidgetItem *root, BaseObject *sche { if(db_model && visible_objs_map[OBJ_TABLE]) { - BaseObject *object=nullptr; vector obj_list; Table *table=nullptr; QTreeWidgetItem *item=nullptr, *item1=nullptr, *item2=nullptr; QFont font; - ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_RULE, - OBJ_TRIGGER, OBJ_INDEX }; - int count, count1, type_cnt=sizeof(types)/sizeof(ObjectType), i, i1, i2; + vector types = BaseObject::getChildObjectTypes(OBJ_TABLE); QPixmap group_icon=QPixmap(PgModelerUiNS::getIconPath(BaseObject::getSchemaName(OBJ_TABLE) + QString("_grp"))); try @@ -574,32 +567,26 @@ void ModelObjectsWidget::updateTableTree(QTreeWidgetItem *root, BaseObject *sche font.setItalic(true); item->setFont(0, font); - count=obj_list.size(); - for(i=0; i < count; i++) + for(auto obj : obj_list) { - table=dynamic_cast
(obj_list[i]); + table=dynamic_cast
(obj); item1=createItemForObject(table, item); //Creating the group for the child objects (column, rules, triggers, indexes and constraints) - for(i1=0; i1 < type_cnt; i1++) + for(auto type : types) { - if(visible_objs_map[types[i1]]) + if(visible_objs_map[type]) { item2=new QTreeWidgetItem(item1); - item2->setIcon(0,QPixmap(PgModelerUiNS::getIconPath(BaseObject::getSchemaName(types[i1]) + QString("_grp")))); + item2->setIcon(0,QPixmap(PgModelerUiNS::getIconPath(BaseObject::getSchemaName(type) + QString("_grp")))); font=item2->font(0); font.setItalic(true); item2->setFont(0, font); - count1=table->getObjectCount(types[i1]); - item2->setText(0,BaseObject::getTypeName(types[i1]) + - QString(" (%1)").arg(count1)); + item2->setText(0, QString("%1 (%2)").arg(BaseObject::getTypeName(type)).arg(table->getObjectCount(type))); - for(i2=0; i2 < count1; i2++) - { - object=table->getObject(i2,types[i1]); - createItemForObject(object, item2); - } + for(auto tab_obj : *table->getObjectList(type)) + createItemForObject(tab_obj, item2); } } } @@ -720,7 +707,8 @@ void ModelObjectsWidget::updateDatabaseTree(void) vector ref_list, tree_state, obj_list; ObjectType types[]={ OBJ_ROLE, OBJ_TABLESPACE, OBJ_LANGUAGE, OBJ_CAST, OBJ_TEXTBOX, - OBJ_RELATIONSHIP, OBJ_EVENT_TRIGGER, OBJ_TAG, OBJ_GENERIC_SQL }; + OBJ_RELATIONSHIP, OBJ_EVENT_TRIGGER, + OBJ_TAG, OBJ_GENERIC_SQL, OBJ_EXTENSION }; unsigned count, i, i1, type_cnt=sizeof(types)/sizeof(ObjectType); try diff --git a/libpgmodeler_ui/src/modelobjectswidget.h b/libpgmodeler_ui/src/modelobjectswidget.h index 99cacd052..2c71b20ca 100644 --- a/libpgmodeler_ui/src/modelobjectswidget.h +++ b/libpgmodeler_ui/src/modelobjectswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modeloverviewwidget.cpp b/libpgmodeler_ui/src/modeloverviewwidget.cpp index ff6cd9f90..a63ebf8a0 100644 --- a/libpgmodeler_ui/src/modeloverviewwidget.cpp +++ b/libpgmodeler_ui/src/modeloverviewwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modeloverviewwidget.h b/libpgmodeler_ui/src/modeloverviewwidget.h index 81b69f002..d5e950a27 100644 --- a/libpgmodeler_ui/src/modeloverviewwidget.h +++ b/libpgmodeler_ui/src/modeloverviewwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelrestorationform.cpp b/libpgmodeler_ui/src/modelrestorationform.cpp index f81539bb5..2e434fe72 100644 --- a/libpgmodeler_ui/src/modelrestorationform.cpp +++ b/libpgmodeler_ui/src/modelrestorationform.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelrestorationform.h b/libpgmodeler_ui/src/modelrestorationform.h index 37e0cfe29..f859f004e 100644 --- a/libpgmodeler_ui/src/modelrestorationform.h +++ b/libpgmodeler_ui/src/modelrestorationform.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelsdiffhelper.cpp b/libpgmodeler_ui/src/modelsdiffhelper.cpp index 25e37f8ca..fb2f6fe16 100644 --- a/libpgmodeler_ui/src/modelsdiffhelper.cpp +++ b/libpgmodeler_ui/src/modelsdiffhelper.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -30,12 +30,13 @@ ModelsDiffHelper::ModelsDiffHelper(void) diff_opts[OPT_KEEP_CLUSTER_OBJS]=true; diff_opts[OPT_CASCADE_MODE]=true; diff_opts[OPT_TRUCANTE_TABLES]=false; - diff_opts[OPT_FORCE_RECREATION]=false; + diff_opts[OPT_FORCE_RECREATION]=true; diff_opts[OPT_RECREATE_UNCHANGEBLE]=true; diff_opts[OPT_KEEP_OBJ_PERMS]=true; diff_opts[OPT_REUSE_SEQUENCES]=true; diff_opts[OPT_PRESERVE_DB_NAME]=true; - diff_opts[OPT_KEEP_NOT_IMPORTED_OBJS]=false; + diff_opts[OPT_DONT_DROP_MISSING_OBJS]=false; + diff_opts[OPT_DROP_MISSING_COLS_CONSTR]=false; } ModelsDiffHelper::~ModelsDiffHelper(void) @@ -45,10 +46,13 @@ ModelsDiffHelper::~ModelsDiffHelper(void) void ModelsDiffHelper::setDiffOption(unsigned opt_id, bool value) { - if(opt_id > OPT_KEEP_NOT_IMPORTED_OBJS) + if(opt_id > OPT_DROP_MISSING_COLS_CONSTR) throw Exception(ERR_REF_ELEM_INV_INDEX,__PRETTY_FUNCTION__,__FILE__,__LINE__); - diff_opts[opt_id]=value; + if(opt_id == OPT_DROP_MISSING_COLS_CONSTR) + diff_opts[opt_id]=value & !diff_opts[OPT_DROP_MISSING_COLS_CONSTR]; + else + diff_opts[opt_id]=value; } void ModelsDiffHelper::setPgSQLVersion(const QString pgsql_ver) @@ -149,11 +153,12 @@ void ModelsDiffHelper::diffTables(Table *src_table, Table *imp_table, unsigned d aux_obj=comp_tab->getObject(tab_obj->getName(), tab_obj->getObjectType()); constr=dynamic_cast(tab_obj); - //Ignoring check constraints added by generalizations - if(constr && constr->isAddedByGeneralization() && - constr->getConstraintType()==ConstraintType::check) + //Ignoring object with sql disabled or check constraints added by generalizations + if(tab_obj->isSQLDisabled() || + (constr && constr->isAddedByGeneralization() && + constr->getConstraintType()==ConstraintType::check)) { - generateDiffInfo(ObjectsDiffInfo::IGNORE_OBJECT, constr); + generateDiffInfo(ObjectsDiffInfo::IGNORE_OBJECT, tab_obj); } else { @@ -176,7 +181,8 @@ void ModelsDiffHelper::diffTables(Table *src_table, Table *imp_table, unsigned d else if(!aux_obj && !tab_obj->isAddedByGeneralization()) { if(diff_type!=ObjectsDiffInfo::DROP_OBJECT || - (diff_type==ObjectsDiffInfo::DROP_OBJECT && !diff_opts[OPT_KEEP_NOT_IMPORTED_OBJS])) + (diff_type==ObjectsDiffInfo::DROP_OBJECT && !diff_opts[OPT_DONT_DROP_MISSING_OBJS]) || + (diff_type==ObjectsDiffInfo::DROP_OBJECT && diff_opts[OPT_DROP_MISSING_COLS_CONSTR])) generateDiffInfo(diff_type, tab_obj); else generateDiffInfo(ObjectsDiffInfo::IGNORE_OBJECT, tab_obj); @@ -329,7 +335,7 @@ void ModelsDiffHelper::diffModels(unsigned diff_type) else if(!aux_object) { if(diff_type != ObjectsDiffInfo::DROP_OBJECT || - (diff_type == ObjectsDiffInfo::DROP_OBJECT && !diff_opts[OPT_KEEP_NOT_IMPORTED_OBJS])) + (diff_type == ObjectsDiffInfo::DROP_OBJECT && !diff_opts[OPT_DONT_DROP_MISSING_OBJS])) generateDiffInfo(diff_type, object); else generateDiffInfo(ObjectsDiffInfo::IGNORE_OBJECT, object); @@ -387,8 +393,7 @@ void ModelsDiffHelper::diffTableObject(TableObject *tab_obj, unsigned diff_type) if(!aux_base_tab) aux_base_tab=dynamic_cast(getRelNNTable(tab_name, source_model)); } - else if(diff_type==ObjectsDiffInfo::CREATE_OBJECT || - diff_type==ObjectsDiffInfo::ALTER_OBJECT) + else if(diff_type==ObjectsDiffInfo::CREATE_OBJECT || diff_type==ObjectsDiffInfo::ALTER_OBJECT) { aux_base_tab=dynamic_cast(imported_model->getObject(tab_name, base_tab->getObjectType())); @@ -411,7 +416,7 @@ void ModelsDiffHelper::diffTableObject(TableObject *tab_obj, unsigned diff_type) if(!aux_tab_obj) { if(diff_type!=ObjectsDiffInfo::DROP_OBJECT || - (diff_type==ObjectsDiffInfo::DROP_OBJECT && !diff_opts[OPT_KEEP_NOT_IMPORTED_OBJS])) + (diff_type==ObjectsDiffInfo::DROP_OBJECT && !diff_opts[OPT_DONT_DROP_MISSING_OBJS])) generateDiffInfo(diff_type, tab_obj); else generateDiffInfo(ObjectsDiffInfo::IGNORE_OBJECT, tab_obj); @@ -602,7 +607,7 @@ void ModelsDiffHelper::processDiffInfos(void) map::reverse_iterator ritr, ritr_end; attribs_map attribs; QString alter_def, no_inherit_def, inherit_def, set_perms, - unset_perms, col_drop_def; + unset_perms, col_drop_def, curr_pgsql_ver = BaseObject::getPgSQLVersion(); SchemaParser schparser; Type *type=nullptr; vector types; @@ -614,6 +619,9 @@ void ModelsDiffHelper::processDiffInfos(void) try { + //Overriding the global PostgreSQL version so the diff code can match the destination server version + BaseObject::setPgSQLVersion(pgsql_version); + if(!diff_infos.empty()) emit s_progressUpdated(0, trUtf8("Processing diff infos...")); @@ -777,10 +785,12 @@ void ModelsDiffHelper::processDiffInfos(void) if(diff.getOldObject()) alter_def=diff.getOldObject()->getAlterDefinition(object); + if(obj_type == OBJ_DATABASE && diff_opts[OPT_PRESERVE_DB_NAME]) + alter_def.remove(QRegExp(QString("(ALTER)( )+(DATABASE)( )+(%1)( )+(RENAME)( )+(TO)(.)*(\\n)").arg(diff.getOldObject()->getSignature()))); + if(!alter_def.isEmpty()) { - if(obj_type!=OBJ_DATABASE || !diff_opts[OPT_PRESERVE_DB_NAME]) - alter_objs[object->getObjectId()]=alter_def; + alter_objs[object->getObjectId()]=alter_def; /* If the object is a column checks if the types of the columns are differents, generating a TRUNCATE TABLE for the parent table */ @@ -821,11 +831,11 @@ void ModelsDiffHelper::processDiffInfos(void) diff_def.clear(); - if(!drop_objs.empty() || !create_objs.empty() || !alter_objs.empty() || !create_fks.empty() || - !inherit_def.isEmpty() || !no_inherit_def.isEmpty() || !set_perms.isEmpty() || - !col_drop_def.isEmpty()) + if(!drop_objs.empty() || !create_objs.empty() || !alter_objs.empty() || + !create_fks.empty() || !create_constrs.empty() || !inherit_def.isEmpty() || + !no_inherit_def.isEmpty() || !set_perms.isEmpty() || !col_drop_def.isEmpty()) { - unsigned create_objs_count=create_objs.size() + create_fks.size(); + unsigned create_objs_count=create_objs.size() + create_constrs.size() + create_fks.size(); bool has_diffs=false; sch_names.removeDuplicates(); @@ -834,6 +844,10 @@ void ModelsDiffHelper::processDiffInfos(void) //Attributes used on the diff schema file attribs[ParsersAttributes::HAS_CHANGES]=ParsersAttributes::_TRUE_; attribs[ParsersAttributes::PGMODELER_VERSION]=GlobalAttributes::PGMODELER_VERSION; + attribs[ParsersAttributes::DB_MODEL]=source_model->getName(); + attribs[ParsersAttributes::DATABASE]=imported_model->getName(); + attribs[ParsersAttributes::DATE]=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); + attribs[ParsersAttributes::CONNECTION]=imported_model->getName(); attribs[ParsersAttributes::CHANGE]=QString::number(alter_objs.size()); attribs[ParsersAttributes::CREATE]=QString::number(create_objs_count); attribs[ParsersAttributes::DROP]=QString::number(drop_objs.size()); @@ -891,9 +905,14 @@ void ModelsDiffHelper::processDiffInfos(void) emit s_progressUpdated(100, trUtf8("No differences between the model and database.")); else emit s_progressUpdated(100, trUtf8("Preparing diff code...")); + + //Restoring the global PostgreSQL version + BaseObject::setPgSQLVersion(curr_pgsql_ver); } catch(Exception &e) { + BaseObject::setPgSQLVersion(curr_pgsql_ver); + for(Type *type : types) type->convertFunctionParameters(true); @@ -959,7 +978,8 @@ void ModelsDiffHelper::recreateObject(BaseObject *object, vector & { if(object && object->getObjectType()!=BASE_RELATIONSHIP && - object->getObjectType()!=OBJ_RELATIONSHIP) + object->getObjectType()!=OBJ_RELATIONSHIP && + object->getObjectType()!=OBJ_DATABASE) { vector ref_objs; BaseObject *aux_obj=nullptr; diff --git a/libpgmodeler_ui/src/modelsdiffhelper.h b/libpgmodeler_ui/src/modelsdiffhelper.h index 1a8bf41f3..8a0b2534d 100644 --- a/libpgmodeler_ui/src/modelsdiffhelper.h +++ b/libpgmodeler_ui/src/modelsdiffhelper.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -43,7 +43,7 @@ class ModelsDiffHelper: public QObject { bool diff_canceled, //!brief Diff options. See OPT_??? constants - diff_opts[9]; + diff_opts[10]; //! \brief Stores the count of objects to be dropped, changed or created unsigned diffs_counter[4]; @@ -128,8 +128,12 @@ class ModelsDiffHelper: public QObject { /*! \brief Indicates to not generate and execute commands to drop missing objects. For instance, if user try to diff a partial model against the original database DROP commands will be generated, this option will avoid this situation and preserve the missing (not imported) objects. */ - OPT_KEEP_NOT_IMPORTED_OBJS=8; + OPT_DONT_DROP_MISSING_OBJS=8, + /*! \brief Indicates to generate and execute commands to drop missing columns and constraints. For instance, if user + try to diff a partial model against the original database and the OPT_DONT_DROP_MISSING_OBJS is set, DROP commands will not be generated, + except for columns and constraints. This option is only considered in the process when OPT_DONT_DROP_MISSING_OBJS is enabled. */ + OPT_DROP_MISSING_COLS_CONSTR=9; ModelsDiffHelper(void); ~ModelsDiffHelper(void); diff --git a/libpgmodeler_ui/src/modelvalidationhelper.cpp b/libpgmodeler_ui/src/modelvalidationhelper.cpp index 704642887..cd0d404ee 100644 --- a/libpgmodeler_ui/src/modelvalidationhelper.cpp +++ b/libpgmodeler_ui/src/modelvalidationhelper.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/modelvalidationhelper.h b/libpgmodeler_ui/src/modelvalidationhelper.h index 516f09548..abde765d1 100644 --- a/libpgmodeler_ui/src/modelvalidationhelper.h +++ b/libpgmodeler_ui/src/modelvalidationhelper.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelvalidationwidget.cpp b/libpgmodeler_ui/src/modelvalidationwidget.cpp index 88f96bba6..9017267c0 100644 --- a/libpgmodeler_ui/src/modelvalidationwidget.cpp +++ b/libpgmodeler_ui/src/modelvalidationwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/modelvalidationwidget.h b/libpgmodeler_ui/src/modelvalidationwidget.h index 7d8ded82b..aecc877b3 100644 --- a/libpgmodeler_ui/src/modelvalidationwidget.h +++ b/libpgmodeler_ui/src/modelvalidationwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/modelwidget.cpp b/libpgmodeler_ui/src/modelwidget.cpp index 6e98dbc03..128f436c6 100644 --- a/libpgmodeler_ui/src/modelwidget.cpp +++ b/libpgmodeler_ui/src/modelwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -55,6 +55,7 @@ #include "pgmodeleruins.h" #include "swapobjectsidswidget.h" #include "genericsqlwidget.h" +#include "policywidget.h" vector ModelWidget::copied_objects; vector ModelWidget::cutted_objects; @@ -85,8 +86,9 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) OBJ_FUNCTION, OBJ_AGGREGATE, OBJ_LANGUAGE, OBJ_OPCLASS, OBJ_OPERATOR, OBJ_OPFAMILY, OBJ_ROLE, OBJ_SCHEMA, OBJ_SEQUENCE, OBJ_TYPE, - OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_RULE, OBJ_TRIGGER, OBJ_INDEX, OBJ_TABLESPACE, - OBJ_COLLATION, OBJ_EXTENSION, OBJ_EVENT_TRIGGER, OBJ_TAG, OBJ_GENERIC_SQL }; + OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_RULE, OBJ_TRIGGER, OBJ_INDEX, OBJ_POLICY, + OBJ_TABLESPACE, OBJ_COLLATION, OBJ_EXTENSION, OBJ_EVENT_TRIGGER, OBJ_TAG, + OBJ_GENERIC_SQL }; unsigned i, obj_cnt=sizeof(types)/sizeof(ObjectType), rel_types_id[]={ BaseRelationship::RELATIONSHIP_11, BaseRelationship::RELATIONSHIP_1N, BaseRelationship::RELATIONSHIP_NN, BaseRelationship::RELATIONSHIP_DEP, @@ -221,11 +223,13 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) action_remove=new QAction(QIcon(PgModelerUiNS::getIconPath("excluir")), trUtf8("Delete"), this); action_remove->setShortcut(QKeySequence(trUtf8("Del"))); + action_remove->setMenuRole(QAction::NoRole); action_cascade_del=new QAction(QIcon(PgModelerUiNS::getIconPath("delcascade")), trUtf8("Del. cascade"), this); action_cascade_del->setShortcut(QKeySequence(trUtf8("Shift+Del"))); + action_cascade_del->setMenuRole(QAction::NoRole); - action_select_all=new QAction(QIcon(PgModelerUiNS::getIconPath("seltodos")), trUtf8("Select all"), this); + action_select_all=new QAction(QIcon(PgModelerUiNS::getIconPath("seltodos")), trUtf8("Select all"), this); action_select_all->setToolTip(trUtf8("Selects all the graphical objects in the model")); action_select_all->setMenu(&select_all_menu); @@ -233,12 +237,15 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) action_copy=new QAction(QIcon(PgModelerUiNS::getIconPath("copiar")), trUtf8("Copy"), this); action_copy->setShortcut(QKeySequence(trUtf8("Ctrl+C"))); + action_copy->setMenuRole(QAction::NoRole); action_paste=new QAction(QIcon(PgModelerUiNS::getIconPath("colar")), trUtf8("Paste"), this); action_paste->setShortcut(QKeySequence(trUtf8("Ctrl+V"))); + action_paste->setMenuRole(QAction::NoRole); action_cut=new QAction(QIcon(PgModelerUiNS::getIconPath("recortar")), trUtf8("Cut"), this); action_cut->setShortcut(QKeySequence(trUtf8("Ctrl+X"))); + action_cut->setMenuRole(QAction::NoRole); action_deps_refs=new QAction(QIcon(PgModelerUiNS::getIconPath("depsrefs")), trUtf8("Deps && Referrers"), this); @@ -268,7 +275,7 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) action_sel_sch_children=new QAction(QIcon(PgModelerUiNS::getIconPath("seltodos")), trUtf8("Select children"), this); action_sel_tagged_tabs=new QAction(QIcon(PgModelerUiNS::getIconPath("seltodos")), trUtf8("Select tagged"), this); - action_highlight_object=new QAction(QIcon(PgModelerUiNS::getIconPath("movimentado")), trUtf8("Highlight"), this); + action_select_object=new QAction(QIcon(PgModelerUiNS::getIconPath("movimentado")), trUtf8("Select"), this); action_parent_rel=new QAction(QIcon(PgModelerUiNS::getIconPath("relationship")), trUtf8("Open relationship"), this); action_append_sql=new QAction(QIcon(PgModelerUiNS::getIconPath("sqlappend")), trUtf8("Custom SQL"), this); @@ -286,6 +293,7 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) action_duplicate=new QAction(QIcon(PgModelerUiNS::getIconPath("duplicate")), trUtf8("Duplicate"), this); action_duplicate->setShortcut(QKeySequence(trUtf8("Ctrl+D"))); + action_duplicate->setMenuRole(QAction::NoRole); action_extended_attribs=new QAction(QIcon(PgModelerUiNS::getIconPath("toggleattribs")), trUtf8("Extended attributes"), this); action_show_ext_attribs=new QAction(trUtf8("Show"), this); @@ -298,6 +306,13 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) toggle_attrs_menu.addAction(action_hide_ext_attribs); action_extended_attribs->setMenu(&toggle_attrs_menu); + action_schemas_rects=new QAction(QIcon(PgModelerUiNS::getIconPath("schemarect")), trUtf8("Schemas rectangles"), this); + action_show_schemas_rects=new QAction(trUtf8("Show"), this); + action_hide_schemas_rects=new QAction(trUtf8("Hide"), this); + toggle_sch_rects_menu.addAction(action_show_schemas_rects); + toggle_sch_rects_menu.addAction(action_hide_schemas_rects); + action_schemas_rects->setMenu(&toggle_sch_rects_menu); + action_fade=new QAction(QIcon(PgModelerUiNS::getIconPath("fade")), trUtf8("Fade in/out"), this); action_fade_in=new QAction(QIcon(PgModelerUiNS::getIconPath("fadein")), trUtf8("Fade in"), this); action_fade_out=new QAction(QIcon(PgModelerUiNS::getIconPath("fadeout")), trUtf8("Fade out"), this); @@ -410,7 +425,7 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) connect(action_edit_perms, SIGNAL(triggered(bool)), this, SLOT(editPermissions(void))); connect(action_sel_sch_children, SIGNAL(triggered(bool)), this, SLOT(selectSchemaChildren(void))); connect(action_sel_tagged_tabs, SIGNAL(triggered(bool)), this, SLOT(selectTaggedTables(void))); - connect(action_highlight_object, SIGNAL(triggered(bool)), this, SLOT(highlightObject(void))); + connect(action_select_object, SIGNAL(triggered(bool)), this, SLOT(highlightObject(void))); connect(action_parent_rel, SIGNAL(triggered(bool)), this, SLOT(editObject(void))); connect(action_append_sql, SIGNAL(triggered(bool)), this, SLOT(editCustomSQL(void))); connect(action_create_seq_col, SIGNAL(triggered(bool)), this, SLOT(createSequenceFromColumn(void))); @@ -430,6 +445,9 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) connect(action_show_ext_attribs, SIGNAL(triggered(bool)), this, SLOT(toggleExtendedAttributes())); connect(action_hide_ext_attribs, SIGNAL(triggered(bool)), this, SLOT(toggleExtendedAttributes())); + connect(action_show_schemas_rects, SIGNAL(triggered(bool)), this, SLOT(toggleSchemasRectangles())); + connect(action_hide_schemas_rects, SIGNAL(triggered(bool)), this, SLOT(toggleSchemasRectangles())); + connect(db_model, SIGNAL(s_objectAdded(BaseObject*)), this, SLOT(handleObjectAddition(BaseObject *))); connect(db_model, SIGNAL(s_objectRemoved(BaseObject*)), this, SLOT(handleObjectRemoval(BaseObject *))); @@ -439,6 +457,7 @@ ModelWidget::ModelWidget(QWidget *parent) : QWidget(parent) connect(scene, SIGNAL(s_popupMenuRequested(BaseObject*)), this, SLOT(configureObjectMenu(BaseObject *))); connect(scene, SIGNAL(s_popupMenuRequested(void)), this, SLOT(showObjectMenu(void))); connect(scene, SIGNAL(s_objectSelected(BaseGraphicObject*,bool)), this, SLOT(configureObjectSelection(void))); + connect(scene, SIGNAL(s_objectsSelectedInRange(void)), this, SLOT(configureObjectSelection(void))); connect(scene, &ObjectsScene::s_extAttributesToggled, [&](){ modified = true; }); @@ -816,7 +835,7 @@ void ModelWidget::addNewObject(void) this->showObjectForm(obj_type, nullptr, parent_obj, pos); } else if(obj_type!=OBJ_TABLE && obj_type!=OBJ_VIEW && - obj_type!=OBJ_TEXTBOX && obj_type <= BASE_TABLE) + obj_type!=OBJ_TEXTBOX && obj_type <= BASE_TABLE) this->showObjectForm(obj_type, nullptr, parent_obj); else { @@ -841,6 +860,13 @@ void ModelWidget::addNewObject(void) viewport->setCursor(QCursor(action->icon().pixmap(QSize(22,22)),0,0)); this->new_obj_type=obj_type; this->enableModelActions(false); + + /* If a single table is selected and the user triggered a relationship creation action via popup menu, + * we force the enabling of the relationship creation steps. This will automatically selects the current table + * as source table of the relationship */ + if(selected_objects.size() == 1 && + selected_objects[0]->getObjectType() == OBJ_TABLE && new_obj_type > BASE_TABLE) + configureObjectSelection(); } } } @@ -1071,7 +1097,10 @@ void ModelWidget::selectAllObjects(void) { QPainterPath pth; pth.addRect(scene->sceneRect()); + + scene->blockItemsSignals(true); scene->setSelectionArea(pth); + scene->blockItemsSignals(false); } else { @@ -1086,9 +1115,15 @@ void ModelWidget::selectAllObjects(void) obj_view = dynamic_cast(dynamic_cast(obj)->getReceiverObject()); if(obj_view) + { + obj_view->blockSignals(true); obj_view->setSelected(true); + obj_view->blockSignals(false); + } } } + + configureObjectSelection(); } void ModelWidget::convertRelationshipNN(void) @@ -1270,16 +1305,16 @@ void ModelWidget::convertRelationshipNN(void) } /* Creates a one-to-many relationship that links the source table of the many-to-many rel. to the created table - The relationship will be identifier if the single pk column attribute of the original relationship is false */ + The relationship will be identifier if the single pk column attribute of the original relationship is false */ rel1=new Relationship(Relationship::RELATIONSHIP_1N, - src_tab, tab, src_mand, false, !rel->isSiglePKColumn()); + src_tab, tab, src_mand, false, !rel->isSiglePKColumn()); db_model->addRelationship(rel1); op_list->registerObject(rel1, Operation::OBJECT_CREATED); /*Creates a one-to-many relationship that links the destination table of the many-to-many rel. to the created table - The relationship will be identifier if the single pk column attribute of the original relationship is false */ + The relationship will be identifier if the single pk column attribute of the original relationship is false */ rel2=new Relationship(Relationship::RELATIONSHIP_1N, - dst_tab, tab, dst_mand, false, !rel->isSiglePKColumn()); + dst_tab, tab, dst_mand, false, !rel->isSiglePKColumn()); db_model->addRelationship(rel2); op_list->registerObject(rel2, Operation::OBJECT_CREATED); } @@ -1361,7 +1396,10 @@ void ModelWidget::adjustSceneSize(void) viewport->centerOn(0,0); if(align_objs) + { scene->alignObjectsToGrid(); + db_model->setObjectsModified({ OBJ_RELATIONSHIP, BASE_RELATIONSHIP }); + } emit s_sceneInteracted(scene_rect.size()); } @@ -1687,6 +1725,8 @@ void ModelWidget::showObjectForm(ObjectType obj_type, BaseObject *object, BaseOb res=openEditingForm(object, parent_obj); else if(obj_type== OBJ_INDEX) res=openEditingForm(object, parent_obj); + else if(obj_type== OBJ_POLICY) + res=openEditingForm(object, parent_obj); else if(obj_type==OBJ_COLUMN || obj_type==OBJ_CONSTRAINT) { TableObject *tab_obj=dynamic_cast(object); @@ -1714,7 +1754,7 @@ void ModelWidget::showObjectForm(ObjectType obj_type, BaseObject *object, BaseOb { Table *tab1=dynamic_cast
(selected_objects[0]), *tab2=(selected_objects.size()==2 ? - dynamic_cast
(selected_objects[1]) : tab1); + dynamic_cast
(selected_objects[1]) : tab1); relationship_wgt->setAttributes(db_model, op_list, tab1, tab2, rel_type); } else @@ -1839,15 +1879,15 @@ void ModelWidget::renameObject(void) void ModelWidget::moveToSchema(void) { QAction *act=dynamic_cast(sender()); - Schema *schema=dynamic_cast(reinterpret_cast(act->data().value())), - *prev_schema=nullptr; + Schema *schema=dynamic_cast(reinterpret_cast(act->data().value())); BaseGraphicObject *obj_graph=nullptr; vector ref_objs; - vectorrels; int op_id=-1, op_curr_idx=op_list->getCurrentIndex(); try { + QApplication::setOverrideCursor(Qt::WaitCursor); + op_list->startOperationChain(); for(BaseObject *obj : selected_objects) @@ -1855,7 +1895,6 @@ void ModelWidget::moveToSchema(void) //Change the object's schema only if the new schema is different from the current if(obj->acceptsSchema() && obj->getSchema()!=schema) { - prev_schema=dynamic_cast(obj->getSchema()); op_id=op_list->registerObject(obj, Operation::OBJECT_MODIFIED, -1); obj->setSchema(schema); @@ -1873,55 +1912,28 @@ void ModelWidget::moveToSchema(void) p.setY(dst_schema->pos().y() + dst_schema->boundingRect().height() + BaseObjectView::VERT_SPACING); dynamic_cast(obj_graph->getReceiverObject())->setPos(p); } - - obj_graph->setModified(true); - schema->setModified(true); - prev_schema->setModified(true); } //Invalidating the code of the object's references db_model->getObjectReferences(obj, ref_objs); + for(BaseObject *ref_obj : ref_objs) - { ref_obj->setCodeInvalidated(true); - - //If the ref object is an table child object - if(TableObject::isTableObject(ref_obj->getObjectType())) - { - //Updates the parent table instead of the object - obj_graph=dynamic_cast(dynamic_cast(ref_obj)->getParentTable()); - - //Get the relationships that the table participate - rels=db_model->getRelationships(dynamic_cast(obj_graph)); - - obj_graph->setModified(true); - - if(!rels.empty()) - { - //Updating the tables from relationships - for(auto &rel : rels) - { - if(rel->getTable(BaseRelationship::SRC_TABLE)!=obj_graph) - rel->getTable(BaseRelationship::SRC_TABLE)->setModified(true); - - if(rel->getTable(BaseRelationship::DST_TABLE)!=obj_graph) - rel->getTable(BaseRelationship::DST_TABLE)->setModified(true); - } - } - } - else - dynamic_cast(ref_obj)->setModified(true); - } } } op_list->finishOperationChain(); - + db_model->setObjectsModified(); this->setModified(true); + emit s_objectModified(); + + QApplication::restoreOverrideCursor(); } catch(Exception &e) { + QApplication::restoreOverrideCursor(); + if(op_id >=0 && op_id > op_curr_idx) op_list->removeLastOperation(); @@ -1994,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) @@ -2047,8 +2061,8 @@ void ModelWidget::selectSchemaChildren(void) Schema *schema=nullptr; schema=dynamic_cast( - reinterpret_cast( - dynamic_cast(obj_sender)->data().value())); + reinterpret_cast( + dynamic_cast(obj_sender)->data().value())); scene->clearSelection(); @@ -2198,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; @@ -2242,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]); @@ -2259,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->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 || + (((constr && + (constr->getConstraintType()==ConstraintType::foreign_key || + (constr->getConstraintType()==ConstraintType::unique && + constr->isReferRelationshipAddedColumn()))))))) deps.push_back(tab_obj); } + + if(object->getObjectType() == OBJ_VIEW && type_id >= 2) + break; } } } @@ -2314,7 +2330,7 @@ void ModelWidget::pasteObjects(void) Operator *oper=nullptr; QString aux_name, copy_obj_name; ObjectType obj_type; - Exception error; + vector errors; unsigned pos=0; TaskProgressWidget task_prog_wgt(this); @@ -2362,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); @@ -2376,9 +2392,9 @@ void ModelWidget::pasteObjects(void) if(tab_obj || (aux_object && (dynamic_cast(object) || - (aux_object->getDatabase()==object->getDatabase()) || - (aux_object->getCodeDefinition(SchemaParser::SchemaParser::XML_DEFINITION) != - object->getCodeDefinition(SchemaParser::SchemaParser::XML_DEFINITION))))) + (aux_object->getDatabase()==object->getDatabase()) || + (aux_object->getCodeDefinition(SchemaParser::SchemaParser::XML_DEFINITION) != + object->getCodeDefinition(SchemaParser::SchemaParser::XML_DEFINITION))))) { //Resolving name conflicts if(obj_type!=OBJ_CAST) @@ -2408,9 +2424,14 @@ void ModelWidget::pasteObjects(void) else { if(tab_obj) - tab_obj->setName(PgModelerNS::generateUniqueName(tab_obj, (*sel_table->getObjectList(tab_obj->getObjectType())), false, QString("_cp"))); + { + 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"))); + object->setName(PgModelerNS::generateUniqueName(object, (*db_model->getObjectList(object->getObjectType())), false, QString("_cp"), true)); copy_obj_name=object->getName(); object->setName(orig_obj_names[object]); @@ -2455,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 - view's only accepts this two types) */ + 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(); @@ -2503,10 +2525,13 @@ void ModelWidget::pasteObjects(void) while(itr!=itr_end) { - if(xml_objs.count(*itr)) + object = *itr; + itr++; + + if(xml_objs.count(object)) { xmlparser->restartParser(); - xmlparser->loadXMLBuffer(xml_objs[*itr]); + xmlparser->loadXMLBuffer(xml_objs[object]); try { @@ -2534,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) @@ -2557,11 +2576,9 @@ void ModelWidget::pasteObjects(void) } catch(Exception &e) { - error=e; + errors.push_back(e); } } - - itr++; } op_list->finishOperationChain(); @@ -2572,12 +2589,12 @@ void ModelWidget::pasteObjects(void) task_prog_wgt.close(); //If some error occur during the process show it to the user - if(error.getErrorType()!=ERR_CUSTOM) + if(!errors.empty()) { Messagebox msg_box; - msg_box.show(error, - trUtf8("Not all objects were pasted to the model due to errors returned during the process! Refer to error stack for more details!"), - Messagebox::ALERT_ICON); + msg_box.show(Exception(trUtf8("Not all objects were pasted to the model due to errors returned during the process! Refer to error stack for more details!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__, errors), + QString(), + Messagebox::ALERT_ICON); } if(!ModelWidget::cut_operation) @@ -2626,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); @@ -2765,7 +2786,7 @@ void ModelWidget::removeObjects(bool cascade) //If the object is as FK relationship remove the foreign keys that generates it if(obj_type==BASE_RELATIONSHIP) { - rel=dynamic_cast(object); + /*rel=dynamic_cast(object); if(rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_FK) { aux_table=dynamic_cast
(rel->getTable(BaseRelationship::DST_TABLE)); @@ -2794,6 +2815,24 @@ void ModelWidget::removeObjects(bool cascade) } constrs.pop_back(); } + }*/ + + rel = dynamic_cast(object); + + if(rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_FK) + { + tab_obj=rel->getReferenceForeignKey(); + obj_id=tab_obj->getObjectId(); + + if(objs_map.count(obj_id)==0) + { + objs_map[tab_obj->getObjectId()]=std::make_tuple(tab_obj, + tab_obj->getName(true), + tab_obj->getObjectType(), + tab_obj->getParentTable()->getName(true), + tab_obj->getParentTable()->getObjectType()); + + } } } else if(objs_map.count(obj_id)==0) @@ -2833,7 +2872,7 @@ void ModelWidget::removeObjects(bool cascade) else if(parent_type!=OBJ_DATABASE) { /* If the parent table does not exist on the model of the object to be removed - does not exists in parent table, it'll not be processed */ + does not exists in parent table, it'll not be processed */ table=dynamic_cast(db_model->getObject(parent_name, parent_type)); if(!table || (table && table->getObjectIndex(obj_name, obj_type) < 0)) continue; @@ -2894,10 +2933,10 @@ void ModelWidget::removeObjects(bool cascade) catch(Exception &e) { if(cascade && (e.getErrorType()==ERR_INVALIDATED_OBJECTS || - e.getErrorType()==ERR_REM_DIRECT_REFERENCE || - e.getErrorType()==ERR_REM_INDIRECT_REFERENCE || - e.getErrorType()==ERR_REM_PROTECTED_OBJECT || - e.getErrorType()==ERR_OPR_RESERVED_OBJECT)) + e.getErrorType()==ERR_REM_DIRECT_REFERENCE || + e.getErrorType()==ERR_REM_INDIRECT_REFERENCE || + e.getErrorType()==ERR_REM_PROTECTED_OBJECT || + e.getErrorType()==ERR_OPR_RESERVED_OBJECT)) errors.push_back(e); else throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); @@ -2924,10 +2963,10 @@ void ModelWidget::removeObjects(bool cascade) catch(Exception &e) { if(cascade && (e.getErrorType()==ERR_INVALIDATED_OBJECTS || - e.getErrorType()==ERR_REM_DIRECT_REFERENCE || - e.getErrorType()==ERR_REM_INDIRECT_REFERENCE || - e.getErrorType()==ERR_REM_PROTECTED_OBJECT || - e.getErrorType()==ERR_OPR_RESERVED_OBJECT)) + e.getErrorType()==ERR_REM_DIRECT_REFERENCE || + e.getErrorType()==ERR_REM_INDIRECT_REFERENCE || + e.getErrorType()==ERR_REM_PROTECTED_OBJECT || + e.getErrorType()==ERR_OPR_RESERVED_OBJECT)) errors.push_back(e); else throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); @@ -3103,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]); @@ -3116,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]); @@ -3258,7 +3303,7 @@ void ModelWidget::configureFadeMenu(void) fade_out_menu.addAction(action); } else - { + { action_fade_in->setMenu(nullptr); action_fade_out->setMenu(nullptr); } @@ -3298,13 +3343,40 @@ void ModelWidget::configureFadeMenu(void) } } +void ModelWidget::fadeObjects(const vector &objects, bool fade_in) +{ + BaseObjectView *obj_view = nullptr; + + for(auto obj : objects) + { + if(!BaseGraphicObject::isGraphicObject(obj->getObjectType())) + continue; + + obj_view = dynamic_cast(dynamic_cast(obj)->getReceiverObject()); + + if(obj_view) + { + dynamic_cast(obj)->setFadedOut(!fade_in); + + obj_view->setOpacity(fade_in ? 1 : min_object_opacity); + + //If the minimum opacity is zero the object hidden + obj_view->setVisible(fade_in || (!fade_in && min_object_opacity > 0)); + + this->modified = true; + } + } + + scene->clearSelection(); +} + void ModelWidget::fadeObjects(QAction *action, bool fade_in) { if(!action) return; vector list; - BaseObjectView *obj_view = nullptr; + //BaseObjectView *obj_view = nullptr; //If the database object is selected or there is no object select if(selected_objects.empty() || (selected_objects.size() == 1 && selected_objects[0]->getObjectType() == OBJ_DATABASE)) @@ -3358,7 +3430,7 @@ void ModelWidget::fadeObjects(QAction *action, bool fade_in) } } - for(auto obj : list) + /*for(auto obj : list) { obj_view = dynamic_cast(dynamic_cast(obj)->getReceiverObject()); @@ -3373,8 +3445,9 @@ void ModelWidget::fadeObjects(QAction *action, bool fade_in) this->modified = true; } - } + } */ + fadeObjects(list, fade_in); scene->clearSelection(); } @@ -3396,7 +3469,6 @@ void ModelWidget::toggleExtendedAttributes(void) if(selected_objects.empty() || (selected_objects.size() == 1 && selected_objects[0] == db_model)) { - objects.assign(db_model->getObjectList(OBJ_TABLE)->begin(), db_model->getObjectList(OBJ_TABLE)->end()); objects.insert(objects.end(), db_model->getObjectList(OBJ_VIEW)->begin(), db_model->getObjectList(OBJ_VIEW)->end()); } @@ -3414,6 +3486,26 @@ void ModelWidget::toggleExtendedAttributes(void) } } + db_model->setObjectsModified({ OBJ_SCHEMA }); + this->setModified(true); +} + +void ModelWidget::toggleSchemasRectangles(void) +{ + bool visible = sender() == action_show_schemas_rects; + Schema *schema = nullptr; + + for(auto obj : *db_model->getObjectList(OBJ_SCHEMA)) + { + schema = dynamic_cast(obj); + + if(schema && schema->isRectVisible() != visible) + { + schema->setRectVisible(visible); + schema->setModified(true); + } + } + this->setModified(true); } @@ -3442,7 +3534,7 @@ void ModelWidget::updateObjectsOpacity(void) } } -void ModelWidget::configurePopupMenu(vector objects) +void ModelWidget::configurePopupMenu(const vector &objects) { QMenu *submenu=nullptr; Table *table=nullptr; @@ -3475,10 +3567,7 @@ void ModelWidget::configurePopupMenu(vector objects) //Configures the "New object" menu with the types at database level for(i=0; i < cnt; i++) - { - //actions_new_objects[types[i]]->setShortcut(QKeySequence(shortcuts[i])); new_object_menu.addAction(actions_new_objects[types[i]]); - } action_new_object->setMenu(&new_object_menu); popup_menu.addAction(action_new_object); @@ -3505,15 +3594,7 @@ void ModelWidget::configurePopupMenu(vector objects) { BaseObject *obj=objects[0]; BaseRelationship *rel=dynamic_cast(obj); - ObjectType obj_type=obj->getObjectType(), - types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_INDEX, - OBJ_RULE, OBJ_TRIGGER }, - sch_types[]={ OBJ_AGGREGATE, OBJ_COLLATION, OBJ_CONVERSION, - OBJ_DOMAIN, OBJ_EXTENSION, OBJ_FUNCTION, OBJ_OPCLASS, - OBJ_OPERATOR, OBJ_OPFAMILY, OBJ_SEQUENCE, OBJ_TABLE, - OBJ_TYPE, OBJ_VIEW }; - unsigned tab_tp_cnt=sizeof(types)/sizeof(ObjectType), - sch_tp_cnt=sizeof(sch_types)/sizeof(ObjectType); + ObjectType obj_type=obj->getObjectType(); configureSubmenu(obj); popup_menu.addAction(action_edit); @@ -3525,23 +3606,21 @@ void ModelWidget::configurePopupMenu(vector objects) { if(obj_type==OBJ_TABLE || obj_type == OBJ_VIEW) { - for(i=0; i < tab_tp_cnt; i++) - { - if(obj_type == OBJ_VIEW && (types[i] == OBJ_COLUMN || types[i] == OBJ_CONSTRAINT)) - continue; + for(auto type : BaseObject::getChildObjectTypes(obj_type)) + new_object_menu.addAction(actions_new_objects[type]); + + if(obj_type==OBJ_TABLE) + new_object_menu.addAction(actions_new_objects[OBJ_RELATIONSHIP]); - new_object_menu.addAction(actions_new_objects[types[i]]); - } action_new_object->setMenu(&new_object_menu); popup_menu.insertAction(action_quick_actions, action_new_object); } else if(obj_type==OBJ_RELATIONSHIP || obj_type==BASE_RELATIONSHIP) { - if(obj_type==OBJ_RELATIONSHIP) { - for(i=0; i < 2; i++) - new_object_menu.addAction(actions_new_objects[types[i]]); + new_object_menu.addAction(actions_new_objects[OBJ_COLUMN]); + new_object_menu.addAction(actions_new_objects[OBJ_CONSTRAINT]); action_new_object->setMenu(&new_object_menu); popup_menu.insertAction(action_quick_actions, action_new_object); @@ -3580,8 +3659,8 @@ void ModelWidget::configurePopupMenu(vector objects) } else if(obj_type == OBJ_SCHEMA) { - for(i=0; i < sch_tp_cnt; i++) - new_object_menu.addAction(actions_new_objects[sch_types[i]]); + for(auto type : BaseObject::getChildObjectTypes(OBJ_SCHEMA)) + new_object_menu.addAction(actions_new_objects[type]); action_new_object->setMenu(&new_object_menu); popup_menu.insertAction(action_quick_actions, action_new_object); @@ -3601,8 +3680,8 @@ void ModelWidget::configurePopupMenu(vector objects) is mainly used when the user wants to find a graphical object from the ModelObjects dockwidget*/ if((sender()!=this && sender()!=scene) && dynamic_cast(obj)) { - popup_menu.addAction(action_highlight_object); - action_highlight_object->setData(QVariant::fromValue(obj)); + popup_menu.addAction(action_select_object); + action_select_object->setData(QVariant::fromValue(obj)); } action_edit->setData(QVariant::fromValue(obj)); @@ -3667,7 +3746,7 @@ void ModelWidget::configurePopupMenu(vector objects) (!tab_obj || (tab_obj && !tab_obj->getParentTable()->isProtected() && !tab_obj->isAddedByRelationship()))) { /* Special case for systema objects: The actions protect/unprotect will be displayed only for - system schemas. The rest of system objects those actions aren't available */ + system schemas. The rest of system objects those actions aren't available */ if(!objects[0]->isSystemObject() || (objects[0]->isSystemObject() && objects[0]->getObjectType()==OBJ_SCHEMA)) { @@ -3698,6 +3777,9 @@ void ModelWidget::configurePopupMenu(vector objects) if(tab_or_view || objects.empty() || objects.size() == 1) popup_menu.addAction(action_extended_attribs); + + if(objects.empty() || (objects.size() == 1 && objects[0]->getObjectType() == OBJ_DATABASE)) + popup_menu.addAction(action_schemas_rects); } if(!tab_obj && @@ -4148,7 +4230,7 @@ void ModelWidget::removeRelationshipPoints(void) } } -void ModelWidget::rearrangeSchemas(QPointF origin, unsigned tabs_per_row, unsigned sch_per_row, double obj_spacing) +void ModelWidget::rearrangeSchemasInGrid(QPointF origin, unsigned tabs_per_row, unsigned sch_per_row, double obj_spacing) { vector *objects=nullptr; Schema *schema=nullptr; @@ -4173,7 +4255,7 @@ void ModelWidget::rearrangeSchemas(QPointF origin, unsigned tabs_per_row, unsign if(sch_view && sch_view->getChildrenCount() > 0) { //Organizing the tables inside the schema - rearrangeTables(schema, QPointF(x,y), tabs_per_row, obj_spacing); + rearrangeTablesInGrid(schema, QPointF(x,y), tabs_per_row, obj_spacing); schema->setModified(true); cy=sch_view->pos().y() + sch_view->boundingRect().height(); @@ -4215,7 +4297,7 @@ void ModelWidget::rearrangeSchemas(QPointF origin, unsigned tabs_per_row, unsign this->adjustSceneSize(); } -void ModelWidget::rearrangeTables(Schema *schema, QPointF origin, unsigned tabs_per_row, double obj_spacing) +void ModelWidget::rearrangeTablesInGrid(Schema *schema, QPointF origin, unsigned tabs_per_row, double obj_spacing) { if(schema) { @@ -4295,7 +4377,7 @@ void ModelWidget::jumpToTable(void) viewport->centerOn(tab_view); } -void ModelWidget::rearrangeObjects(void) +void ModelWidget::rearrangeTablesHierarchically(void) { vector objects; BaseGraphicObject *graph_obj = nullptr; @@ -4394,7 +4476,7 @@ void ModelWidget::rearrangeObjects(void) objects.assign(not_linked_tabs.begin(), not_linked_tabs.end()); objects.insert(objects.end(), db_model->getObjectList(OBJ_TEXTBOX)->begin(), db_model->getObjectList(OBJ_TEXTBOX)->end()); - px = 100; + px = 50; py = items_rect.bottom() + 100; max_h = 0; @@ -4409,7 +4491,7 @@ void ModelWidget::rearrangeObjects(void) if(px > max_w) { - px = 100; + px = 50; py += max_h + 100; } } @@ -4435,7 +4517,7 @@ void ModelWidget::rearrangeObjects(void) else { //This is a fallback arrangement when the model does not have relationships - rearrangeSchemas(QPointF(50,50), 10, 5, 50); + rearrangeSchemasInGrid(QPointF(50, 50), 10, 5, 50); } adjustSceneSize(); @@ -4484,7 +4566,7 @@ QRectF ModelWidget::rearrangeTablesHierarchically(BaseTableView *root, vectorpos().x() + (tab_view->boundingRect().width() * 1.50); - py = root->pos().y() + 25; + py = root->pos().y() + 75; for(auto &next_tab : next_tabs) { @@ -4502,7 +4584,7 @@ QRectF ModelWidget::rearrangeTablesHierarchically(BaseTableView *root, vectorsetPos(QPointF(px, py)); next_tab->setProtected(is_protected); - py += tab_view->boundingRect().height() + 50; + py += tab_view->boundingRect().height() + 75; px += 50; } @@ -4517,6 +4599,226 @@ QRectF ModelWidget::rearrangeTablesHierarchically(BaseTableView *root, vectorpos(), QPointF(px1, py1))); } +void ModelWidget::rearrangeTablesInSchema(Schema *schema, QPointF start) +{ + vector tables, views; + + if(!schema) return; + + tables = db_model->getObjects(OBJ_TABLE, schema); + views = db_model->getObjects(OBJ_VIEW, schema); + tables.insert(tables.end(), views.begin(), views.end()); + + if(!tables.empty()) + { + BaseTable *base_tab = nullptr; + BaseTableView *tab_view = nullptr, *comp_tab = nullptr, *curr_tab = nullptr; + + //If there two or less tables we put them side-by-side + if(tables.size() <= 2) + { + base_tab = dynamic_cast(tables[0]); + curr_tab = dynamic_cast(base_tab->getReceiverObject()); + curr_tab->setPos(start); + + if(tables.size() > 1) + { + tab_view = curr_tab; + base_tab = dynamic_cast(tables[1]); + curr_tab = dynamic_cast(base_tab->getReceiverObject()); + curr_tab->setPos(start + QPointF(tab_view->boundingRect().width() * 1.25, 0)); + } + } + else + { + double max_w = 0, max_h = 0; + bool has_collision = false; + QRectF curr_brect, comp_brect, irect; + QPointF pos; + random_device rand_seed; + default_random_engine rand_num_engine; + unsigned tries = 0; + + rand_num_engine.seed(rand_seed()); + + /* Calculating the maximum width and height + * The new tables' positions are calculated using these dimensions */ + for(auto &tab : tables) + { + base_tab = dynamic_cast(tab); + curr_tab = dynamic_cast(base_tab->getReceiverObject()); + max_w += curr_tab->boundingRect().width(); + max_h += curr_tab->boundingRect().height(); + } + + if(tables.size() >= 4) + { + max_w *= 0.50f; + max_h *= 0.50f; + } + else + { + max_w *= 1.15f; + max_h *= 1.15f; + } + + uniform_int_distribution dist_x(start.x(), start.x() + max_w), + dist_y(start.y(), start.y() + max_h); + + //Doing the first random positioning on all tables + for(auto &tab : tables) + { + base_tab = dynamic_cast(tab); + curr_tab = dynamic_cast(base_tab->getReceiverObject()); + pos.setX(dist_x(rand_num_engine)); + pos.setY(dist_y(rand_num_engine)); + curr_tab->setPos(pos); + } + + /* Collision detection: If a table collides with other tables it'll then repositioned + * until no interception is detected */ + for(auto &tab : tables) + { + base_tab = dynamic_cast(tab); + curr_tab = dynamic_cast(base_tab->getReceiverObject()); + curr_brect = QRectF(curr_tab->pos(), curr_tab->boundingRect().size()); + tries = 0; + + do + { + has_collision = false; + + for(auto &tab1 : tables) + { + if(tab == tab1) + continue; + + base_tab = dynamic_cast(tab1); + comp_tab = dynamic_cast(base_tab->getReceiverObject()); + comp_brect = QRectF(comp_tab->pos(), comp_tab->boundingRect().size()); + irect = comp_brect.intersected(curr_brect); + + if(irect.isValid()) + { + has_collision = true; + pos.setX(dist_x(rand_num_engine)); + pos.setY(dist_y(rand_num_engine)); + curr_tab->setPos(pos); + curr_brect = QRectF(curr_tab->pos(), curr_tab->boundingRect().size()); + break; + } + } + + tries++; + } + while(has_collision && tries < (tables.size() * 100)); + } + } + + schema->setRectVisible(true); + schema->setModified(true); + } +} + +void ModelWidget::rearrangeTablesInSchemas(void) +{ + BaseRelationship *base_rel = nullptr; + Schema *schema = nullptr; + SchemaView *sch_view = nullptr, *sch_view_aux = nullptr; + QRectF curr_brect, comp_brect, irect; + random_device rand_seed; + default_random_engine rand_num_engine; + double max_w = 1000, max_h = 1000; + vector schemas = *db_model->getObjectList(OBJ_SCHEMA), rels; + bool has_collision = false; + uniform_int_distribution dist_x(0, max_w), dist_y(0, max_h); + unsigned tries = 0, + max_tries = (db_model->getObjectCount(OBJ_TABLE) + + db_model->getObjectCount(OBJ_VIEW) + + db_model->getObjectCount(OBJ_SCHEMA)) * 100; + + + rand_num_engine.seed(rand_seed()); + + /* Rearraging tables inside schemas and determining the maximum width and height by summing + * all schemas widths and heights. These values will be serve as the maximum + * position limit for the schemas */ + for(auto &sch : schemas) + { + schema = dynamic_cast(sch); + sch_view = dynamic_cast(schema->getReceiverObject()); + + if(!sch_view) continue; + + rearrangeTablesInSchema(schema, QPointF(dist_x(rand_num_engine), dist_y(rand_num_engine))); + + max_w += sch_view->boundingRect().width(); + max_h += sch_view->boundingRect().height(); + } + + uniform_int_distribution::param_type new_dx(0, max_w * 0.40); + dist_x.param(new_dx); + + uniform_int_distribution::param_type new_dy(0, max_h * 0.40); + dist_y.param(new_dy); + + /* Collision detection: If a schema collides with other schemas it'll then repositioned + * until no interception is detected or the tries reached the max_tries value */ + for(auto &sch : schemas) + { + schema = dynamic_cast(sch); + sch_view = dynamic_cast(schema->getReceiverObject()); + tries = 0; + + if(!sch_view) continue; + + curr_brect = QRectF(sch_view->pos(), sch_view->boundingRect().size()); + + do + { + has_collision = false; + + for(auto &sch1 : schemas) + { + schema = dynamic_cast(sch1); + sch_view_aux = dynamic_cast(schema->getReceiverObject()); + + if(sch == sch1 || !sch_view_aux) + continue; + + comp_brect = QRectF(sch_view_aux->pos(), sch_view_aux->boundingRect().size()); + irect = comp_brect.intersected(curr_brect); + + if(irect.isValid()) + { + has_collision = true; + sch_view->moveTo(QPointF(dist_x(rand_num_engine), dist_y(rand_num_engine))); + curr_brect = QRectF(sch_view->pos(), sch_view->boundingRect().size()); + break; + } + } + + tries++; + } + while(has_collision && tries < max_tries); + } + + //Removing all custom points from relationships + rels.assign(db_model->getObjectList(OBJ_RELATIONSHIP)->begin(), db_model->getObjectList(OBJ_RELATIONSHIP)->end()); + rels.insert(rels.end(), db_model->getObjectList(BASE_RELATIONSHIP)->begin(), db_model->getObjectList(BASE_RELATIONSHIP)->end()); + + for(auto &rel : rels) + { + base_rel = dynamic_cast(rel); + base_rel->setPoints({}); + base_rel->resetLabelsDistance(); + } + + db_model->setObjectsModified({ OBJ_TABLE, OBJ_VIEW, OBJ_SCHEMA, OBJ_RELATIONSHIP, BASE_RELATIONSHIP }); + adjustSceneSize(); + viewport->updateScene({ scene->sceneRect() }); +} + void ModelWidget::updateMagnifierArea(void) { QPoint pos = viewport->mapFromGlobal(QCursor::pos()); @@ -4537,12 +4839,11 @@ void ModelWidget::updateMagnifierArea(void) magnifier_area_lbl->move(5, magnifier_area_lbl->geometry().top()); QPainter p(&pix); - p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); + p.setRenderHints(viewport->renderHints()); scene->blockSignals(true); scene->render(&p, QRectF(QPointF(0,0), size), QRectF(scene_pos - QPointF(cx, cy), size)); - p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing, false); p.setPen(QColor(80,0,0)); p.drawLine(QPointF(cx, cy - 10), QPointF(cx, cy + 10)); p.drawLine(QPointF(cx - 10, cy), QPointF(cx + 10, cy)); diff --git a/libpgmodeler_ui/src/modelwidget.h b/libpgmodeler_ui/src/modelwidget.h index 80c344bfd..375ff61fc 100644 --- a/libpgmodeler_ui/src/modelwidget.h +++ b/libpgmodeler_ui/src/modelwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -116,7 +116,9 @@ class ModelWidget: public QWidget { select_all_menu, - jump_to_tab_menu; + jump_to_tab_menu, + + toggle_sch_rects_menu; //! \brief Stores the selected object on the scene vector selected_objects; @@ -164,7 +166,7 @@ class ModelWidget: public QWidget { int openEditingForm(BaseObject *object, BaseObject *parent_obj, const QPointF &pos); //! \brief Configures the popup menu according the the selected objects list - void configurePopupMenu(vector objects=vector()); + void configurePopupMenu(const vector &objects=vector()); //! \brief Configures the submenu related to the object void configureSubmenu(BaseObject *object); @@ -182,6 +184,11 @@ class ModelWidget: public QWidget { This method returns the bounding rect of the items after the rearrangement */ QRectF rearrangeTablesHierarchically(BaseTableView *root, vector &evaluated_tabs); + /*! \brief Arrange tables inside the provided schema randomly (scattered). An start point should + * be provided. The method will avoid to put two or more tables in the same position causing + * overlaping. This method causes the schema rectangle to be enabled. */ + void rearrangeTablesInSchema(Schema *schema, QPointF start); + void updateMagnifierArea(void); void showMagnifierArea(bool show); @@ -212,7 +219,7 @@ class ModelWidget: public QWidget { *action_quick_actions, *action_sel_sch_children, *action_sel_tagged_tabs, - *action_highlight_object, + *action_select_object, *action_parent_rel, *action_append_sql, *action_create_seq_col, @@ -233,7 +240,10 @@ class ModelWidget: public QWidget { *action_show_ext_attribs, *action_hide_ext_attribs, *action_edit_creation_order, - *action_jump_to_table; + *action_jump_to_table, + *action_schemas_rects, + *action_show_schemas_rects, + *action_hide_schemas_rects; //! \brief Actions used to create new objects on the model map actions_new_objects; @@ -256,18 +266,16 @@ class ModelWidget: public QWidget { //! \brief Disables the model actions when some new object action is active void enableModelActions(bool value); - /*! \brief Reorganizes the schemas over the scene. The parameters are: an origin point, - number of tables per row, schemas per row and a object spacing */ - void rearrangeSchemas(QPointF origin, unsigned tabs_per_row, unsigned sch_per_row, double obj_spacing); - /*! \brief Reorganizes the tables of a specific schema over the scene. The parameter are: the schema in which the tables will be rearranged, an origin point, number of tables per row a object spacing */ - void rearrangeTables(Schema *schema, QPointF origin, unsigned tabs_per_row, double obj_spacing); + void rearrangeTablesInGrid(Schema *schema, QPointF origin, unsigned tabs_per_row, double obj_spacing); + + void fadeObjects(const vector &objects, bool fade_in); public: static constexpr double MINIMUM_ZOOM=0.050000, - MAXIMUM_ZOOM=4.000001, + MAXIMUM_ZOOM=5.000001, ZOOM_INCREMENT=0.050000; ModelWidget(QWidget *parent = 0); @@ -333,7 +341,14 @@ class ModelWidget: public QWidget { /*! \brief Rearrange table/view/textboxes in the canvas in such way to provide better visualization * of the whole model. Currently only hierachical arrangement is possible. See rearrangeTablesHierarchically() */ - void rearrangeObjects(void); + void rearrangeTablesHierarchically(void); + + /*! \brief Reorganizes the schemas over the scene in a grid form. The parameters are: an origin point, + number of tables per row, schemas per row and a object spacing */ + void rearrangeSchemasInGrid(QPointF origin = QPointF(50, 50), unsigned tabs_per_row = 5, unsigned sch_per_row = 3, double obj_spacing = 50); + + //! \brief Arrange all tables it their schemas randomly (scattered) + void rearrangeTablesInSchemas(void); void emitSceneInteracted(void); @@ -455,6 +470,8 @@ class ModelWidget: public QWidget { void toggleExtendedAttributes(void); + void toggleSchemasRectangles(void); + void editCreationOrder(void); void jumpToTable(void); diff --git a/libpgmodeler_ui/src/newobjectoverlaywidget.cpp b/libpgmodeler_ui/src/newobjectoverlaywidget.cpp index 8f43aef99..9435231c6 100644 --- a/libpgmodeler_ui/src/newobjectoverlaywidget.cpp +++ b/libpgmodeler_ui/src/newobjectoverlaywidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -55,6 +55,7 @@ NewObjectOverlayWidget::NewObjectOverlayWidget(ModelWidget *parent): QWidget(par { column_tb, std::make_tuple(trUtf8("C"), OBJ_COLUMN) }, { rule_tb, std::make_tuple(trUtf8("V"), OBJ_RULE) }, { trigger_tb, std::make_tuple(trUtf8("B"), OBJ_TRIGGER) }, + { policy_tb, std::make_tuple(trUtf8("9"), OBJ_POLICY) }, { genericsql_tb, std::make_tuple(trUtf8("8"), OBJ_GENERIC_SQL) } }; map> rel_shortcuts={ { rel11_tb, std::make_tuple(trUtf8("1"), 0) }, @@ -122,8 +123,8 @@ void NewObjectOverlayWidget::setSelectedObjects(vector &sel_objs) rule_tb->setVisible(obj_type==OBJ_TABLE || obj_type==OBJ_VIEW); trigger_tb->setVisible(obj_type==OBJ_TABLE || obj_type==OBJ_VIEW); tab_perms_tb->setVisible(obj_type==OBJ_TABLE || obj_type==OBJ_VIEW); - rel_btns_wgt->setVisible(sel_objs.size()==2 && - sel_objs.at(0)->getObjectType()==OBJ_TABLE && sel_objs.at(1)->getObjectType()==OBJ_TABLE); + rel_btns_wgt->setVisible((sel_objs.size()==1 && sel_objs.at(0)->getObjectType()==OBJ_TABLE) || + (sel_objs.size()==2 && sel_objs.at(0)->getObjectType()==OBJ_TABLE && sel_objs.at(1)->getObjectType()==OBJ_TABLE)); overlay_frm->adjustSize(); this->adjustSize(); diff --git a/libpgmodeler_ui/src/newobjectoverlaywidget.h b/libpgmodeler_ui/src/newobjectoverlaywidget.h index 88a60b50a..eeec324a6 100644 --- a/libpgmodeler_ui/src/newobjectoverlaywidget.h +++ b/libpgmodeler_ui/src/newobjectoverlaywidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/numberedtexteditor.cpp b/libpgmodeler_ui/src/numberedtexteditor.cpp index 1af28338c..56fec138c 100644 --- a/libpgmodeler_ui/src/numberedtexteditor.cpp +++ b/libpgmodeler_ui/src/numberedtexteditor.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -42,7 +42,7 @@ NumberedTextEditor::NumberedTextEditor(QWidget * parent, bool handle_ext_files) if(handle_ext_files) { QPalette pal; - QHBoxLayout *hbox = new QHBoxLayout; + QHBoxLayout *hbox = new QHBoxLayout, *hbox1 = new QHBoxLayout; QFont font = this->font(); font.setPointSizeF(font.pointSizeF() * 0.95f); @@ -56,13 +56,31 @@ NumberedTextEditor::NumberedTextEditor(QWidget * parent, bool handle_ext_files) top_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); hbox->setContentsMargins(2,2,2,2); + hbox1->setContentsMargins(0,0,0,0); + + QLabel *ico = new QLabel(this); + msg_lbl = new QLabel(this); + msg_lbl->setTextInteractionFlags(Qt::TextSelectableByMouse); + + ico->setMaximumSize(22,22); + ico->setPixmap(QPixmap(PgModelerUiNS::getIconPath("msgbox_alerta"))); + ico->setScaledContents(true); + + editor_alert_wgt = new QWidget(this); + editor_alert_wgt->setFont(font); + hbox1->addWidget(ico); + hbox1->addWidget(msg_lbl); + editor_alert_wgt->setLayout(hbox1); + editor_alert_wgt->setVisible(false); + + hbox->addWidget(editor_alert_wgt); hbox->addSpacerItem(new QSpacerItem(10,10, QSizePolicy::Expanding)); load_file_btn = new QToolButton(top_widget); load_file_btn->setIcon(QPixmap(PgModelerUiNS::getIconPath("abrir"))); load_file_btn->setIconSize(QSize(16,16)); load_file_btn->setAutoRaise(true); - load_file_btn->setText(trUtf8("Load file")); + load_file_btn->setText(trUtf8("Load")); load_file_btn->setToolTip(trUtf8("Load the object's source code from an external file")); load_file_btn->setFont(font); load_file_btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -73,7 +91,7 @@ NumberedTextEditor::NumberedTextEditor(QWidget * parent, bool handle_ext_files) edit_src_btn->setIcon(QPixmap(PgModelerUiNS::getIconPath("editar"))); edit_src_btn->setIconSize(QSize(16,16)); edit_src_btn->setAutoRaise(true); - edit_src_btn->setText(trUtf8("Edit source")); + edit_src_btn->setText(trUtf8("Edit")); edit_src_btn->setToolTip(trUtf8("Edit the source code in the preferred external editor")); edit_src_btn->setFont(font); edit_src_btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -121,6 +139,7 @@ NumberedTextEditor::~NumberedTextEditor(void) disconnect(&src_editor_proc, nullptr, this, nullptr); src_editor_proc.terminate(); src_editor_proc.waitForFinished(); + QFile(tmp_src_file.fileName()).remove(); } } @@ -338,15 +357,6 @@ void NumberedTextEditor::loadFile(void) void NumberedTextEditor::editSource(void) { - //If the editor process is already running we block a second try to start the editor process - if(src_editor_proc.state() != QProcess::NotRunning) - { - Messagebox msg_box; - msg_box.show(PgModelerUiNS::formatMessage(trUtf8("The source code is currently being edited in the application `%1' (pid: %2)! Only one instance of the source code editor application is allowed.") - .arg(src_editor_proc.program()).arg(src_editor_proc.processId())), Messagebox::ALERT_ICON); - return; - } - QByteArray buffer; QFile input; @@ -368,12 +378,30 @@ void NumberedTextEditor::editSource(void) src_editor_proc.setProgram(NumberedTextEditor::src_editor_app); src_editor_proc.setArguments({ src_editor_app_args, tmp_src_file.fileName() }); src_editor_proc.start(); + + src_editor_proc.waitForStarted(); + if(src_editor_proc.state() == QProcess::Running) + { + msg_lbl->setText(PgModelerUiNS::formatMessage(trUtf8("The source editor `%1' is running on `pid: %2'.") + .arg(src_editor_proc.program()).arg(src_editor_proc.processId()))); + editor_alert_wgt->setVisible(true); + load_file_btn->setEnabled(false); + edit_src_btn->setEnabled(false); + clear_btn->setEnabled(false); + this->setReadOnly(true); + } } void NumberedTextEditor::updateSource(void) { QFile input(tmp_src_file.fileName()); + editor_alert_wgt->setVisible(false); + load_file_btn->setEnabled(true); + edit_src_btn->setEnabled(true); + clear_btn->setEnabled(!this->toPlainText().isEmpty()); + this->setReadOnly(false); + if(!input.open(QFile::ReadOnly)) throw Exception(Exception::getErrorMessage(ERR_FILE_DIR_NOT_ACCESSED) .arg(tmp_src_file.fileName()) diff --git a/libpgmodeler_ui/src/numberedtexteditor.h b/libpgmodeler_ui/src/numberedtexteditor.h index 18c4743a1..168d12846 100644 --- a/libpgmodeler_ui/src/numberedtexteditor.h +++ b/libpgmodeler_ui/src/numberedtexteditor.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -31,6 +31,7 @@ based upon the code editor example provided by Qt #include #include #include +#include #include "linenumberswidget.h" class NumberedTextEditor : public QPlainTextEdit { @@ -62,7 +63,11 @@ class NumberedTextEditor : public QPlainTextEdit { //! \brief Indicates if the text editor can handle external files bool handle_ext_files; - QWidget *top_widget; + QWidget *top_widget, + + *editor_alert_wgt; + + QLabel *msg_lbl; QToolButton *load_file_btn, *edit_src_btn, *clear_btn; diff --git a/libpgmodeler_ui/src/objectdepsrefswidget.cpp b/libpgmodeler_ui/src/objectdepsrefswidget.cpp index bf0a12f1c..01e834b5a 100644 --- a/libpgmodeler_ui/src/objectdepsrefswidget.cpp +++ b/libpgmodeler_ui/src/objectdepsrefswidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -74,19 +74,6 @@ void ObjectDepsRefsWidget::clearTables(void) references_tbw->setRowCount(0); } -void ObjectDepsRefsWidget::hideEvent(QHideEvent *event) -{ - tabWidget->setCurrentIndex(0); - model_wgt=nullptr; - references_tbw->setEnabled(true); - dependences_tbw->setEnabled(true); - exc_ind_deps_chk->setEnabled(true); - alert_frm->setVisible(false); - - clearTables(); - BaseObjectWidget::hideEvent(event); -} - void ObjectDepsRefsWidget::updateObjectTables(void) { vector objs; @@ -97,6 +84,7 @@ 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 diff --git a/libpgmodeler_ui/src/objectdepsrefswidget.h b/libpgmodeler_ui/src/objectdepsrefswidget.h index 923ae67b9..36aa66960 100644 --- a/libpgmodeler_ui/src/objectdepsrefswidget.h +++ b/libpgmodeler_ui/src/objectdepsrefswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -32,9 +32,9 @@ class ObjectDepsRefsWidget: public BaseObjectWidget, public Ui::ObjectDepsRefsWidget { private: Q_OBJECT + ModelWidget *model_wgt; - void hideEvent(QHideEvent *event); void setAttributes(DatabaseModel *model, BaseObject *object, BaseObject *parent_obj); public: diff --git a/libpgmodeler_ui/src/objectfinderwidget.cpp b/libpgmodeler_ui/src/objectfinderwidget.cpp index 283963c8f..5c2c22877 100644 --- a/libpgmodeler_ui/src/objectfinderwidget.cpp +++ b/libpgmodeler_ui/src/objectfinderwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,13 +27,20 @@ ObjectFinderWidget::ObjectFinderWidget(QWidget *parent) : QWidget(parent) splitter->handle(1)->setEnabled(false); updateObjectTypeList(obj_types_lst); + select_menu.addAction(trUtf8("Listed"), this, SLOT(selectObjects())); + select_menu.addAction(trUtf8("Not listed"), this, SLOT(selectObjects())); + select_btn->setMenu(&select_menu); + + fade_menu.addAction(trUtf8("Listed"), this, SLOT(fadeObjects())); + fade_menu.addAction(trUtf8("Not listed"), this, SLOT(fadeObjects())); + fade_btn->setMenu(&fade_menu); + connect(filter_btn, SIGNAL(toggled(bool)), filter_frm, SLOT(setVisible(bool))); connect(filter_btn, &QToolButton::toggled, [&](){ splitter->setSizes({0, 1000}); splitter->handle(1)->setEnabled(filter_btn->isChecked()); }); - connect(find_btn, SIGNAL(clicked(bool)), this, SLOT(findObjects(void))); connect(hide_tb, SIGNAL(clicked(void)), this, SLOT(hide(void))); connect(result_tbw, SIGNAL(itemPressed(QTableWidgetItem*)), this, SLOT(selectObject(void))); @@ -41,6 +48,7 @@ ObjectFinderWidget::ObjectFinderWidget(QWidget *parent) : QWidget(parent) connect(clear_res_btn, SIGNAL(clicked(void)), this, SLOT(clearResult(void))); connect(select_all_btn, SIGNAL(clicked(void)), this, SLOT(setAllObjectsChecked(void))); connect(clear_all_btn, SIGNAL(clicked(void)), this, SLOT(setAllObjectsChecked(void))); + this->setModel(nullptr); pattern_edt->installEventFilter(this); } @@ -83,8 +91,95 @@ void ObjectFinderWidget::resizeEvent(QResizeEvent *event) filter_btn->setToolButtonStyle(style); find_btn->setToolButtonStyle(style); clear_res_btn->setToolButtonStyle(style); - highlight_btn->setToolButtonStyle(style); + select_btn->setToolButtonStyle(style); + fade_btn->setToolButtonStyle(style); + } +} + +void ObjectFinderWidget::fadeObjects(void) +{ + if(!model_wgt) + return; + + vector objects, other_objs; + bool fade_listed = false; + + for(auto obj_type : {OBJ_TABLE, OBJ_VIEW, OBJ_TEXTBOX, OBJ_RELATIONSHIP, BASE_RELATIONSHIP, OBJ_SCHEMA}) + { + objects.insert(objects.end(), + model_wgt->getDatabaseModel()->getObjectList(obj_type)->begin(), + model_wgt->getDatabaseModel()->getObjectList(obj_type)->end()); + } + + model_wgt->fadeObjects(objects, true); + + if(!fade_menu.actions().contains(qobject_cast(sender()))) + return; + + fade_listed = qobject_cast(sender()) == fade_menu.actions().at(0); + + std::sort(objects.begin(), objects.end()); + std::sort(found_objs.begin(), found_objs.end()); + std::set_difference(objects.begin(), objects.end(), found_objs.begin(), found_objs.end(), + std::inserter(other_objs, other_objs.begin())); + + model_wgt->fadeObjects(found_objs, fade_listed); + model_wgt->fadeObjects(other_objs, !fade_listed); +} + +void ObjectFinderWidget::selectObjects(void) +{ + if(!model_wgt) + return; + + vector objects, other_objs; + BaseObjectView *obj_view = nullptr; + BaseGraphicObject *graph_obj = nullptr; + bool sel_listed = false; + + for(auto obj_type : {OBJ_TABLE, OBJ_VIEW, OBJ_TEXTBOX, OBJ_RELATIONSHIP, BASE_RELATIONSHIP, OBJ_SCHEMA}) + { + objects.insert(objects.end(), + model_wgt->getDatabaseModel()->getObjectList(obj_type)->begin(), + model_wgt->getDatabaseModel()->getObjectList(obj_type)->end()); + } + + model_wgt->scene->blockSignals(true); + fadeObjects(); + model_wgt->scene->blockSignals(false); + + sel_listed = qobject_cast(sender()) == select_menu.actions().at(0); + + std::sort(objects.begin(), objects.end()); + std::sort(found_objs.begin(), found_objs.end()); + std::set_difference(objects.begin(), objects.end(), found_objs.begin(), found_objs.end(), + std::inserter(other_objs, other_objs.begin())); + + objects.clear(); + + if(sel_listed) + objects.assign(found_objs.begin(), found_objs.end()); + else + objects.assign(other_objs.begin(), other_objs.end()); + + for(auto &obj : objects) + { + graph_obj = dynamic_cast(obj); + + if(graph_obj) + { + obj_view = dynamic_cast(graph_obj->getReceiverObject()); + + if(obj_view) + { + obj_view->blockSignals(true); + obj_view->setSelected(true); + obj_view->blockSignals(false); + } + } } + + model_wgt->configureObjectSelection(); } void ObjectFinderWidget::setModel(ModelWidget *model_wgt) @@ -99,25 +194,27 @@ void ObjectFinderWidget::setModel(ModelWidget *model_wgt) pattern_lbl->setEnabled(enable); find_btn->setEnabled(enable); result_tbw->setEnabled(enable); - highlight_btn->setEnabled(enable); } void ObjectFinderWidget::clearResult(void) { selected_obj=nullptr; + found_objs.clear(); result_tbw->clearContents(); result_tbw->setRowCount(0); found_lbl->setVisible(false); clear_res_btn->setEnabled(false); + + select_btn->setEnabled(false); + fade_btn->setEnabled(false); } void ObjectFinderWidget::findObjects(void) { if(model_wgt) { - vector objs; vector types; clearResult(); @@ -130,24 +227,27 @@ void ObjectFinderWidget::findObjects(void) } //Search the objects on model - objs=model_wgt->getDatabaseModel()->findObjects(pattern_edt->text(), types, true, + found_objs=model_wgt->getDatabaseModel()->findObjects(pattern_edt->text(), types, true, case_sensitive_chk->isChecked(), regexp_chk->isChecked(), exact_match_chk->isChecked()); //Show the found objects on the result table - updateObjectTable(result_tbw, objs); + updateObjectTable(result_tbw, found_objs); found_lbl->setVisible(true); //Show a message indicating the number of found objects - if(!objs.empty()) + if(!found_objs.empty()) { - found_lbl->setText(trUtf8("Found %1 object(s).").arg(objs.size())); + found_lbl->setText(trUtf8("Found %1 object(s).").arg(found_objs.size())); result_tbw->resizeColumnsToContents(); result_tbw->horizontalHeader()->setStretchLastSection(true); } else found_lbl->setText(trUtf8("No objects found.")); - clear_res_btn->setEnabled(!objs.empty()); + clear_res_btn->setEnabled(!found_objs.empty()); + select_btn->setEnabled(!found_objs.empty()); + fade_btn->setEnabled(!found_objs.empty()); + fadeObjects(); } } @@ -167,8 +267,7 @@ void ObjectFinderWidget::selectObject(void) if(tab_obj && !graph_obj) graph_obj=dynamic_cast(tab_obj->getParentTable()); - //Highlight the graphical object when the 'highlight' button is checked - if(graph_obj && highlight_btn->isChecked()) + if(graph_obj) { BaseObjectView *obj=dynamic_cast(graph_obj->getReceiverObject()); model_wgt->scene->clearSelection(); diff --git a/libpgmodeler_ui/src/objectfinderwidget.h b/libpgmodeler_ui/src/objectfinderwidget.h index 3f9de590a..c0d6154df 100644 --- a/libpgmodeler_ui/src/objectfinderwidget.h +++ b/libpgmodeler_ui/src/objectfinderwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,6 +34,10 @@ class ObjectFinderWidget : public QWidget, public Ui::ObjectFinderWidget { private: Q_OBJECT + vector found_objs; + + QMenu select_menu, fade_menu; + //! \brief Reference model widget ModelWidget *model_wgt; @@ -44,6 +48,7 @@ class ObjectFinderWidget : public QWidget, public Ui::ObjectFinderWidget { bool eventFilter(QObject *object, QEvent *event); void showEvent(QShowEvent *); + void resizeEvent(QResizeEvent *event); public: @@ -75,7 +80,10 @@ class ObjectFinderWidget : public QWidget, public Ui::ObjectFinderWidget { void selectObject(void); void setAllObjectsChecked(void); - + + void fadeObjects(void); + + void selectObjects(void); }; #endif diff --git a/libpgmodeler_ui/src/objectrenamewidget.cpp b/libpgmodeler_ui/src/objectrenamewidget.cpp index e6594c968..ea92d20a6 100644 --- a/libpgmodeler_ui/src/objectrenamewidget.cpp +++ b/libpgmodeler_ui/src/objectrenamewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/objectrenamewidget.h b/libpgmodeler_ui/src/objectrenamewidget.h index b252f2520..5de5aa33b 100644 --- a/libpgmodeler_ui/src/objectrenamewidget.h +++ b/libpgmodeler_ui/src/objectrenamewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/objectsdiffinfo.cpp b/libpgmodeler_ui/src/objectsdiffinfo.cpp index 950604b66..d27beaf9f 100644 --- a/libpgmodeler_ui/src/objectsdiffinfo.cpp +++ b/libpgmodeler_ui/src/objectsdiffinfo.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/objectsdiffinfo.h b/libpgmodeler_ui/src/objectsdiffinfo.h index 08c74fa67..1e28a13ea 100644 --- a/libpgmodeler_ui/src/objectsdiffinfo.h +++ b/libpgmodeler_ui/src/objectsdiffinfo.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/objectselectorwidget.cpp b/libpgmodeler_ui/src/objectselectorwidget.cpp index 1570293cb..1d40df118 100644 --- a/libpgmodeler_ui/src/objectselectorwidget.cpp +++ b/libpgmodeler_ui/src/objectselectorwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -83,10 +83,15 @@ void ObjectSelectorWidget::configureSelector(bool install_highlighter) bool ObjectSelectorWidget::eventFilter(QObject *obj, QEvent *evnt) { if(this->isEnabled() && evnt->type()==QEvent::FocusIn && - QApplication::mouseButtons()==Qt::LeftButton && obj==obj_name_txt) + QApplication::mouseButtons()==Qt::LeftButton && obj==obj_name_txt) { - showObjectView(); - return(true); + QFocusEvent *focus_evnt = dynamic_cast(evnt); + + if(focus_evnt->reason() == Qt::MouseFocusReason) + { + showObjectView(); + return(true); + } } return(QWidget::eventFilter(obj, evnt)); diff --git a/libpgmodeler_ui/src/objectselectorwidget.h b/libpgmodeler_ui/src/objectselectorwidget.h index 334beb1bf..2ea94b041 100644 --- a/libpgmodeler_ui/src/objectselectorwidget.h +++ b/libpgmodeler_ui/src/objectselectorwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/objecttablewidget.cpp b/libpgmodeler_ui/src/objectstablewidget.cpp similarity index 85% rename from libpgmodeler_ui/src/objecttablewidget.cpp rename to libpgmodeler_ui/src/objectstablewidget.cpp index 66e5dc148..4b59c4ca8 100644 --- a/libpgmodeler_ui/src/objecttablewidget.cpp +++ b/libpgmodeler_ui/src/objectstablewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -16,9 +16,9 @@ # Also, you can get the complete GNU General Public License at */ -#include "objecttablewidget.h" +#include "objectstablewidget.h" -ObjectTableWidget::ObjectTableWidget(unsigned button_conf, bool conf_exclusion, QWidget *parent): QWidget(parent) +ObjectsTableWidget::ObjectsTableWidget(unsigned button_conf, bool conf_exclusion, QWidget *parent): QWidget(parent) { setupUi(this); connect(move_down_tb, SIGNAL(clicked(bool)), this, SLOT(moveRows(void))); @@ -58,7 +58,7 @@ ObjectTableWidget::ObjectTableWidget(unsigned button_conf, bool conf_exclusion, move_down_tb->setToolTip(move_down_tb->toolTip() + QString(" (%1)").arg(move_down_tb->shortcut().toString())); } -void ObjectTableWidget::setButtonConfiguration(unsigned button_conf) +void ObjectsTableWidget::setButtonConfiguration(unsigned button_conf) { bool move_btn = false; @@ -92,7 +92,7 @@ void ObjectTableWidget::setButtonConfiguration(unsigned button_conf) } } -QTableWidgetItem *ObjectTableWidget::getItem(unsigned row_idx, unsigned col_idx) +QTableWidgetItem *ObjectsTableWidget::getItem(unsigned row_idx, unsigned col_idx) { if(row_idx >= static_cast(table_tbw->rowCount())) throw Exception(ERR_REF_LIN_OBJTAB_INV_INDEX,__PRETTY_FUNCTION__,__FILE__,__LINE__); @@ -103,13 +103,13 @@ QTableWidgetItem *ObjectTableWidget::getItem(unsigned row_idx, unsigned col_idx) return(table_tbw->item(row_idx, col_idx)); } -void ObjectTableWidget::adjustColumnToContents(int col) +void ObjectsTableWidget::adjustColumnToContents(int col) { table_tbw->resizeColumnToContents(col); table_tbw->resizeRowsToContents(); } -void ObjectTableWidget::setColumnCount(unsigned col_count) +void ObjectsTableWidget::setColumnCount(unsigned col_count) { if(col_count > 0) { @@ -128,7 +128,7 @@ void ObjectTableWidget::setColumnCount(unsigned col_count) } } -void ObjectTableWidget::setHeaderLabel(const QString &label, unsigned col_idx) +void ObjectsTableWidget::setHeaderLabel(const QString &label, unsigned col_idx) { QTableWidgetItem *item=nullptr; @@ -139,7 +139,7 @@ void ObjectTableWidget::setHeaderLabel(const QString &label, unsigned col_idx) item->setText(label); } -void ObjectTableWidget::setHeaderIcon(const QIcon &icon, unsigned col_idx) +void ObjectsTableWidget::setHeaderIcon(const QIcon &icon, unsigned col_idx) { QTableWidgetItem *item=nullptr; @@ -150,17 +150,17 @@ void ObjectTableWidget::setHeaderIcon(const QIcon &icon, unsigned col_idx) item->setIcon(icon); } -void ObjectTableWidget::setCellIcon(const QIcon &icon, unsigned row_idx, unsigned col_idx) +void ObjectsTableWidget::setCellIcon(const QIcon &icon, unsigned row_idx, unsigned col_idx) { getItem(row_idx, col_idx)->setIcon(icon); } -void ObjectTableWidget::setCellText(const QString &text, unsigned row_idx, unsigned col_idx) +void ObjectsTableWidget::setCellText(const QString &text, unsigned row_idx, unsigned col_idx) { getItem(row_idx, col_idx)->setText(text); } -void ObjectTableWidget::clearCellText(unsigned row_idx, unsigned col_idx) +void ObjectsTableWidget::clearCellText(unsigned row_idx, unsigned col_idx) { try { @@ -172,7 +172,7 @@ void ObjectTableWidget::clearCellText(unsigned row_idx, unsigned col_idx) } } -void ObjectTableWidget::setRowFont(int row_idx, const QFont &font, const QColor &fg_color, const QColor &bg_color) +void ObjectsTableWidget::setRowFont(int row_idx, const QFont &font, const QColor &fg_color, const QColor &bg_color) { QTableWidgetItem *item=nullptr; int col_count, i; @@ -190,7 +190,7 @@ void ObjectTableWidget::setRowFont(int row_idx, const QFont &font, const QColor } } -void ObjectTableWidget::setRowData(const QVariant &data, unsigned row_idx) +void ObjectsTableWidget::setRowData(const QVariant &data, unsigned row_idx) { QTableWidgetItem *item=nullptr; @@ -202,17 +202,17 @@ void ObjectTableWidget::setRowData(const QVariant &data, unsigned row_idx) item->setData(Qt::UserRole, data); } -unsigned ObjectTableWidget::getColumnCount(void) +unsigned ObjectsTableWidget::getColumnCount(void) { return(table_tbw->columnCount()); } -unsigned ObjectTableWidget::getRowCount(void) +unsigned ObjectsTableWidget::getRowCount(void) { return(table_tbw->rowCount()); } -QString ObjectTableWidget::getHeaderLabel(unsigned col_idx) +QString ObjectsTableWidget::getHeaderLabel(unsigned col_idx) { QTableWidgetItem *item=nullptr; @@ -223,22 +223,22 @@ QString ObjectTableWidget::getHeaderLabel(unsigned col_idx) return(item->text()); } -QString ObjectTableWidget::getCellText(unsigned row_idx, unsigned col_idx) +QString ObjectsTableWidget::getCellText(unsigned row_idx, unsigned col_idx) { return(getItem(row_idx, col_idx)->text()); } -Qt::CheckState ObjectTableWidget::getCellCheckState(unsigned row_idx, unsigned col_idx) +Qt::CheckState ObjectsTableWidget::getCellCheckState(unsigned row_idx, unsigned col_idx) { return(getItem(row_idx, col_idx)->checkState()); } -void ObjectTableWidget::setCellCheckState(unsigned row_idx, unsigned col_idx, Qt::CheckState check_state) +void ObjectsTableWidget::setCellCheckState(unsigned row_idx, unsigned col_idx, Qt::CheckState check_state) { getItem(row_idx, col_idx)->setCheckState(check_state); } -void ObjectTableWidget::setCellDisabled(unsigned row_idx, unsigned col_idx, bool disabled) +void ObjectsTableWidget::setCellDisabled(unsigned row_idx, unsigned col_idx, bool disabled) { QTableWidgetItem *item = getItem(row_idx, col_idx); @@ -248,12 +248,12 @@ void ObjectTableWidget::setCellDisabled(unsigned row_idx, unsigned col_idx, bool item->setFlags(Qt::ItemIsEnabled); } -bool ObjectTableWidget::isCellDisabled(unsigned row_idx, unsigned col_idx) +bool ObjectsTableWidget::isCellDisabled(unsigned row_idx, unsigned col_idx) { return(getItem(row_idx, col_idx)->flags() == Qt::NoItemFlags); } -QVariant ObjectTableWidget::getRowData(unsigned row_idx) +QVariant ObjectsTableWidget::getRowData(unsigned row_idx) { QTableWidgetItem *item=nullptr; @@ -264,12 +264,12 @@ QVariant ObjectTableWidget::getRowData(unsigned row_idx) return(item->data(Qt::UserRole)); } -int ObjectTableWidget::getSelectedRow(void) +int ObjectsTableWidget::getSelectedRow(void) { return(table_tbw->currentRow()); } -int ObjectTableWidget::getRowIndex(const QVariant &data) +int ObjectsTableWidget::getRowIndex(const QVariant &data) { unsigned i, count; QTableWidgetItem *item=nullptr; @@ -291,7 +291,7 @@ int ObjectTableWidget::getRowIndex(const QVariant &data) return(i); } -void ObjectTableWidget::addColumn(unsigned col_idx) +void ObjectsTableWidget::addColumn(unsigned col_idx) { if(col_idx >= static_cast(table_tbw->columnCount())) col_idx=table_tbw->columnCount(); @@ -303,7 +303,7 @@ void ObjectTableWidget::addColumn(unsigned col_idx) emit s_columnAdded(col_idx); } -void ObjectTableWidget::selectRow(int lin_idx) +void ObjectsTableWidget::selectRow(int lin_idx) { QTableWidgetItem *item=nullptr; @@ -318,7 +318,7 @@ void ObjectTableWidget::selectRow(int lin_idx) } } -void ObjectTableWidget::addRow(unsigned lin_idx) +void ObjectsTableWidget::addRow(unsigned lin_idx) { QTableWidgetItem *item=nullptr; unsigned col_idx, col_cont=table_tbw->columnCount(); @@ -340,7 +340,7 @@ void ObjectTableWidget::addRow(unsigned lin_idx) table_tbw->setCurrentItem(item); } -void ObjectTableWidget::addRow(void) +void ObjectsTableWidget::addRow(void) { this->addRow(table_tbw->rowCount()); setButtonsEnabled(); @@ -349,7 +349,7 @@ void ObjectTableWidget::addRow(void) emit s_rowAdded(table_tbw->rowCount()-1); } -void ObjectTableWidget::removeRow(unsigned row_idx) +void ObjectsTableWidget::removeRow(unsigned row_idx) { unsigned i, count; bool conf; @@ -374,7 +374,7 @@ void ObjectTableWidget::removeRow(unsigned row_idx) conf_exclusion=conf; } -void ObjectTableWidget::removeRow(void) +void ObjectsTableWidget::removeRow(void) { if(table_tbw->currentRow()>=0) { @@ -401,7 +401,7 @@ void ObjectTableWidget::removeRow(void) } } -void ObjectTableWidget::duplicateRow(void) +void ObjectsTableWidget::duplicateRow(void) { if(table_tbw->currentRow() >= 0) { @@ -424,7 +424,7 @@ void ObjectTableWidget::duplicateRow(void) } } -void ObjectTableWidget::removeRows(void) +void ObjectsTableWidget::removeRows(void) { if(table_tbw->rowCount() > 0) { @@ -448,7 +448,7 @@ void ObjectTableWidget::removeRows(void) } } -void ObjectTableWidget::removeColumn(unsigned col_idx) +void ObjectsTableWidget::removeColumn(unsigned col_idx) { if(col_idx >= static_cast(table_tbw->columnCount())) throw Exception(ERR_REF_COL_OBJTAB_INV_INDEX,__PRETTY_FUNCTION__,__FILE__,__LINE__); @@ -460,7 +460,7 @@ void ObjectTableWidget::removeColumn(unsigned col_idx) emit s_columnRemoved(col_idx); } -void ObjectTableWidget::moveRows(void) +void ObjectsTableWidget::moveRows(void) { QObject *sender_obj=sender(); QTableWidgetItem *item=nullptr, *item1=nullptr; @@ -545,24 +545,24 @@ void ObjectTableWidget::moveRows(void) } } -void ObjectTableWidget::editRow(void) +void ObjectsTableWidget::editRow(void) { emit s_rowEdited(table_tbw->currentRow()); } -void ObjectTableWidget::updateRow(void) +void ObjectsTableWidget::updateRow(void) { emit s_rowUpdated(table_tbw->currentRow()); } -void ObjectTableWidget::clearSelection(void) +void ObjectsTableWidget::clearSelection(void) { table_tbw->clearSelection(); table_tbw->setCurrentItem(nullptr); setButtonsEnabled(); } -void ObjectTableWidget::setButtonsEnabled(unsigned button_conf, bool value) +void ObjectsTableWidget::setButtonsEnabled(unsigned button_conf, bool value) { int lin=-1; QTableWidgetItem *item=table_tbw->currentItem(); @@ -597,12 +597,12 @@ void ObjectTableWidget::setButtonsEnabled(unsigned button_conf, bool value) duplicate_tb->setEnabled(value && lin >= 0); } -void ObjectTableWidget::setButtonsEnabled(void) +void ObjectsTableWidget::setButtonsEnabled(void) { setButtonsEnabled(ALL_BUTTONS, true); } -void ObjectTableWidget::emitRowSelected(void) +void ObjectsTableWidget::emitRowSelected(void) { QTableWidgetItem *item=table_tbw->currentItem(); @@ -610,7 +610,7 @@ void ObjectTableWidget::emitRowSelected(void) emit s_rowSelected(item->row()); } -void ObjectTableWidget::resizeEvent(QResizeEvent *) +void ObjectsTableWidget::resizeEvent(QResizeEvent *) { table_tbw->resizeRowsToContents(); } diff --git a/libpgmodeler_ui/src/objecttablewidget.h b/libpgmodeler_ui/src/objectstablewidget.h similarity index 95% rename from libpgmodeler_ui/src/objecttablewidget.h rename to libpgmodeler_ui/src/objectstablewidget.h index cf8aab106..a68a0feb0 100644 --- a/libpgmodeler_ui/src/objecttablewidget.h +++ b/libpgmodeler_ui/src/objectstablewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -18,7 +18,7 @@ /** \ingroup libpgmodeler_ui -\class ObjectTableWidget +\class ObjectsTableWidget \brief Implements a basic table (grid) which can be used commonly to store objects references and show information about them on it's rows. This class also implements operations to handle insertion/deletion/update/movements @@ -28,11 +28,11 @@ of rows on the table. #ifndef OBJECT_TABLE_WIDGET_H #define OBJECT_TABLE_WIDGET_H -#include "ui_objecttablewidget.h" +#include "ui_objectstablewidget.h" #include "messagebox.h" #include "baseobjectwidget.h" -class ObjectTableWidget: public QWidget, public Ui::ObjectTableWidget { +class ObjectsTableWidget: public QWidget, public Ui::ObjectsTableWidget { private: Q_OBJECT @@ -54,7 +54,7 @@ class ObjectTableWidget: public QWidget, public Ui::ObjectTableWidget { ALL_BUTTONS=127, NO_BUTTONS=0; - ObjectTableWidget(unsigned button_conf=ALL_BUTTONS, bool conf_exclusion=false, QWidget * parent = 0); + ObjectsTableWidget(unsigned button_conf=ALL_BUTTONS, bool conf_exclusion=false, QWidget * parent = 0); //! \brief Sets the table's column count void setColumnCount(unsigned col_count); diff --git a/libpgmodeler_ui/src/operationlistwidget.cpp b/libpgmodeler_ui/src/operationlistwidget.cpp index b3c582dcb..6cee4a8ad 100644 --- a/libpgmodeler_ui/src/operationlistwidget.cpp +++ b/libpgmodeler_ui/src/operationlistwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/operationlistwidget.h b/libpgmodeler_ui/src/operationlistwidget.h index 3dc17b27c..1647ed265 100644 --- a/libpgmodeler_ui/src/operationlistwidget.h +++ b/libpgmodeler_ui/src/operationlistwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/operatorclasswidget.cpp b/libpgmodeler_ui/src/operatorclasswidget.cpp index 66ab8c771..4c4404cba 100644 --- a/libpgmodeler_ui/src/operatorclasswidget.cpp +++ b/libpgmodeler_ui/src/operatorclasswidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,7 +36,7 @@ OperatorClassWidget::OperatorClassWidget(QWidget *parent): BaseObjectWidget(pare elem_family_sel=new ObjectSelectorWidget(OBJ_OPFAMILY, true, this); function_sel=new ObjectSelectorWidget(OBJ_FUNCTION, true, this); storage_type=new PgSQLTypeWidget(this, trUtf8("Storage Type")); - elements_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ ObjectTableWidget::DUPLICATE_BUTTON, true, this); + elements_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ ObjectsTableWidget::DUPLICATE_BUTTON, true, this); elements_tab->setColumnCount(4); elements_tab->setHeaderLabel(trUtf8("Object"),0); @@ -98,16 +98,6 @@ OperatorClassWidget::OperatorClassWidget(QWidget *parent): BaseObjectWidget(pare } } -void OperatorClassWidget::hideEvent(QHideEvent *event) -{ - function_sel->clearSelector(); - operator_sel->clearSelector(); - stg_num_sb->setValue(1); - elements_tab->removeRows(); - selectElementType(0); - BaseObjectWidget::hideEvent(event); -} - void OperatorClassWidget::selectElementType(int elem_type) { unsigned sel_idx=static_cast(elem_type); diff --git a/libpgmodeler_ui/src/operatorclasswidget.h b/libpgmodeler_ui/src/operatorclasswidget.h index 3aff4ec6a..6314db2e3 100644 --- a/libpgmodeler_ui/src/operatorclasswidget.h +++ b/libpgmodeler_ui/src/operatorclasswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -28,7 +28,7 @@ #include "baseobjectwidget.h" #include "ui_operatorclasswidget.h" #include "pgsqltypewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" /* Declaring the OperatorClassElement class as a Qt metatype in order to permit that instances of the class be used as data of QVariant and QMetaType */ @@ -49,9 +49,7 @@ class OperatorClassWidget: public BaseObjectWidget, public Ui::OperatorClassWidg *storage_type; //! \brief Stores the elements of operator class - ObjectTableWidget *elements_tab; - - void hideEvent(QHideEvent *event); + ObjectsTableWidget *elements_tab; public: OperatorClassWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/operatorfamilywidget.cpp b/libpgmodeler_ui/src/operatorfamilywidget.cpp index b0496786f..527600869 100644 --- a/libpgmodeler_ui/src/operatorfamilywidget.cpp +++ b/libpgmodeler_ui/src/operatorfamilywidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -42,13 +42,7 @@ OperatorFamilyWidget::OperatorFamilyWidget(QWidget *parent): BaseObjectWidget(pa opfamily_grid->addWidget(frame, opfamily_grid->count()+1, 0, 1, 5); configureTabOrder(); - setMinimumSize(500, 250); -} - -void OperatorFamilyWidget::hideEvent(QHideEvent *event) -{ - indexing_cmb->setCurrentIndex(0); - BaseObjectWidget::hideEvent(event); + setMinimumSize(500, 290); } void OperatorFamilyWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, OperatorFamily *op_family) diff --git a/libpgmodeler_ui/src/operatorfamilywidget.h b/libpgmodeler_ui/src/operatorfamilywidget.h index 960256ce5..f435da965 100644 --- a/libpgmodeler_ui/src/operatorfamilywidget.h +++ b/libpgmodeler_ui/src/operatorfamilywidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,9 +36,6 @@ class OperatorFamilyWidget: public BaseObjectWidget, public Ui::OperatorFamilyWi OperatorFamilyWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, OperatorFamily *op_family); - private slots: - void hideEvent(QHideEvent *event); - public slots: void applyConfiguration(void); }; diff --git a/libpgmodeler_ui/src/operatorwidget.cpp b/libpgmodeler_ui/src/operatorwidget.cpp index ac7a3776f..c0c8fbb21 100644 --- a/libpgmodeler_ui/src/operatorwidget.cpp +++ b/libpgmodeler_ui/src/operatorwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -78,23 +78,6 @@ OperatorWidget::OperatorWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_OP } } -void OperatorWidget::hideEvent(QHideEvent *event) -{ - unsigned i; - - hashes_chk->setChecked(false); - merges_chk->setChecked(false); - - for(i=Operator::FUNC_OPERATOR; i <= Operator::FUNC_RESTRICT; i++) - functions_sel[i]->clearSelector(); - - for(i=Operator::OPER_COMMUTATOR; i <= Operator::OPER_NEGATOR; i++) - operators_sel[i]->clearSelector(); - - attributes_twg->setCurrentIndex(0); - BaseObjectWidget::hideEvent(event); -} - void OperatorWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Operator *oper) { unsigned i; diff --git a/libpgmodeler_ui/src/operatorwidget.h b/libpgmodeler_ui/src/operatorwidget.h index 826cf6926..706a071e8 100644 --- a/libpgmodeler_ui/src/operatorwidget.h +++ b/libpgmodeler_ui/src/operatorwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -43,9 +43,6 @@ class OperatorWidget: public BaseObjectWidget, public Ui::OperatorWidget { void setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Operator *oper); - private slots: - void hideEvent(QHideEvent *event); - public slots: void applyConfiguration(void); }; diff --git a/libpgmodeler_ui/src/parameterwidget.cpp b/libpgmodeler_ui/src/parameterwidget.cpp index 8f9336d3c..6da42e340 100644 --- a/libpgmodeler_ui/src/parameterwidget.cpp +++ b/libpgmodeler_ui/src/parameterwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -61,14 +61,6 @@ void ParameterWidget::enableVariadic(void) !param_out_chk->isChecked()); } -void ParameterWidget::hideEvent(QHideEvent *event) -{ - param_in_chk->setChecked(false); - param_out_chk->setChecked(false); - default_value_edt->clear(); - BaseObjectWidget::hideEvent(event); -} - void ParameterWidget::setAttributes(Parameter param, DatabaseModel *model) { this->parameter=param; diff --git a/libpgmodeler_ui/src/parameterwidget.h b/libpgmodeler_ui/src/parameterwidget.h index 4c40290d3..24ff1037e 100644 --- a/libpgmodeler_ui/src/parameterwidget.h +++ b/libpgmodeler_ui/src/parameterwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,8 +36,6 @@ class ParameterWidget: public BaseObjectWidget, public Ui::ParameterWidget { PgSQLTypeWidget *data_type; Parameter parameter; - void hideEvent(QHideEvent *event); - public: ParameterWidget(QWidget * parent = 0); void setAttributes(Parameter parameter, DatabaseModel *model); diff --git a/libpgmodeler_ui/src/permissionwidget.cpp b/libpgmodeler_ui/src/permissionwidget.cpp index 2d48145b8..818b9666d 100644 --- a/libpgmodeler_ui/src/permissionwidget.cpp +++ b/libpgmodeler_ui/src/permissionwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -22,7 +22,6 @@ PermissionWidget::PermissionWidget(QWidget *parent): BaseObjectWidget(parent, OB { QGridLayout *grid=nullptr; QFrame *frame=nullptr; - QFont font; QCheckBox *check=nullptr; unsigned i; QString privs[]={ ParsersAttributes::SELECT_PRIV, ParsersAttributes::INSERT_PRIV, @@ -40,31 +39,27 @@ PermissionWidget::PermissionWidget(QWidget *parent): BaseObjectWidget(parent, OB object_selection_wgt=new ModelObjectsWidget(true); permission=nullptr; - comment_lbl->setText(trUtf8("Type:")); - font=name_edt->font(); - font.setItalic(true); - comment_edt->setFont(font); - comment_edt->setReadOnly(true); - name_edt->setFont(font); - name_edt->setReadOnly(true); - configureFormLayout(permission_grid, OBJ_PERMISSION); - roles_tab=new ObjectTableWidget(ObjectTableWidget::ADD_BUTTON | - ObjectTableWidget::REMOVE_BUTTON | - ObjectTableWidget::EDIT_BUTTON, false, this); + name_edt->setReadOnly(true); + comment_edt->setVisible(false); + comment_lbl->setVisible(false); + + roles_tab=new ObjectsTableWidget(ObjectsTableWidget::ADD_BUTTON | + ObjectsTableWidget::REMOVE_BUTTON | + ObjectsTableWidget::EDIT_BUTTON, false, this); roles_tab->setColumnCount(1); - roles_tab->setHeaderLabel(trUtf8("Role"),0); - roles_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("role")),0); + roles_tab->setHeaderLabel(trUtf8("Name"),0); + roles_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")),0); grid=new QGridLayout; grid->addWidget(roles_tab,0,0,1,1); grid->setContentsMargins(2,2,2,2); roles_gb->setLayout(grid); - permissions_tab=new ObjectTableWidget(ObjectTableWidget::REMOVE_BUTTON | - ObjectTableWidget::EDIT_BUTTON | - ObjectTableWidget::REMOVE_ALL_BUTTON, true, this); + permissions_tab=new ObjectsTableWidget(ObjectsTableWidget::REMOVE_BUTTON | + ObjectsTableWidget::EDIT_BUTTON | + ObjectsTableWidget::REMOVE_ALL_BUTTON, true, this); permissions_tab->setColumnCount(3); permissions_tab->setHeaderLabel(trUtf8("Id"),0); permissions_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")),0); @@ -93,7 +88,8 @@ PermissionWidget::PermissionWidget(QWidget *parent): BaseObjectWidget(parent, OB connect(check, SIGNAL(clicked(bool)), this, SLOT(checkPrivilege(void))); } - frame=generateInformationFrame(trUtf8("Leave the Roles empty to create a permission applicable to PUBLIC.")); + frame=generateInformationFrame(trUtf8("Leave the Roles grid empty in order to create a %1 applicable to PUBLIC.") + .arg(BaseObject::getTypeName(OBJ_PERMISSION).toLower())); permission_grid->addWidget(frame, permission_grid->count()+1, 0, 1, 0); frame->setParent(this); @@ -125,21 +121,6 @@ PermissionWidget::~PermissionWidget(void) delete(object_selection_wgt); } -void PermissionWidget::hideEvent(QHideEvent *event) -{ - disconnect(object_selection_wgt,0,this,0); - cancelOperation(); - - permissions_tab->blockSignals(true); - permissions_tab->removeRows(); - permissions_tab->blockSignals(false); - - if(perms_changed) - emit s_objectManipulated(); - - BaseObjectWidget::hideEvent(event); -} - void PermissionWidget::setAttributes(DatabaseModel *model, BaseObject *parent_obj, BaseObject *object) { BaseObjectWidget::setAttributes(model,object,parent_obj); @@ -157,8 +138,7 @@ void PermissionWidget::setAttributes(DatabaseModel *model, BaseObject *parent_ob connect(roles_tab, SIGNAL(s_rowAdded(int)), this, SLOT(selectRole(void))); connect(permissions_tab, SIGNAL(s_rowsRemoved(void)), this, SLOT(removePermissions(void))); - name_edt->setText(object->getName(true)); - comment_edt->setText(object->getTypeName()); + name_edt->setText(QString("%1 (%2)").arg(object->getSignature()).arg(object->getTypeName())); for(priv=Permission::PRIV_SELECT; priv<=Permission::PRIV_USAGE; priv++) { @@ -559,5 +539,8 @@ void PermissionWidget::updateCodePreview(void) void PermissionWidget::applyConfiguration(void) { + if(perms_changed) + emit s_objectManipulated(); + emit s_closeRequested(); } diff --git a/libpgmodeler_ui/src/permissionwidget.h b/libpgmodeler_ui/src/permissionwidget.h index bef0a4be2..deea3720c 100644 --- a/libpgmodeler_ui/src/permissionwidget.h +++ b/libpgmodeler_ui/src/permissionwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_permissionwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "modelobjectswidget.h" class PermissionWidget: public BaseObjectWidget, public Ui::PermissionWidget { @@ -40,7 +40,7 @@ class PermissionWidget: public BaseObjectWidget, public Ui::PermissionWidget { Permission *permission; //! \brief Table widget that stores the roles that has permission over the object - ObjectTableWidget *roles_tab, + ObjectsTableWidget *roles_tab, //! \brief Table widget that stores the permissions related to the object *permissions_tab; @@ -52,8 +52,6 @@ class PermissionWidget: public BaseObjectWidget, public Ui::PermissionWidget { emit the signal s_objectManipulated() */ bool perms_changed; - void hideEvent(QHideEvent *event); - public: PermissionWidget(QWidget * parent = 0); ~PermissionWidget(void); diff --git a/libpgmodeler_ui/src/pgmodelerplugin.cpp b/libpgmodeler_ui/src/pgmodelerplugin.cpp index 61b9d966a..8bc3eefad 100644 --- a/libpgmodeler_ui/src/pgmodelerplugin.cpp +++ b/libpgmodeler_ui/src/pgmodelerplugin.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/pgmodelerplugin.h b/libpgmodeler_ui/src/pgmodelerplugin.h index 41f4a5d65..0467cc71f 100644 --- a/libpgmodeler_ui/src/pgmodelerplugin.h +++ b/libpgmodeler_ui/src/pgmodelerplugin.h @@ -1,7 +1,7 @@ /* # Projeto: Modelador de Banco de Dados PostgreSQL (pgsqlDBM) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/pgmodeleruins.cpp b/libpgmodeler_ui/src/pgmodeleruins.cpp index 93eb2edba..b03c296c7 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; @@ -316,7 +318,7 @@ namespace PgModelerUiNS { if(curr_h > screen->size().height()) curr_h = screen->size().height() * 0.80; - widget->setMinimumSize(curr_w, curr_h); - widget->resize(widget->minimumSize()); + widget->setMinimumSize(widget->minimumSize()); + widget->resize(curr_w, curr_h); } } diff --git a/libpgmodeler_ui/src/pgmodeleruins.h b/libpgmodeler_ui/src/pgmodeleruins.h index 71cfbc0c4..523b738e0 100644 --- a/libpgmodeler_ui/src/pgmodeleruins.h +++ b/libpgmodeler_ui/src/pgmodeleruins.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/pgsqltypewidget.cpp b/libpgmodeler_ui/src/pgsqltypewidget.cpp index aa35824a4..6bd122972 100644 --- a/libpgmodeler_ui/src/pgsqltypewidget.cpp +++ b/libpgmodeler_ui/src/pgsqltypewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -195,6 +195,10 @@ void PgSQLTypeWidget::setAttributes(PgSQLType type, DatabaseModel *model, unsig idx=interval_cmb->findText(~(type.getIntervalType())); interval_cmb->setCurrentIndex(idx); + idx=spatial_cmb->findText(~(type.getSpatialType())); + if(idx < 0) idx = 0; + spatial_cmb->setCurrentIndex(idx); + timezone_chk->setChecked(type.isWithTimezone()); this->type=type; diff --git a/libpgmodeler_ui/src/pgsqltypewidget.h b/libpgmodeler_ui/src/pgsqltypewidget.h index 8b420c42a..f8933195d 100644 --- a/libpgmodeler_ui/src/pgsqltypewidget.h +++ b/libpgmodeler_ui/src/pgsqltypewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/plaintextitemdelegate.cpp b/libpgmodeler_ui/src/plaintextitemdelegate.cpp index d4090c1cc..63376a826 100644 --- a/libpgmodeler_ui/src/plaintextitemdelegate.cpp +++ b/libpgmodeler_ui/src/plaintextitemdelegate.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/plaintextitemdelegate.h b/libpgmodeler_ui/src/plaintextitemdelegate.h index af6cd3516..ddb50f7a9 100644 --- a/libpgmodeler_ui/src/plaintextitemdelegate.h +++ b/libpgmodeler_ui/src/plaintextitemdelegate.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/pluginsconfigwidget.cpp b/libpgmodeler_ui/src/pluginsconfigwidget.cpp index a1818a291..1288a10a5 100644 --- a/libpgmodeler_ui/src/pluginsconfigwidget.cpp +++ b/libpgmodeler_ui/src/pluginsconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ PluginsConfigWidget::PluginsConfigWidget(QWidget *parent) : BaseConfigWidget(par root_dir_edt->setText(dir.absolutePath()); - plugins_tab=new ObjectTableWidget(ObjectTableWidget::EDIT_BUTTON, false, this); + plugins_tab=new ObjectsTableWidget(ObjectsTableWidget::EDIT_BUTTON, false, this); plugins_tab->setColumnCount(3); plugins_tab->setHeaderLabel(trUtf8("Plugin"),0); plugins_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("plugins")),0); diff --git a/libpgmodeler_ui/src/pluginsconfigwidget.h b/libpgmodeler_ui/src/pluginsconfigwidget.h index c36dbd0e4..47982b275 100644 --- a/libpgmodeler_ui/src/pluginsconfigwidget.h +++ b/libpgmodeler_ui/src/pluginsconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseconfigwidget.h" #include "ui_pluginsconfigwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "pgmodelerplugin.h" class PluginsConfigWidget: public BaseConfigWidget, public Ui::PluginsConfigWidget { @@ -41,7 +41,7 @@ class PluginsConfigWidget: public BaseConfigWidget, public Ui::PluginsConfigWidg vector plugins_actions; //! \brief Table used to show the loaded plugins - ObjectTableWidget *plugins_tab; + ObjectsTableWidget *plugins_tab; /* Disabled methods */ void applyConfiguration(void){} diff --git a/libpgmodeler_ui/src/policywidget.cpp b/libpgmodeler_ui/src/policywidget.cpp new file mode 100644 index 000000000..201bd48b1 --- /dev/null +++ b/libpgmodeler_ui/src/policywidget.cpp @@ -0,0 +1,142 @@ +/* +# 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 "policywidget.h" + +PolicyWidget::PolicyWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_POLICY) +{ + try + { + Ui_PolicyWidget::setupUi(this); + + model_objs_wgt = new ModelObjectsWidget(true, this); + model_objs_wgt->setObjectVisible(OBJ_ROLE, true); + + check_edt = PgModelerUiNS::createNumberedTextEditor(check_wgt); + check_hl = new SyntaxHighlighter(check_edt); + check_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); + + using_edt = PgModelerUiNS::createNumberedTextEditor(using_wgt); + using_hl = new SyntaxHighlighter(using_edt); + using_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); + + roles_tab = new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::DUPLICATE_BUTTON | + ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::EDIT_BUTTON), true, this); + roles_tab->setColumnCount(1); + roles_tab->setHeaderLabel(trUtf8("Name"), 0); + roles_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")), 0); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(roles_tab); + + QFrame *frame=generateInformationFrame(trUtf8("Leave the Roles grid empty in order to create a %1 applicable to PUBLIC.") + .arg(BaseObject::getTypeName(OBJ_POLICY).toLower())); + vbox->addWidget(frame); + frame->setParent(this); + vbox->setContentsMargins(4,4,4,4); + attribs_tbw->widget(0)->setLayout(vbox); + + QStringList cmds; + PolicyCmdType::getTypes(cmds); + command_cmb->addItems(cmds); + + configureFormLayout(policy_grid, OBJ_POLICY); + + connect(roles_tab, SIGNAL(s_rowAdded(int)), model_objs_wgt, SLOT(show())); + connect(model_objs_wgt, SIGNAL(s_visibilityChanged(BaseObject*, bool)), this, SLOT(selectRole(BaseObject*, bool))); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} + +void PolicyWidget::setAttributes(DatabaseModel *model, OperationList *op_list, BaseObject *parent_obj, Policy *policy) +{ + if(!parent_obj) + throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + BaseObjectWidget::setAttributes(model, op_list, policy, parent_obj); + model_objs_wgt->setModel(model); + + if(policy) + { + command_cmb->setCurrentText(~policy->getPolicyCommand()); + permissive_chk->setChecked(policy->isPermissive()); + check_edt->setPlainText(policy->getCheckExpression()); + using_edt->setPlainText(policy->getUsingExpression()); + + roles_tab->blockSignals(true); + + for(auto role : policy->getRoles()) + { + roles_tab->addRow(); + roles_tab->setCellText(role->getName(), roles_tab->getRowCount() - 1, 0); + roles_tab->setRowData(QVariant::fromValue(reinterpret_cast(role)), roles_tab->getRowCount() - 1); + } + + roles_tab->blockSignals(false); + } +} + +void PolicyWidget::selectRole(BaseObject *role, bool show_wgt) +{ + if(!show_wgt) + { + if(!role) + roles_tab->removeRow(roles_tab->getRowCount() - 1); + else + { + roles_tab->setCellText(role->getName(), roles_tab->getRowCount() - 1, 0); + roles_tab->setRowData(QVariant::fromValue(reinterpret_cast(role)), roles_tab->getRowCount() - 1); + } + } +} + +void PolicyWidget::applyConfiguration(void) +{ + try + { + Policy *policy = nullptr; + unsigned count, i; + + startConfiguration(); + + policy =dynamic_cast(this->object); + policy->removeRoles(); + policy->setUsingExpression(using_edt->toPlainText()); + policy->setCheckExpression(check_edt->toPlainText()); + policy->setPermissive(permissive_chk->isChecked()); + policy->setPolicyCommand(command_cmb->currentText()); + + count=roles_tab->getRowCount(); + + for(i=0; i < count; i++) + policy->addRole(reinterpret_cast(roles_tab->getRowData(i).value())); + + BaseObjectWidget::applyConfiguration(); + finishConfiguration(); + } + catch(Exception &e) + { + cancelConfiguration(); + throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} diff --git a/libpgmodeler_ui/src/policywidget.h b/libpgmodeler_ui/src/policywidget.h new file mode 100644 index 000000000..b007a7476 --- /dev/null +++ b/libpgmodeler_ui/src/policywidget.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 +*/ + +#ifndef POLICY_WIDGET_H +#define POLICY_WIDGET_H + +#include +#include "baseobjectwidget.h" +#include "ui_policywidget.h" +#include "policy.h" +#include "objectstablewidget.h" +#include "modelobjectswidget.h" + +class PolicyWidget : public BaseObjectWidget, Ui::PolicyWidget { + private: + Q_OBJECT + + ModelObjectsWidget *model_objs_wgt; + + ObjectsTableWidget *roles_tab; + + SyntaxHighlighter *using_hl, *check_hl; + + NumberedTextEditor *using_edt, *check_edt; + + public: + PolicyWidget(QWidget *parent = 0); + + void setAttributes(DatabaseModel *model, OperationList *op_list, BaseObject *parent_obj, Policy *policy); + + public slots: + void applyConfiguration(void); + + private slots: + void selectRole(BaseObject *role, bool show_wgt); +}; + +#endif diff --git a/libpgmodeler_ui/src/relationshipconfigwidget.cpp b/libpgmodeler_ui/src/relationshipconfigwidget.cpp index df1425dc4..e869133b1 100644 --- a/libpgmodeler_ui/src/relationshipconfigwidget.cpp +++ b/libpgmodeler_ui/src/relationshipconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -45,10 +45,16 @@ RelationshipConfigWidget::RelationshipConfigWidget(QWidget * parent) : BaseConfi } fk_to_pk_ht=new HintTextWidget(fk_to_pk_hint, this); - fk_to_pk_ht->setText(fk_to_pk_chk->statusTip()); + fk_to_pk_ht->setText(fk_to_pk_rb->statusTip()); center_pnts_ht=new HintTextWidget(center_pnts_hint, this); - center_pnts_ht->setText(center_pnts_chk->statusTip()); + center_pnts_ht->setText(center_pnts_rb->statusTip()); + + tab_edges_ht=new HintTextWidget(tab_edges_hint, this); + tab_edges_ht->setText(tab_edges_rb->statusTip()); + + crows_foot_ht=new HintTextWidget(crows_foot_hint, this); + crows_foot_ht->setText(crows_foot_rb->statusTip()); DeferralType::getTypes(list); deferral_cmb->addItems(list); @@ -61,11 +67,10 @@ RelationshipConfigWidget::RelationshipConfigWidget(QWidget * parent) : BaseConfi for(int i=0; i < rel_types.size(); i++) rel_type_cmb->setItemData(i, rel_types[i]); - connect(fk_to_pk_chk, SIGNAL(toggled(bool)), conn_cnt_pnts_lbl, SLOT(setDisabled(bool))); - connect(fk_to_pk_chk, SIGNAL(toggled(bool)), this, SLOT(setConfigurationChanged(bool))); - - connect(center_pnts_chk, SIGNAL(toggled(bool)), conn_fk_pk_lbl, SLOT(setDisabled(bool))); - connect(center_pnts_chk, SIGNAL(toggled(bool)), this, SLOT(setConfigurationChanged(bool))); + connect(crows_foot_rb, SIGNAL(toggled(bool)), this, SLOT(enableConnModePreview(void))); + connect(fk_to_pk_rb, SIGNAL(toggled(bool)), this, SLOT(enableConnModePreview(void))); + connect(center_pnts_rb, SIGNAL(toggled(bool)), this, SLOT(enableConnModePreview(void))); + connect(tab_edges_rb, SIGNAL(toggled(bool)), this, SLOT(enableConnModePreview(void))); connect(deferrable_chk, SIGNAL(toggled(bool)), deferral_lbl, SLOT(setEnabled(bool))); connect(deferrable_chk, SIGNAL(toggled(bool)), deferral_cmb, SLOT(setEnabled(bool))); @@ -90,8 +95,10 @@ void RelationshipConfigWidget::loadConfiguration(void) vector key_attribs={ParsersAttributes::TYPE}; BaseConfigWidget::loadConfiguration(GlobalAttributes::RELATIONSHIPS_CONF, config_params, key_attribs); - fk_to_pk_chk->setChecked(config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]==ParsersAttributes::CONNECT_FK_TO_PK); - center_pnts_chk->setChecked(config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]==ParsersAttributes::CONNECT_CENTER_PNTS); + fk_to_pk_rb->setChecked(config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]==ParsersAttributes::CONNECT_FK_TO_PK); + center_pnts_rb->setChecked(config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]==ParsersAttributes::CONNECT_CENTER_PNTS); + tab_edges_rb->setChecked(config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]==ParsersAttributes::CONNECT_TABLE_EDGES); + crows_foot_rb->setChecked(config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]==ParsersAttributes::CROWS_FOOT); deferrable_chk->setChecked(config_params[ParsersAttributes::FOREIGN_KEYS][ParsersAttributes::DEFERRABLE]==ParsersAttributes::_TRUE_); deferral_cmb->setCurrentText(config_params[ParsersAttributes::FOREIGN_KEYS][ParsersAttributes::DEFER_TYPE]); @@ -133,7 +140,14 @@ void RelationshipConfigWidget::saveConfiguration(void) GlobalAttributes::SCHEMA_EXT; - config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]=(fk_to_pk_chk->isChecked() ? ParsersAttributes::CONNECT_FK_TO_PK : ParsersAttributes::CONNECT_CENTER_PNTS); + if(crows_foot_rb->isChecked()) + config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]=ParsersAttributes::CROWS_FOOT; + else if(fk_to_pk_rb->isChecked()) + config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]=ParsersAttributes::CONNECT_FK_TO_PK; + else if(tab_edges_rb->isChecked()) + config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]=ParsersAttributes::CONNECT_TABLE_EDGES; + else + config_params[ParsersAttributes::CONNECTION][ParsersAttributes::MODE]=ParsersAttributes::CONNECT_CENTER_PNTS; config_params[ParsersAttributes::FOREIGN_KEYS][ParsersAttributes::DEFERRABLE]=(deferrable_chk->isChecked() ? ParsersAttributes::_TRUE_ : ParsersAttributes::_FALSE_); config_params[ParsersAttributes::FOREIGN_KEYS][ParsersAttributes::DEFER_TYPE]=deferral_cmb->currentText(); @@ -160,17 +174,24 @@ void RelationshipConfigWidget::saveConfiguration(void) void RelationshipConfigWidget::applyConfiguration(void) { - if(fk_to_pk_chk->isChecked()) - RelationshipView::setLineConnectionMode(RelationshipView::CONNECT_FK_TO_PK); - else - RelationshipView::setLineConnectionMode(RelationshipView::CONNECT_CENTER_PNTS); + RelationshipView::setCrowsFoot(crows_foot_rb->isChecked()); + + if(!crows_foot_rb->isChecked()) + { + if(fk_to_pk_rb->isChecked()) + RelationshipView::setLineConnectionMode(RelationshipView::CONNECT_FK_TO_PK); + else if(tab_edges_rb->isChecked()) + RelationshipView::setLineConnectionMode(RelationshipView::CONNECT_TABLE_EGDES); + else + RelationshipView::setLineConnectionMode(RelationshipView::CONNECT_CENTER_PNTS); + } } void RelationshipConfigWidget::restoreDefaults(void) { try { - BaseConfigWidget::restoreDefaults(GlobalAttributes::RELATIONSHIPS_CONF); + BaseConfigWidget::restoreDefaults(GlobalAttributes::RELATIONSHIPS_CONF, false); this->loadConfiguration(); setConfigurationChanged(true); } @@ -240,6 +261,15 @@ void RelationshipConfigWidget::updatePattern(void) patterns[rel_type][inputs_map[input]]=input->toPlainText(); } +void RelationshipConfigWidget::enableConnModePreview(void) +{ + crows_foot_lbl->setEnabled(crows_foot_rb->isChecked()); + conn_cnt_pnts_lbl->setEnabled(center_pnts_rb->isChecked()); + conn_tab_edges_lbl->setEnabled(tab_edges_rb->isChecked()); + conn_fk_pk_lbl->setEnabled(fk_to_pk_rb->isChecked()); + setConfigurationChanged(true); +} + void RelationshipConfigWidget::hideEvent(QHideEvent *) { settings_twg->setCurrentIndex(0); diff --git a/libpgmodeler_ui/src/relationshipconfigwidget.h b/libpgmodeler_ui/src/relationshipconfigwidget.h index a6e9bd81c..cd87c9bac 100644 --- a/libpgmodeler_ui/src/relationshipconfigwidget.h +++ b/libpgmodeler_ui/src/relationshipconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -40,7 +40,7 @@ class RelationshipConfigWidget: public BaseConfigWidget, public Ui::Relationshi map patterns; - HintTextWidget *fk_to_pk_ht, *center_pnts_ht; + HintTextWidget *fk_to_pk_ht, *center_pnts_ht, *tab_edges_ht, *crows_foot_ht; void hideEvent(QHideEvent *); @@ -58,6 +58,7 @@ class RelationshipConfigWidget: public BaseConfigWidget, public Ui::Relationshi private slots: void fillNamePatterns(void); void updatePattern(void); + void enableConnModePreview(void); }; diff --git a/libpgmodeler_ui/src/relationshipwidget.cpp b/libpgmodeler_ui/src/relationshipwidget.cpp index 0f018e673..478dd38fa 100644 --- a/libpgmodeler_ui/src/relationshipwidget.cpp +++ b/libpgmodeler_ui/src/relationshipwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -65,15 +65,15 @@ RelationshipWidget::RelationshipWidget(QWidget *parent): BaseObjectWidget(parent GlobalAttributes::CONFIGURATION_EXT); } - attributes_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::UPDATE_BUTTON | - ObjectTableWidget::MOVE_BUTTONS), true, this); + attributes_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::MOVE_BUTTONS), true, this); - constraints_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::UPDATE_BUTTON | - ObjectTableWidget::MOVE_BUTTONS), true, this); + constraints_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::MOVE_BUTTONS), true, this); - advanced_objs_tab=new ObjectTableWidget(ObjectTableWidget::EDIT_BUTTON, true, this); + advanced_objs_tab=new ObjectsTableWidget(ObjectsTableWidget::EDIT_BUTTON, true, this); attributes_tab->setColumnCount(2); attributes_tab->setHeaderLabel(trUtf8("Attribute"), 0); @@ -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))); @@ -196,36 +200,6 @@ RelationshipWidget::RelationshipWidget(QWidget *parent): BaseObjectWidget(parent } } -void RelationshipWidget::hideEvent(QHideEvent *event) -{ - BaseRelationship *rel=dynamic_cast(this->object); - - custom_color_chk->setChecked(false); - identifier_chk->setChecked(false); - table1_mand_chk->setChecked(false); - table2_mand_chk->setChecked(false); - relnn_tab_name_edt->clear(); - deferrable_chk->setChecked(false); - deferral_cmb->setCurrentIndex(0); - rel_attribs_tbw->setCurrentIndex(0); - del_action_cmb->setCurrentIndex(0); - upd_action_cmb->setCurrentIndex(0); - - attributes_tab->blockSignals(true); - constraints_tab->blockSignals(true); - attributes_tab->removeRows(); - constraints_tab->removeRows(); - attributes_tab->blockSignals(false); - constraints_tab->blockSignals(false); - - rel_columns_lst->clear(); - - if(rel && !rel->isModified()) - this->cancelConfiguration(); - - BaseObjectWidget::hideEvent(event); -} - void RelationshipWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Table *src_tab, Table *dst_tab, unsigned rel_type) { Relationship *rel=nullptr; @@ -334,8 +308,8 @@ void RelationshipWidget::setAttributes(DatabaseModel *model, OperationList *op_l table2_mand_chk->setChecked(aux_rel->isTableMandatory(BaseRelationship::DST_TABLE)); identifier_chk->setChecked(aux_rel->isIdentifier()); relnn_tab_name_edt->setText(aux_rel->getTableNameRelNN()); - attributes_tab->setButtonsEnabled(ObjectTableWidget::ALL_BUTTONS, !aux_rel->isProtected()); - constraints_tab->setButtonsEnabled(ObjectTableWidget::ALL_BUTTONS, !aux_rel->isProtected()); + attributes_tab->setButtonsEnabled(ObjectsTableWidget::ALL_BUTTONS, !aux_rel->isProtected()); + constraints_tab->setButtonsEnabled(ObjectsTableWidget::ALL_BUTTONS, !aux_rel->isProtected()); //Lists the relationship attributes listObjects(OBJ_COLUMN); @@ -526,7 +500,7 @@ void RelationshipWidget::usePatternGlobalSettings(bool value) void RelationshipWidget::listObjects(ObjectType obj_type) { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; Relationship *rel=nullptr; unsigned count, i; @@ -551,7 +525,7 @@ void RelationshipWidget::listObjects(ObjectType obj_type) tab->clearSelection(); tab->blockSignals(false); - constraints_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, + constraints_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, attributes_tab->getRowCount() > 0); } catch(Exception &e) @@ -617,23 +591,18 @@ void RelationshipWidget::listAdvancedObjects(void) } else if(base_rel->getRelationshipType()==BaseRelationship::RELATIONSHIP_FK) { - tab=dynamic_cast
(base_rel->getTable(BaseRelationship::DST_TABLE)); - dynamic_cast
(base_rel->getTable(BaseRelationship::SRC_TABLE))->getForeignKeys(constrs,false,tab); + Constraint *fk = base_rel->getReferenceForeignKey(); - if(!base_rel->isSelfRelationship()) + if(fk) { - tab=dynamic_cast
(base_rel->getTable(BaseRelationship::SRC_TABLE)); - dynamic_cast
(base_rel->getTable(BaseRelationship::DST_TABLE))->getForeignKeys(constrs,false,tab); - } - - count=constrs.size(); + int row = 0; - for(i=0, i1=advanced_objs_tab->getRowCount(); i < count; i++, i1++) - { advanced_objs_tab->addRow(); - advanced_objs_tab->setCellText(constrs[i]->getName(),i1,0); - advanced_objs_tab->setCellText(constrs[i]->getTypeName(),i1,1); - advanced_objs_tab->setRowData(QVariant::fromValue(constrs[i]), i1); + row = advanced_objs_tab->getRowCount() - 1; + + advanced_objs_tab->setCellText(fk->getName(), row ,0); + advanced_objs_tab->setCellText(fk->getTypeName(), row, 1); + advanced_objs_tab->setRowData(QVariant::fromValue(fk), row); } } @@ -654,16 +623,28 @@ void RelationshipWidget::showAdvancedObject(int row) Constraint *constr=nullptr; Column *col=nullptr; ObjectType obj_type=object->getObjectType(); + bool is_protected = false; if(obj_type==OBJ_COLUMN) { col=dynamic_cast(object); + is_protected = col->isProtected(); openEditingForm(col, col->getParentTable()); } else if(obj_type==OBJ_CONSTRAINT) { constr=dynamic_cast(object); + + if(!constr->isAddedByRelationship()) + { + is_protected = constr->isProtected(); + constr->setProtected(true); + } + openEditingForm(constr, constr->getParentTable()); + + if(!constr->isAddedByRelationship()) + constr->setProtected(is_protected); } else { @@ -731,7 +712,7 @@ void RelationshipWidget::duplicateObject(int curr_row, int new_row) BaseObject *object = nullptr, *dup_object = nullptr; Relationship *rel = dynamic_cast(this->object); vector obj_list; - ObjectTableWidget *tab = nullptr; + ObjectsTableWidget *tab = nullptr; int op_id = -1; if(!rel) @@ -814,7 +795,7 @@ void RelationshipWidget::editObject(int row) void RelationshipWidget::showObjectData(TableObject *object, int row) { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; if(object->getObjectType()==OBJ_COLUMN) { diff --git a/libpgmodeler_ui/src/relationshipwidget.h b/libpgmodeler_ui/src/relationshipwidget.h index 352645ecd..e0ff0b0be 100644 --- a/libpgmodeler_ui/src/relationshipwidget.h +++ b/libpgmodeler_ui/src/relationshipwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_relationshipwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "colorpickerwidget.h" #include "hinttextwidget.h" @@ -56,7 +56,7 @@ class RelationshipWidget: public BaseObjectWidget, public Ui::RelationshipWidget *patterns_hl[7]; //! \brief Table widgets that stores the attributes, constraint and advanced objects of relationship - ObjectTableWidget *attributes_tab, + ObjectsTableWidget *attributes_tab, *constraints_tab, *advanced_objs_tab; @@ -85,8 +85,6 @@ class RelationshipWidget: public BaseObjectWidget, public Ui::RelationshipWidget QSize getIdealSize(void); private slots: - void hideEvent(QHideEvent *event); - void addObject(void); void editObject(int row); void removeObject(int row); diff --git a/libpgmodeler_ui/src/resultsetmodel.cpp b/libpgmodeler_ui/src/resultsetmodel.cpp new file mode 100644 index 000000000..548ff7c3d --- /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 000000000..ec1a6a5a3 --- /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/rolewidget.cpp b/libpgmodeler_ui/src/rolewidget.cpp index 4a97fd88c..2e4c40128 100644 --- a/libpgmodeler_ui/src/rolewidget.cpp +++ b/libpgmodeler_ui/src/rolewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -21,7 +21,7 @@ RoleWidget::RoleWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_ROLE) { - ObjectTableWidget *obj_tab=nullptr; + ObjectsTableWidget *obj_tab=nullptr; QGridLayout *grid=nullptr; QFrame *frame=nullptr; map > fields_map; @@ -38,7 +38,8 @@ RoleWidget::RoleWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_ROLE) role_grid->addWidget(frame, role_grid->count()+1, 0, 1, 4); frame->setParent(this); - fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_90)].push_back(can_replicate_chk); + fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_91)].push_back(can_replicate_chk); + fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_95)].push_back(bypass_rls_chk); frame=generateVersionWarningFrame(fields_map); role_grid->addWidget(frame, role_grid->count()+1, 0, 1, 0); frame->setParent(this); @@ -49,8 +50,8 @@ RoleWidget::RoleWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_ROLE) //Alocation of the member role tables for(i=0; i < 3; i++) { - obj_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::UPDATE_BUTTON | ObjectTableWidget::DUPLICATE_BUTTON), true, this); + obj_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::UPDATE_BUTTON | ObjectsTableWidget::DUPLICATE_BUTTON), true, this); members_tab[i]=obj_tab; obj_tab->setColumnCount(5); @@ -106,32 +107,6 @@ void RoleWidget::selectMemberRole(void) object_selection_wgt->show(); } -void RoleWidget::hideEvent(QHideEvent *event) -{ - unsigned i; - - for(i=0; i < 3; i++) - members_tab[i]->blockSignals(true); - - for(i=0; i < 3; i++) - { - members_tab[i]->removeRows(); - members_tab[i]->blockSignals(false); - } - - members_twg->setCurrentIndex(0); - passwd_edt->clear(); - conn_limit_sb->setValue(conn_limit_sb->minimum()); - superusr_chk->setChecked(false); - inh_perm_chk->setChecked(false); - create_db_chk->setChecked(false); - can_login_chk->setChecked(false); - create_role_chk->setChecked(false); - encrypt_pass_chk->setChecked(false); - - BaseObjectWidget::hideEvent(event); -} - void RoleWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Role *role) { if(role) @@ -149,6 +124,7 @@ void RoleWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Rol inh_perm_chk->setChecked(role->getOption(Role::OP_INHERIT)); can_login_chk->setChecked(role->getOption(Role::OP_LOGIN)); can_replicate_chk->setChecked(role->getOption(Role::OP_REPLICATION)); + bypass_rls_chk->setChecked(role->getOption(Role::OP_BYPASSRLS)); } BaseObjectWidget::setAttributes(model, op_list, role); @@ -295,6 +271,7 @@ void RoleWidget::applyConfiguration(void) role->setOption(Role::OP_INHERIT, inh_perm_chk->isChecked()); role->setOption(Role::OP_LOGIN, can_login_chk->isChecked()); role->setOption(Role::OP_REPLICATION, can_replicate_chk->isChecked()); + role->setOption(Role::OP_BYPASSRLS, bypass_rls_chk->isChecked()); for(type_id=0; type_id < 3; type_id++) { diff --git a/libpgmodeler_ui/src/rolewidget.h b/libpgmodeler_ui/src/rolewidget.h index 501711a16..1007af38a 100644 --- a/libpgmodeler_ui/src/rolewidget.h +++ b/libpgmodeler_ui/src/rolewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_rolewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" class RoleWidget: public BaseObjectWidget, public Ui::RoleWidget { private: @@ -37,7 +37,7 @@ class RoleWidget: public BaseObjectWidget, public Ui::RoleWidget { ModelObjectsWidget *object_selection_wgt; //! \brief Store the table widgets used to reference the member roles - ObjectTableWidget *members_tab[3]; + ObjectsTableWidget *members_tab[3]; //! \brief Fills the tables with to member roles of the editing role void fillMembersTable(void); @@ -45,8 +45,6 @@ class RoleWidget: public BaseObjectWidget, public Ui::RoleWidget { //! \brief Show the specified role data on the specified table index at the specified row void showRoleData(Role *role, unsigned table_id, unsigned row); - void hideEvent(QHideEvent *event); - public: RoleWidget(QWidget * parent = 0); ~RoleWidget(void); diff --git a/libpgmodeler_ui/src/rulewidget.cpp b/libpgmodeler_ui/src/rulewidget.cpp index c5c1d8b50..788ebdc9d 100644 --- a/libpgmodeler_ui/src/rulewidget.cpp +++ b/libpgmodeler_ui/src/rulewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,7 +34,7 @@ RuleWidget::RuleWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_RULE) command_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); command_cp=new CodeCompletionWidget(comando_txt); - commands_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ ObjectTableWidget::DUPLICATE_BUTTON, true, this); + commands_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ ObjectsTableWidget::DUPLICATE_BUTTON, true, this); commands_tab->setHeaderLabel(trUtf8("SQL command"),0); commands_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("codigosql")),0); dynamic_cast(commands_gb->layout())->addWidget(commands_tab, 1, 0, 1, 2); @@ -66,15 +66,6 @@ RuleWidget::RuleWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_RULE) } } -void RuleWidget::hideEvent(QHideEvent *event) -{ - BaseObjectWidget::hideEvent(event); - comando_txt->clear(); - commands_tab->removeRows(); - event_cmb->setCurrentIndex(0); - exec_type_cmb->setCurrentIndex(0); -} - void RuleWidget::editCommand(int row) { comando_txt->setPlainText(commands_tab->getCellText(row,0)); diff --git a/libpgmodeler_ui/src/rulewidget.h b/libpgmodeler_ui/src/rulewidget.h index 583eff942..925e8398f 100644 --- a/libpgmodeler_ui/src/rulewidget.h +++ b/libpgmodeler_ui/src/rulewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_rulewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "codecompletionwidget.h" class RuleWidget: public BaseObjectWidget, public Ui::RuleWidget { @@ -39,14 +39,13 @@ class RuleWidget: public BaseObjectWidget, public Ui::RuleWidget { CodeCompletionWidget *command_cp; - ObjectTableWidget *commands_tab; + ObjectsTableWidget *commands_tab; public: RuleWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, BaseTable *parent_tab, Rule *rule); private slots: - void hideEvent(QHideEvent *event); void handleCommand(int row); void editCommand(int row); diff --git a/libpgmodeler_ui/src/sceneinfowidget.cpp b/libpgmodeler_ui/src/sceneinfowidget.cpp index dfa0fcf13..487fd382a 100644 --- a/libpgmodeler_ui/src/sceneinfowidget.cpp +++ b/libpgmodeler_ui/src/sceneinfowidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/sceneinfowidget.h b/libpgmodeler_ui/src/sceneinfowidget.h index 3a7fd573a..33b4d2c9b 100644 --- a/libpgmodeler_ui/src/sceneinfowidget.h +++ b/libpgmodeler_ui/src/sceneinfowidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/schemawidget.cpp b/libpgmodeler_ui/src/schemawidget.cpp index 046e34508..7ddac2b95 100644 --- a/libpgmodeler_ui/src/schemawidget.cpp +++ b/libpgmodeler_ui/src/schemawidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/schemawidget.h b/libpgmodeler_ui/src/schemawidget.h index 827df3aea..8808e8a39 100644 --- a/libpgmodeler_ui/src/schemawidget.h +++ b/libpgmodeler_ui/src/schemawidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/sequencewidget.cpp b/libpgmodeler_ui/src/sequencewidget.cpp index 1cb60f8a2..d736855f9 100644 --- a/libpgmodeler_ui/src/sequencewidget.cpp +++ b/libpgmodeler_ui/src/sequencewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -32,7 +32,7 @@ SequenceWidget::SequenceWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_SE sequence_grid->addItem(new QSpacerItem(10,0,QSizePolicy::Minimum,QSizePolicy::Expanding), sequence_grid->count(), 0); configureTabOrder(); - setMinimumSize(520, 280); + setMinimumSize(520, 320); } catch(Exception &e) { @@ -40,12 +40,6 @@ SequenceWidget::SequenceWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_SE } } -void SequenceWidget::hideEvent(QHideEvent *event) -{ - column_sel->clearSelector(); - BaseObjectWidget::hideEvent(event); -} - void SequenceWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, Sequence *sequence) { column_sel->setModel(model); diff --git a/libpgmodeler_ui/src/sequencewidget.h b/libpgmodeler_ui/src/sequencewidget.h index c6a0bcf36..8b055c633 100644 --- a/libpgmodeler_ui/src/sequencewidget.h +++ b/libpgmodeler_ui/src/sequencewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,8 +34,6 @@ class SequenceWidget: public BaseObjectWidget, public Ui::SequenceWidget { ObjectSelectorWidget *column_sel; - void hideEvent(QHideEvent *event); - public: SequenceWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/snippetsconfigwidget.cpp b/libpgmodeler_ui/src/snippetsconfigwidget.cpp index ba17a7e4f..67d02a78f 100644 --- a/libpgmodeler_ui/src/snippetsconfigwidget.cpp +++ b/libpgmodeler_ui/src/snippetsconfigwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/snippetsconfigwidget.h b/libpgmodeler_ui/src/snippetsconfigwidget.h index 31ae67280..b3d9f7dd8 100644 --- a/libpgmodeler_ui/src/snippetsconfigwidget.h +++ b/libpgmodeler_ui/src/snippetsconfigwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/sourcecodewidget.cpp b/libpgmodeler_ui/src/sourcecodewidget.cpp index e84af8551..02c9d7324 100644 --- a/libpgmodeler_ui/src/sourcecodewidget.cpp +++ b/libpgmodeler_ui/src/sourcecodewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -24,11 +24,10 @@ SourceCodeWidget::SourceCodeWidget(QWidget *parent): BaseObjectWidget(parent) { try { - QFont font; - Ui_SourceCodeWidget::setupUi(this); configureFormLayout(codigofonte_grid, BASE_OBJECT); - comment_lbl->setText(trUtf8("Type:")); + comment_lbl->setVisible(false); + comment_edt->setVisible(false); hl_sqlcode=nullptr; hl_xmlcode=nullptr; @@ -39,11 +38,6 @@ SourceCodeWidget::SourceCodeWidget(QWidget *parent): BaseObjectWidget(parent) xmlcode_txt=PgModelerUiNS::createNumberedTextEditor(xmlcode_wgt); xmlcode_txt->setReadOnly(true); - font=name_edt->font(); - font.setItalic(true); - comment_edt->setFont(font); - comment_edt->setReadOnly(true); - name_edt->setFont(font); name_edt->setReadOnly(true); version_cmb->addItems(PgSQLVersions::ALL_VERSIONS); @@ -69,19 +63,6 @@ SourceCodeWidget::SourceCodeWidget(QWidget *parent): BaseObjectWidget(parent) } } -void SourceCodeWidget::hideEvent(QHideEvent *event) -{ - version_cmb->blockSignals(true); - sourcecode_twg->blockSignals(true); - version_cmb->setCurrentIndex(0); - sourcecode_twg->setCurrentIndex(0); - version_cmb->blockSignals(false); - sourcecode_twg->blockSignals(false); - sqlcode_txt->clear(); - xmlcode_txt->clear(); - BaseObjectWidget::hideEvent(event); -} - void SourceCodeWidget::setSourceCodeTab(int) { QString code_icon; @@ -245,6 +226,7 @@ void SourceCodeWidget::setAttributes(DatabaseModel *model, BaseObject *object) BaseObjectWidget::setAttributes(model, object, nullptr); ObjectType obj_type=object->getObjectType(); + this->name_edt->setText(QString("%1 (%2)").arg(object->getSignature()).arg(object->getTypeName())); this->protected_obj_frm->setVisible(false); this->obj_id_lbl->setVisible(false); this->code_options_cmb->setEnabled(obj_type!=OBJ_DATABASE && @@ -259,8 +241,6 @@ void SourceCodeWidget::setAttributes(DatabaseModel *model, BaseObject *object) obj_icon_lbl->setPixmap(QPixmap(PgModelerUiNS::getIconPath(object->getObjectType()))); - comment_edt->setText(object->getTypeName()); - if(!hl_sqlcode->isConfigurationLoaded()) hl_sqlcode->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); diff --git a/libpgmodeler_ui/src/sourcecodewidget.h b/libpgmodeler_ui/src/sourcecodewidget.h index 79beb35f2..43f0021cc 100644 --- a/libpgmodeler_ui/src/sourcecodewidget.h +++ b/libpgmodeler_ui/src/sourcecodewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -46,8 +46,6 @@ class SourceCodeWidget: public BaseObjectWidget, public Ui::SourceCodeWidget { HintTextWidget *code_options_ht; - void hideEvent(QHideEvent *event); - public: SourceCodeWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/sqlexecutionwidget.cpp b/libpgmodeler_ui/src/sqlexecutionwidget.cpp index ec9ce1f7e..19b004a8a 100644 --- a/libpgmodeler_ui/src/sqlexecutionwidget.cpp +++ b/libpgmodeler_ui/src/sqlexecutionwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -22,15 +22,19 @@ #include "snippetsconfigwidget.h" #include "pgmodeleruins.h" #include "plaintextitemdelegate.h" +#include "datamanipulationform.h" map SQLExecutionWidget::cmd_history; int SQLExecutionWidget::cmd_history_max_len = 1000; +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); @@ -48,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); @@ -71,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())); @@ -100,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, @@ -124,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)) @@ -182,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) { @@ -233,7 +263,9 @@ void SQLExecutionWidget::fillResultsTable(Catalog &catalog, ResultSet &res, QTab results_tbw->setRowCount(0); results_tbw->setColumnCount(col_cnt); results_tbw->verticalHeader()->setVisible(true); + results_tbw->setSortingEnabled(false); results_tbw->blockSignals(true); + results_tbw->setUpdatesEnabled(false); //Configuring the grid columns with the names of retrived table columns for(col=0; col < col_cnt; col++) @@ -261,7 +293,7 @@ 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)]); } @@ -286,8 +318,10 @@ void SQLExecutionWidget::fillResultsTable(Catalog &catalog, ResultSet &res, QTab { item->setText(res.getColumnValue(col)); + /* When storing column values in the QTableWidget items we need distinguish empty from null values + * Since it may affect the generation of SQL like delete when the field value is used somehow (see DataManipulationForm::getDMLCommand) */ if(store_data) - item->setData(Qt::UserRole, item->text()); + item->setData(Qt::UserRole, res.isColumnValueNull(col) ? COLUMN_NULL_VALUE : item->text()); } results_tbw->setItem(row, col, item); @@ -300,6 +334,7 @@ void SQLExecutionWidget::fillResultsTable(Catalog &catalog, ResultSet &res, QTab while(res.accessTuple(ResultSet::NEXT_TUPLE)); } + results_tbw->setUpdatesEnabled(true); results_tbw->blockSignals(false); results_tbw->resizeColumnsToContents(); results_tbw->resizeRowsToContents(); @@ -403,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); @@ -423,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()); @@ -435,7 +473,7 @@ void SQLExecutionWidget::runSQLCommand(void) if(!res.isEmpty()) { fillResultsTable(res); - output_tbw->setTabText(0, trUtf8("Results (%1)").arg(res.getTupleCount())); + output_tbw->setTabText(0, trUtf8("Results (%1)").arg(results_tbw->model()->rowCount())); output_tbw->setCurrentIndex(0); } else @@ -453,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"))); @@ -532,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__); @@ -558,116 +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(); } } -QByteArray SQLExecutionWidget::generateCSVBuffer(QTableWidget *results_tbw, int start_row, int start_col, int row_cnt, int col_cnt) +int SQLExecutionWidget::clearAll(void) { - if(!results_tbw) - throw Exception(ERR_OPR_NOT_ALOC_OBJECT ,__PRETTY_FUNCTION__,__FILE__,__LINE__); - - QByteArray buf; - QStringList line; + Messagebox msg_box; + int res = 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; + 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); - //Creating the header of csv - for(col=start_col; col < max_col; col++) - line.append(QString("\"%1\"").arg(results_tbw->horizontalHeaderItem(col)->text())); + res = msg_box.result(); - buf.append(line.join(';')); - buf.append('\n'); - line.clear(); + if(res==QDialog::Accepted) + { + sql_cmd_txt->setPlainText(QString()); + msgoutput_lst->clear(); + msgoutput_lst->setVisible(true); + results_parent->setVisible(false); + export_tb->setEnabled(false); + } - //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())); + return(res); +} - buf.append(line.join(';')); - line.clear(); - buf.append('\n'); - } - } +QByteArray SQLExecutionWidget::generateCSVBuffer(QTableView *results_tbw) +{ + return(generateBuffer(results_tbw, QChar(';'), true, true)); +} - return(buf); +QByteArray SQLExecutionWidget::generateTextBuffer(QTableView *results_tbw) +{ + return(generateBuffer(results_tbw, QChar('\t'), false, false)); } -QByteArray SQLExecutionWidget::generateTextBuffer(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; - //Creating the content - for(row=start_row; row < max_row; row++) - { - for(col=start_col; col < max_col; col++) - { - line.push_back(results_tbw->item(row, col)->text()); - } + int col=0, row=0, + max_col=start_col + col_cnt, + max_row=start_row + row_cnt; - buf.append(line.join('\t')); - line.clear(); - buf.append('\n'); - } - } - - 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); + if(incl_col_names) + { + //Creating the header + for(col=start_col; col < max_col; col++) + line.append(str_pattern.arg(model->headerData(col, Qt::Horizontal).toString())); - res = msg_box.result(); + buf.append(line.join(separator)); + buf.append('\n'); + line.clear(); + } - if(res==QDialog::Accepted) + //Creating the content + for(row=start_row; row < max_row; row++) { - sql_cmd_txt->setPlainText(QString()); - msgoutput_lst->clear(); - msgoutput_lst->setVisible(true); - results_parent->setVisible(false); - export_tb->setEnabled(false); + for(col=start_col; col < max_col; col++) + { + index = model->index(row, col); + line.append(str_pattern.arg(index.data().toString())); + } + + 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; @@ -682,21 +725,21 @@ 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 */ + DataManipulationForm::setHasCsvClipboard(true); } 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); @@ -713,17 +756,6 @@ void SQLExecutionWidget::selectSnippet(QAction *act) sql_cmd_txt->setTextCursor(cursor); } -/*void SQLExecutionWidget::handleSelectedWord(QString word) -{ - if(SnippetsConfigWidget::isSnippetExists(word)) - { - QTextCursor tc=sql_cmd_txt->textCursor(); - tc.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); - tc.removeSelectedText(); - tc.insertText(SnippetsConfigWidget::getParsedSnippet(word)); - } -}*/ - void SQLExecutionWidget::toggleOutputPane(bool visible) { if(!visible) diff --git a/libpgmodeler_ui/src/sqlexecutionwidget.h b/libpgmodeler_ui/src/sqlexecutionwidget.h index 0cd71a9b1..9b8ff25be 100644 --- a/libpgmodeler_ui/src/sqlexecutionwidget.h +++ b/libpgmodeler_ui/src/sqlexecutionwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -33,6 +33,7 @@ #include "codecompletionwidget.h" #include "numberedtexteditor.h" #include "findreplacewidget.h" +#include "resultsetmodel.h" class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget { private: @@ -68,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); @@ -94,7 +97,10 @@ class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget { bool eventFilter(QObject *object, QEvent *event); public: + static const QString COLUMN_NULL_VALUE; + SQLExecutionWidget(QWidget * parent = 0); + ~SQLExecutionWidget(void); //! \brief Configures the connection to query the server void setConnection(Connection conn); @@ -104,16 +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 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); //! \brief Exports the results to csv file - static void exportResults(QTableWidget *results_tbw); + static void exportResults(QTableView *results_tbw); public slots: void configureSnippets(void); @@ -148,8 +157,6 @@ class SQLExecutionWidget: public QWidget, public Ui::SQLExecutionWidget { void selectSnippet(QAction *act); - //void handleSelectedWord(QString word); - void toggleOutputPane(bool visible); void showHistoryContextMenu(void); diff --git a/libpgmodeler_ui/src/sqltoolwidget.cpp b/libpgmodeler_ui/src/sqltoolwidget.cpp index 451b13811..906b9564a 100644 --- a/libpgmodeler_ui/src/sqltoolwidget.cpp +++ b/libpgmodeler_ui/src/sqltoolwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -203,6 +203,7 @@ void SQLToolWidget::disconnectFromDatabases(void) connections_cmb->setCurrentIndex(0); disconnect_tb->setEnabled(false); + sourcecode_txt->clear(); } } catch(Exception &e) diff --git a/libpgmodeler_ui/src/sqltoolwidget.h b/libpgmodeler_ui/src/sqltoolwidget.h index 0237a6948..f471a4e62 100644 --- a/libpgmodeler_ui/src/sqltoolwidget.h +++ b/libpgmodeler_ui/src/sqltoolwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/swapobjectsidswidget.h b/libpgmodeler_ui/src/swapobjectsidswidget.h index 6cf1c120b..af414541f 100644 --- a/libpgmodeler_ui/src/swapobjectsidswidget.h +++ b/libpgmodeler_ui/src/swapobjectsidswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/syntaxhighlighter.cpp b/libpgmodeler_ui/src/syntaxhighlighter.cpp index fef8d6b4f..9537fd800 100644 --- a/libpgmodeler_ui/src/syntaxhighlighter.cpp +++ b/libpgmodeler_ui/src/syntaxhighlighter.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -105,7 +105,8 @@ void SyntaxHighlighter::highlightBlock(const QString &txt) /* If the previous block info is a open multiline expression the current block will inherit this settings to force the same text formatting */ - if(prev_info && currentBlock().previous().userState()==OPEN_EXPR_BLOCK) + if(prev_info && currentBlock().previous().userState()==OPEN_EXPR_BLOCK && + currentBlockState() == OPEN_EXPR_BLOCK) { info->group=prev_info->group; info->has_exprs=prev_info->has_exprs; @@ -154,13 +155,45 @@ void SyntaxHighlighter::highlightBlock(const QString &txt) } else { + BlockInfo *prev_info = dynamic_cast(currentBlock().previous().userData()); + while(i < len && !word_separators.contains(text[i]) && - !word_delimiters.contains(text[i]) && - !ignored_chars.contains(text[i])) + !ignored_chars.contains(text[i]) && + !word_delimiters.contains(text[i])) { word+=text[i++]; } + + /* This is an workaround for multi lined groups which use word delimiters + in their final expressions. In some cases the highlighter can't undertand that + a multi line group was closed and right after another group starts, this way it + continues to highlight text as the previous multi lined group. + + An example of that situation is for multi lined string group: + + word delimiter: ' (apostrophe) + initial-exp: (')(.)*(\n) + final-exp: (.)*(')(\n)* + + String: 'lorem\n ipsum' nextword + + In the example above, without the workaround, the highlighter would highlight the first line + "'lorem\n" as string and continue to hightlight the " ipsum' nextword" in the same way as well, + this because the final expression of the group contains the word delimiter '. In order to force the highlight stop + in the last ' we include it in the current evaluated word and increment the position in the text so the next + word starts without the word delimiter. */ + if(word_delimiters.contains(text[i]) && prev_info && !prev_info->group.isEmpty() && prev_info->has_exprs) + { + for(auto exp : final_exprs[prev_info->group]) + { + if(exp.pattern().contains(text[i])) + { + word+=text[i++]; + break; + } + } + } } } @@ -177,6 +210,7 @@ void SyntaxHighlighter::highlightBlock(const QString &txt) match_idx=-1; match_len=0; + group=identifyWordGroup(word, lookahead_chr, match_idx, match_len); if(!group.isEmpty()) diff --git a/libpgmodeler_ui/src/syntaxhighlighter.h b/libpgmodeler_ui/src/syntaxhighlighter.h index 00faaebe8..67e949f09 100644 --- a/libpgmodeler_ui/src/syntaxhighlighter.h +++ b/libpgmodeler_ui/src/syntaxhighlighter.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/tabledatawidget.cpp b/libpgmodeler_ui/src/tabledatawidget.cpp index d27d95e8a..74bb0add7 100644 --- a/libpgmodeler_ui/src/tabledatawidget.cpp +++ b/libpgmodeler_ui/src/tabledatawidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/tabledatawidget.h b/libpgmodeler_ui/src/tabledatawidget.h index aaa38d381..564eeb9b3 100644 --- a/libpgmodeler_ui/src/tabledatawidget.h +++ b/libpgmodeler_ui/src/tabledatawidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/tablespacewidget.cpp b/libpgmodeler_ui/src/tablespacewidget.cpp index d1b3db0db..4933de221 100644 --- a/libpgmodeler_ui/src/tablespacewidget.cpp +++ b/libpgmodeler_ui/src/tablespacewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -33,12 +33,6 @@ TablespaceWidget::TablespaceWidget(QWidget *parent): BaseObjectWidget(parent, OB setMinimumSize(480, 140); } -void TablespaceWidget::hideEvent(QHideEvent *event) -{ - directory_edt->clear(); - BaseObjectWidget::hideEvent(event); -} - void TablespaceWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Tablespace *tablespc) { BaseObjectWidget::setAttributes(model, op_list, tablespc); diff --git a/libpgmodeler_ui/src/tablespacewidget.h b/libpgmodeler_ui/src/tablespacewidget.h index 1695c2d02..2d2590fe1 100644 --- a/libpgmodeler_ui/src/tablespacewidget.h +++ b/libpgmodeler_ui/src/tablespacewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -36,9 +36,6 @@ class TablespaceWidget: public BaseObjectWidget, public Ui::TablespaceWidget { TablespaceWidget(QWidget * parent = 0); void setAttributes(DatabaseModel *model, OperationList *op_list, Tablespace *tablespc); - private slots: - void hideEvent(QHideEvent *event); - public slots: void applyConfiguration(void); }; diff --git a/libpgmodeler_ui/src/tablewidget.cpp b/libpgmodeler_ui/src/tablewidget.cpp index fc62b29b2..8099d124a 100644 --- a/libpgmodeler_ui/src/tablewidget.cpp +++ b/libpgmodeler_ui/src/tablewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -24,12 +24,13 @@ #include "triggerwidget.h" #include "baseform.h" #include "tabledatawidget.h" +#include "policywidget.h" TableWidget::TableWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TABLE) { QGridLayout *grid=nullptr; - ObjectTableWidget *tab=nullptr; - ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX }; + ObjectsTableWidget *tab=nullptr; + ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX, OBJ_POLICY }; map > fields_map; QFrame *frame=nullptr; QToolButton *edt_data_tb=nullptr; @@ -49,11 +50,13 @@ TableWidget::TableWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TABLE) misc_btns_lt->insertWidget(1, edt_data_tb); fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_91)].push_back(unlogged_chk); + fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_95)].push_back(enable_rls_chk); + fields_map[generateVersionsInterval(AFTER_VERSION, PgSQLVersions::PGSQL_VERSION_95)].push_back(force_rls_chk); frame=generateVersionWarningFrame(fields_map); table_grid->addWidget(frame, table_grid->count()+1, 0, 1, 2); frame->setParent(this); - parent_tables = new ObjectTableWidget(ObjectTableWidget::NO_BUTTONS, true, this); + parent_tables = new ObjectsTableWidget(ObjectsTableWidget::NO_BUTTONS, true, this); parent_tables->setColumnCount(3); parent_tables->setHeaderLabel(trUtf8("Name"), 0); parent_tables->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")),0); @@ -63,18 +66,18 @@ TableWidget::TableWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TABLE) parent_tables->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("usertype")),2); tag_sel=new ObjectSelectorWidget(OBJ_TAG, false, this); - dynamic_cast(options_gb->layout())->addWidget(tag_sel, 0, 1, 1, 3); + dynamic_cast(options_gb->layout())->addWidget(tag_sel, 0, 1,1,3); grid=new QGridLayout; grid->addWidget(parent_tables, 0,0,1,1); grid->setContentsMargins(4,4,4,4); - attributes_tbw->widget(5)->setLayout(grid); + attributes_tbw->widget(6)->setLayout(grid); //Configuring the table objects that stores the columns, triggers, constraints, rules and indexes - for(unsigned i=0; i < 5; i++) + for(unsigned i=0; i <= 5; i++) { - tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::UPDATE_BUTTON), true, this); + tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::UPDATE_BUTTON), true, this); objects_tab_map[types[i]]=tab; @@ -101,7 +104,7 @@ TableWidget::TableWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TABLE) objects_tab_map[OBJ_COLUMN]->setHeaderLabel(trUtf8("Attribute(s)"), 4); objects_tab_map[OBJ_COLUMN]->adjustColumnToContents(0); - connect(objects_tab_map[OBJ_COLUMN], &ObjectTableWidget::s_cellClicked, [&](int row, int col){ + connect(objects_tab_map[OBJ_COLUMN], &ObjectsTableWidget::s_cellClicked, [&](int row, int col){ if(col == 0 && objects_tab_map[OBJ_COLUMN]->isCellDisabled(static_cast(row), static_cast(col))) { Messagebox msg_box; @@ -143,38 +146,23 @@ TableWidget::TableWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TABLE) objects_tab_map[OBJ_INDEX]->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")),0); objects_tab_map[OBJ_INDEX]->setHeaderLabel(trUtf8("Indexing"), 1); + objects_tab_map[OBJ_POLICY]->setColumnCount(6); + objects_tab_map[OBJ_POLICY]->setHeaderLabel(trUtf8("Name"), 0); + objects_tab_map[OBJ_POLICY]->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")),0); + objects_tab_map[OBJ_POLICY]->setHeaderLabel(trUtf8("Command"), 1); + objects_tab_map[OBJ_POLICY]->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("keyword")),1); + objects_tab_map[OBJ_POLICY]->setHeaderLabel(trUtf8("Permissive"), 2); + objects_tab_map[OBJ_POLICY]->setHeaderLabel(trUtf8("USING expression"), 3); + objects_tab_map[OBJ_POLICY]->setHeaderLabel(trUtf8("CHECK expression"), 4); + objects_tab_map[OBJ_POLICY]->setHeaderLabel(trUtf8("Roles"), 5); + objects_tab_map[OBJ_POLICY]->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("role")),5); + configureFormLayout(table_grid, OBJ_TABLE); configureTabOrder({ tag_sel }); setMinimumSize(600, 610); } -void TableWidget::hideEvent(QHideEvent *event) -{ - map::iterator itr, itr_end; - Table *tab=dynamic_cast
(this->object); - - parent_tables->removeRows(); - with_oids_chk->setChecked(false); - unlogged_chk->setChecked(false); - attributes_tbw->setCurrentIndex(0); - - itr=objects_tab_map.begin(); - itr_end=objects_tab_map.end(); - while(itr!=itr_end) - { - (itr->second)->blockSignals(true); - (itr->second)->removeRows(); - (itr->second)->blockSignals(false); - itr++; - } - - if(this->new_object && !tab->isModified()) - this->cancelConfiguration(); - - BaseObjectWidget::hideEvent(event); -} - template int TableWidget::openEditingForm(TableObject *object) { @@ -183,12 +171,10 @@ int TableWidget::openEditingForm(TableObject *object) object_wgt->setAttributes(this->model, this->op_list, dynamic_cast
(this->object), dynamic_cast(object)); editing_form.setMainWidget(object_wgt); - - editing_form.adjustSize(); return(editing_form.exec()); } -ObjectTableWidget *TableWidget::getObjectTable(ObjectType obj_type) +ObjectsTableWidget *TableWidget::getObjectTable(ObjectType obj_type) { if(objects_tab_map.count(obj_type) > 0) return(objects_tab_map[obj_type]); @@ -202,7 +188,7 @@ ObjectType TableWidget::getObjectType(QObject *sender) if(sender) { - map::iterator itr, itr_end; + map::iterator itr, itr_end; itr=objects_tab_map.begin(); itr_end=objects_tab_map.end(); @@ -225,7 +211,7 @@ void TableWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Sc { unsigned i, count; Table *aux_tab=nullptr; - ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX }; + ObjectType types[]={ OBJ_COLUMN, OBJ_CONSTRAINT, OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX, OBJ_POLICY }; if(!table) { @@ -246,11 +232,11 @@ void TableWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Sc /* Listing all objects (column, constraint, trigger, index, rule) on the respective table objects */ - for(i=0; i < 5; i++) + for(i=0; i < 6; i++) { listObjects(types[i]); - objects_tab_map[types[i]]->setButtonConfiguration(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::UPDATE_BUTTON)); + objects_tab_map[types[i]]->setButtonConfiguration(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::UPDATE_BUTTON)); } //Listing the ancestor tables @@ -277,6 +263,8 @@ void TableWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Sc with_oids_chk->setChecked(table->isWithOIDs()); unlogged_chk->setChecked(table->isUnlogged()); gen_alter_cmds_chk->setChecked(table->isGenerateAlterCmds()); + enable_rls_chk->setChecked(table->isRLSEnabled()); + force_rls_chk->setChecked(table->isRLSForced()); tag_sel->setModel(this->model); tag_sel->setSelectedObject(table->getTag()); @@ -289,7 +277,7 @@ void TableWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Sc void TableWidget::listObjects(ObjectType obj_type) { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; unsigned count, i; Table *table=nullptr; @@ -315,11 +303,11 @@ void TableWidget::listObjects(ObjectType obj_type) //Enables the add button on the constraints, triggers and index tab only when there is columns created if(obj_type==OBJ_COLUMN) { - objects_tab_map[OBJ_CONSTRAINT]->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, + objects_tab_map[OBJ_CONSTRAINT]->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, objects_tab_map[OBJ_COLUMN]->getRowCount() > 0); - objects_tab_map[OBJ_TRIGGER]->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, + objects_tab_map[OBJ_TRIGGER]->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, objects_tab_map[OBJ_COLUMN]->getRowCount() > 0); - objects_tab_map[OBJ_INDEX]->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, + objects_tab_map[OBJ_INDEX]->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, objects_tab_map[OBJ_COLUMN]->getRowCount() > 0); } } @@ -333,7 +321,7 @@ void TableWidget::handleObject(void) { ObjectType obj_type=BASE_OBJECT; TableObject *object=nullptr; - ObjectTableWidget *obj_table=nullptr; + ObjectsTableWidget *obj_table=nullptr; try { @@ -354,8 +342,10 @@ void TableWidget::handleObject(void) openEditingForm(object); else if(obj_type==OBJ_INDEX) openEditingForm(object); - else + else if(obj_type==OBJ_RULE) openEditingForm(object); + else + openEditingForm(object); listObjects(obj_type); @@ -371,12 +361,13 @@ void TableWidget::handleObject(void) void TableWidget::showObjectData(TableObject *object, int row) { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; Column *column=nullptr; Constraint *constr=nullptr; Trigger *trigger=nullptr; Rule *rule=nullptr; Index *index=nullptr; + Policy *policy=nullptr; ObjectType obj_type; QString str_aux, str_aux1; @@ -416,6 +407,8 @@ void TableWidget::showObjectData(TableObject *object, int row) //Column 3: Column defaul value if(column->getSequence()) str_aux=QString("nextval('%1'::regclass)").arg(column->getSequence()->getName(true).remove('"')); + else if(column->getIdentityType() != BaseType::null) + str_aux=QString("GENERATED %1 AS IDENTITY").arg(~column->getIdentityType()); else str_aux=column->getDefaultValue(); @@ -499,13 +492,37 @@ void TableWidget::showObjectData(TableObject *object, int row) //Column 2: Rule event type tab->setCellText(~rule->getEventType(),row,2); } - else + else if(obj_type==OBJ_INDEX) { index=dynamic_cast(object); //Coluna 1: Indexing type tab->setCellText(~index->getIndexingType(),row,1); } + else if(obj_type==OBJ_POLICY) + { + QStringList rol_names; + + policy = dynamic_cast(object); + + //Column 1: Command + tab->setCellText(~policy->getPolicyCommand(), row, 1); + + //Column 2: Permissive + tab->setCellText(QString("%1").arg(policy->isPermissive() ? trUtf8("Yes") : trUtf8("No")), row, 2); + + //Column 3: USING expression + tab->setCellText(policy->getUsingExpression(), row, 3); + + //Column 4: CHECK expression + tab->setCellText(policy->getCheckExpression(), row, 4); + + for(auto role : policy->getRoles()) + rol_names.append(role->getName()); + + //Column 5: Roles + tab->setCellText(!rol_names.isEmpty() ? rol_names.join(", ") : QString("PUBLIC"), row, 5); + } //Changes the foreground/background color of the table row if the object is protected or added by relationship if(object->isAddedByRelationship() || object->isProtected()) @@ -628,7 +645,7 @@ void TableWidget::duplicateObject(int sel_row, int new_row) { ObjectType obj_type=BASE_OBJECT; BaseObject *object=nullptr, *dup_object=nullptr; - ObjectTableWidget *obj_table=nullptr; + ObjectsTableWidget *obj_table=nullptr; Table *table = dynamic_cast
(this->object); int op_id = -1; @@ -719,7 +736,7 @@ void TableWidget::applyConfiguration(void) Constraint *pk = nullptr; vector rels; vector pk_cols; - ObjectTableWidget *col_tab = objects_tab_map[OBJ_COLUMN]; + ObjectsTableWidget *col_tab = objects_tab_map[OBJ_COLUMN]; if(!this->new_object) op_list->registerObject(this->object, Operation::OBJECT_MODIFIED); @@ -729,6 +746,8 @@ void TableWidget::applyConfiguration(void) table=dynamic_cast
(this->object); table->setWithOIDs(with_oids_chk->isChecked()); table->setGenerateAlterCmds(gen_alter_cmds_chk->isChecked()); + table->setRLSEnabled(enable_rls_chk->isChecked()); + table->setRLSForced(force_rls_chk->isChecked()); table->setUnlogged(unlogged_chk->isChecked()); table->setTag(dynamic_cast(tag_sel->getSelectedObject())); diff --git a/libpgmodeler_ui/src/tablewidget.h b/libpgmodeler_ui/src/tablewidget.h index 2ec9d4977..2019e12fa 100644 --- a/libpgmodeler_ui/src/tablewidget.h +++ b/libpgmodeler_ui/src/tablewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,19 +27,19 @@ #include "baseobjectwidget.h" #include "ui_tablewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "tableview.h" class TableWidget: public BaseObjectWidget, public Ui::TableWidget { private: Q_OBJECT - ObjectTableWidget *parent_tables; + ObjectsTableWidget *parent_tables; ObjectSelectorWidget *tag_sel; //! \brief Stores the objects tables used to handle columns, constraints, indexes, rules and triggers - map objects_tab_map; + map objects_tab_map; //! \brief Lists (on the correct object table) the table objects according to the specified type void listObjects(ObjectType obj_type); @@ -48,7 +48,7 @@ class TableWidget: public BaseObjectWidget, public Ui::TableWidget { void showObjectData(TableObject *object, int row); //! \brief Returns the object table according with the child type - ObjectTableWidget *getObjectTable(ObjectType obj_type); + ObjectsTableWidget *getObjectTable(ObjectType obj_type); //! \brief Returns the object type according to the widget (in this case a object table) that called the method ObjectType getObjectType(QObject *sender); @@ -58,8 +58,6 @@ class TableWidget: public BaseObjectWidget, public Ui::TableWidget { template int openEditingForm(TableObject *object); - void hideEvent(QHideEvent *event); - public: TableWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/tagwidget.cpp b/libpgmodeler_ui/src/tagwidget.cpp index 6f7812628..dacae2328 100644 --- a/libpgmodeler_ui/src/tagwidget.cpp +++ b/libpgmodeler_ui/src/tagwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/tagwidget.h b/libpgmodeler_ui/src/tagwidget.h index d66919b45..a33cdbcde 100644 --- a/libpgmodeler_ui/src/tagwidget.h +++ b/libpgmodeler_ui/src/tagwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/taskprogresswidget.cpp b/libpgmodeler_ui/src/taskprogresswidget.cpp index 15706b5c6..930d7cd73 100644 --- a/libpgmodeler_ui/src/taskprogresswidget.cpp +++ b/libpgmodeler_ui/src/taskprogresswidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/taskprogresswidget.h b/libpgmodeler_ui/src/taskprogresswidget.h index 4f5945fea..7b9a08294 100644 --- a/libpgmodeler_ui/src/taskprogresswidget.h +++ b/libpgmodeler_ui/src/taskprogresswidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/textboxwidget.cpp b/libpgmodeler_ui/src/textboxwidget.cpp index 176d0dcd1..2adfc6746 100644 --- a/libpgmodeler_ui/src/textboxwidget.cpp +++ b/libpgmodeler_ui/src/textboxwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -29,21 +29,6 @@ TextboxWidget::TextboxWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TEXT setMinimumSize(500, 200); } -void TextboxWidget::hideEvent(QHideEvent *event) -{ - QPalette palette; - - text_txt->clear(); - bold_chk->setChecked(false); - italic_chk->setChecked(false); - underline_chk->setChecked(false); - - palette.setColor(QPalette::Button, QColor(0,0,0)); - color_select_tb->setPalette(palette); - - BaseObjectWidget::hideEvent(event); -} - void TextboxWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Textbox *txtbox, double obj_px, double obj_py) { if(txtbox) diff --git a/libpgmodeler_ui/src/textboxwidget.h b/libpgmodeler_ui/src/textboxwidget.h index 8bd8c767a..2b7991222 100644 --- a/libpgmodeler_ui/src/textboxwidget.h +++ b/libpgmodeler_ui/src/textboxwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -31,7 +31,6 @@ class TextboxWidget: public BaseObjectWidget, public Ui::TextboxWidget { private: Q_OBJECT - void hideEvent(QHideEvent *event); public: TextboxWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/triggerwidget.cpp b/libpgmodeler_ui/src/triggerwidget.cpp index ded3fc960..d619ad946 100644 --- a/libpgmodeler_ui/src/triggerwidget.cpp +++ b/libpgmodeler_ui/src/triggerwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -29,12 +29,12 @@ TriggerWidget::TriggerWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TRIG cond_expr_hl=new SyntaxHighlighter(cond_expr_txt, false, true); cond_expr_hl->loadConfiguration(GlobalAttributes::SQL_HIGHLIGHT_CONF_PATH); - columns_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::EDIT_BUTTON | - ObjectTableWidget::UPDATE_BUTTON | - ObjectTableWidget::DUPLICATE_BUTTON), true, this); + columns_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::EDIT_BUTTON | + ObjectsTableWidget::UPDATE_BUTTON | + ObjectsTableWidget::DUPLICATE_BUTTON), true, this); - arguments_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ ObjectTableWidget::DUPLICATE_BUTTON, true, this); + arguments_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ ObjectsTableWidget::DUPLICATE_BUTTON, true, this); ref_table_sel=new ObjectSelectorWidget(OBJ_TABLE, true, this); function_sel=new ObjectSelectorWidget(OBJ_FUNCTION, true, this); @@ -121,7 +121,7 @@ void TriggerWidget::addColumn(int lin_idx) column=reinterpret_cast(column_cmb->itemData(column_cmb->currentIndex(),Qt::UserRole).value()); column_cmb->removeItem(column_cmb->currentIndex()); addColumn(column, lin_idx); - columns_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); + columns_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); } catch(Exception &e) { @@ -164,7 +164,7 @@ void TriggerWidget::updateColumnsCombo(void) } } - columns_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); + columns_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); } } catch(Exception &e) @@ -189,36 +189,6 @@ void TriggerWidget::editArgument(int lin_idx) argument_edt->setText(arguments_tab->getCellText(lin_idx, 0)); } -void TriggerWidget::hideEvent(QHideEvent *event) -{ - BaseObjectWidget::hideEvent(event); - - cond_expr_txt->clear(); - column_cmb->clear(); - argument_edt->clear(); - - deferrable_chk->setChecked(false); - firing_mode_cmb->setCurrentIndex(0); - deferral_type_cmb->setCurrentIndex(0); - - columns_tab->blockSignals(true); - arguments_tab->blockSignals(true); - columns_tab->removeRows(); - arguments_tab->removeRows(); - columns_tab->blockSignals(false); - arguments_tab->blockSignals(false); - - insert_chk->setChecked(false); - update_chk->setChecked(false); - delete_chk->setChecked(false); - truncate_chk->setChecked(false); - - function_sel->clearSelector(); - ref_table_sel->clearSelector(); - - arg_cols_tbw->setCurrentIndex(0); -} - void TriggerWidget::setAttributes(DatabaseModel *model, OperationList *op_list, BaseTable *parent_table, Trigger *trigger) { unsigned count=0, i; @@ -266,7 +236,7 @@ void TriggerWidget::setAttributes(DatabaseModel *model, OperationList *op_list, arguments_tab->setCellText(trigger->getArgument(i), i, 0); } - columns_tab->setButtonsEnabled(ObjectTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); + columns_tab->setButtonsEnabled(ObjectsTableWidget::ADD_BUTTON, (column_cmb->count()!=0)); arguments_tab->blockSignals(false); columns_tab->blockSignals(false); } diff --git a/libpgmodeler_ui/src/triggerwidget.h b/libpgmodeler_ui/src/triggerwidget.h index 638b552a3..1b8095470 100644 --- a/libpgmodeler_ui/src/triggerwidget.h +++ b/libpgmodeler_ui/src/triggerwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,7 +27,7 @@ #include "baseobjectwidget.h" #include "ui_triggerwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" class TriggerWidget: public BaseObjectWidget, public Ui::TriggerWidget { private: @@ -37,7 +37,7 @@ class TriggerWidget: public BaseObjectWidget, public Ui::TriggerWidget { SyntaxHighlighter *cond_expr_hl; //! \brief Object tables used to control columns and agruments - ObjectTableWidget *columns_tab, + ObjectsTableWidget *columns_tab, *arguments_tab; //! \brief Selectors for reference table and trigger function @@ -47,8 +47,6 @@ class TriggerWidget: public BaseObjectWidget, public Ui::TriggerWidget { //! \brief Adds a column to the referenced columns table void addColumn(Column *column, int row); - void hideEvent(QHideEvent *event); - public: TriggerWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/typewidget.cpp b/libpgmodeler_ui/src/typewidget.cpp index f52183e78..08a03f3a5 100644 --- a/libpgmodeler_ui/src/typewidget.cpp +++ b/libpgmodeler_ui/src/typewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -47,13 +47,13 @@ TypeWidget::TypeWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TYPE) grid->addWidget(functions_sel[i],i,1,1,1); } - enumerations_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::EDIT_BUTTON | ObjectTableWidget::DUPLICATE_BUTTON), true, this); + enumerations_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::EDIT_BUTTON | ObjectsTableWidget::DUPLICATE_BUTTON), true, this); grid=dynamic_cast(enumerations_gb->layout()); grid->addWidget(enumerations_tab,1,0,1,2); enumerations_gb->setVisible(false); - attributes_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ ObjectTableWidget::DUPLICATE_BUTTON, true, this); + attributes_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ ObjectsTableWidget::DUPLICATE_BUTTON, true, this); attributes_tab->setColumnCount(3); attributes_tab->setHeaderLabel(trUtf8("Name"),0); attributes_tab->setHeaderIcon(QPixmap(PgModelerUiNS::getIconPath("uid")),0); @@ -135,32 +135,6 @@ TypeWidget::TypeWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_TYPE) } } -void TypeWidget::hideEvent(QHideEvent *event) -{ - enumerations_tab->removeRows(); - attributes_tab->removeRows(); - - for(unsigned i=Type::INPUT_FUNC; i <= Type::SUBTYPE_DIFF_FUNC; i++) - functions_sel[i]->clearSelector(); - - base_type_rb->setChecked(true); - internal_len_sb->setValue(0); - by_value_chk->setChecked(false); - preferred_chk->setChecked(false); - delimiter_edt->clear(); - default_value_edt->clear();; - category_cmb->setCurrentIndex(0); - storage_cmb->setCurrentIndex(0); - alignment_cmb->setCurrentIndex(0); - base_attribs_twg->setCurrentIndex(0); - opclass_sel->clearSelector(); - - collation_sel->setEnabled(true); - collation_lbl->setEnabled(true); - - BaseObjectWidget::hideEvent(event); -} - void TypeWidget::selectTypeConfiguration(void) { base_attribs_twg->setVisible(base_type_rb->isChecked()); diff --git a/libpgmodeler_ui/src/typewidget.h b/libpgmodeler_ui/src/typewidget.h index 9d770ed0f..b4041a334 100644 --- a/libpgmodeler_ui/src/typewidget.h +++ b/libpgmodeler_ui/src/typewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -28,7 +28,7 @@ #include "baseobjectwidget.h" #include "ui_typewidget.h" #include "pgsqltypewidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" /* Declaring the TypeAttribute class as a Qt metatype in order to permit that instances of the class be used as data of QVariant and QMetaType */ @@ -51,7 +51,7 @@ class TypeWidget: public BaseObjectWidget, public Ui::TypeWidget { *range_subtype; //! \brief Tables that store enumaration elementas and composite attributes - ObjectTableWidget *enumerations_tab, + ObjectsTableWidget *enumerations_tab, *attributes_tab; //! \brief Composite type attribute collation selector @@ -60,8 +60,6 @@ class TypeWidget: public BaseObjectWidget, public Ui::TypeWidget { //! \brief Composite type attribute datatype configurator PgSQLTypeWidget *attrib_type_wgt; - void hideEvent(QHideEvent *event); - public: TypeWidget(QWidget * parent = 0); diff --git a/libpgmodeler_ui/src/updatenotifierwidget.cpp b/libpgmodeler_ui/src/updatenotifierwidget.cpp index b56ad6fc3..e1376cb0b 100644 --- a/libpgmodeler_ui/src/updatenotifierwidget.cpp +++ b/libpgmodeler_ui/src/updatenotifierwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/updatenotifierwidget.h b/libpgmodeler_ui/src/updatenotifierwidget.h index 75313326b..b650b2846 100644 --- a/libpgmodeler_ui/src/updatenotifierwidget.h +++ b/libpgmodeler_ui/src/updatenotifierwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/validationinfo.cpp b/libpgmodeler_ui/src/validationinfo.cpp index 6943ae88d..b97ce3ee5 100644 --- a/libpgmodeler_ui/src/validationinfo.cpp +++ b/libpgmodeler_ui/src/validationinfo.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/validationinfo.h b/libpgmodeler_ui/src/validationinfo.h index a0de7ecab..4ff487267 100644 --- a/libpgmodeler_ui/src/validationinfo.h +++ b/libpgmodeler_ui/src/validationinfo.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -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/src/viewwidget.cpp b/libpgmodeler_ui/src/viewwidget.cpp index 0f9d763e4..3c5e08786 100644 --- a/libpgmodeler_ui/src/viewwidget.cpp +++ b/libpgmodeler_ui/src/viewwidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -26,7 +26,7 @@ ViewWidget::ViewWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_VIEW) { try { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; ObjectType types[]={ OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX }; QGridLayout *grid=nullptr; QVBoxLayout *vbox=nullptr; @@ -64,12 +64,12 @@ ViewWidget::ViewWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_VIEW) column_sel=new ObjectSelectorWidget(OBJ_COLUMN, true, this); column_sel->enableObjectCreation(false); - references_tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS, true, this); + references_tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS, true, this); references_tab->setColumnCount(4); references_tab->setHeaderLabel(trUtf8("Col./Expr."),0); references_tab->setHeaderLabel(trUtf8("Alias"),1); references_tab->setHeaderLabel(trUtf8("Alias Col."),2); - references_tab->setHeaderLabel(trUtf8("Flags: SF FW AW VD"),3); + references_tab->setHeaderLabel(trUtf8("Flags: SF FW AW EX VD"),3); cte_expression_cp=new CodeCompletionWidget(cte_expression_txt, true); expression_cp=new CodeCompletionWidget(expression_txt, true); @@ -84,8 +84,8 @@ ViewWidget::ViewWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_VIEW) //Configuring the table objects that stores the triggers and rules for(unsigned i=0, tab_id=1; i < sizeof(types)/sizeof(ObjectType); i++, tab_id++) { - tab=new ObjectTableWidget(ObjectTableWidget::ALL_BUTTONS ^ - (ObjectTableWidget::UPDATE_BUTTON | ObjectTableWidget::MOVE_BUTTONS), true, this); + tab=new ObjectsTableWidget(ObjectsTableWidget::ALL_BUTTONS ^ + (ObjectsTableWidget::UPDATE_BUTTON | ObjectsTableWidget::MOVE_BUTTONS), true, this); objects_tab_map[types[i]]=tab; @@ -172,7 +172,7 @@ ViewWidget::ViewWidget(QWidget *parent): BaseObjectWidget(parent, OBJ_VIEW) } } -ObjectTableWidget *ViewWidget::getObjectTable(ObjectType obj_type) +ObjectsTableWidget *ViewWidget::getObjectTable(ObjectType obj_type) { if(objects_tab_map.count(obj_type) > 0) return(objects_tab_map[obj_type]); @@ -197,7 +197,7 @@ void ViewWidget::handleObject(void) { ObjectType obj_type=BASE_OBJECT; TableObject *object=nullptr; - ObjectTableWidget *obj_table=nullptr; + ObjectsTableWidget *obj_table=nullptr; try { @@ -227,7 +227,7 @@ void ViewWidget::duplicateObject(int curr_row, int new_row) { ObjectType obj_type=BASE_OBJECT; BaseObject *object=nullptr, *dup_object=nullptr; - ObjectTableWidget *obj_table=nullptr; + ObjectsTableWidget *obj_table=nullptr; View *view = dynamic_cast(this->object); int op_id = -1; @@ -332,7 +332,7 @@ ObjectType ViewWidget::getObjectType(QObject *sender) if(sender) { - map::iterator itr, itr_end; + map::iterator itr, itr_end; itr=objects_tab_map.begin(); itr_end=objects_tab_map.end(); @@ -351,7 +351,7 @@ ObjectType ViewWidget::getObjectType(QObject *sender) void ViewWidget::showObjectData(TableObject *object, int row) { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; Trigger *trigger=nullptr; Rule *rule=nullptr; Index *index=nullptr; @@ -412,7 +412,7 @@ void ViewWidget::showObjectData(TableObject *object, int row) void ViewWidget::listObjects(ObjectType obj_type) { - ObjectTableWidget *tab=nullptr; + ObjectsTableWidget *tab=nullptr; unsigned count, i; View *view=nullptr; @@ -440,30 +440,6 @@ void ViewWidget::listObjects(ObjectType obj_type) } } -void ViewWidget::hideEvent(QHideEvent *evento) -{ - //View *view=dynamic_cast(this->object); - ObjectType types[]={ OBJ_TRIGGER, OBJ_RULE }; - - references_tab->removeRows(); - tabWidget->setCurrentIndex(0); - cte_expression_txt->clear(); - - clearReferenceForm(); - - for(unsigned i=0; i < sizeof(types)/sizeof(ObjectType); i++) - { - objects_tab_map[types[i]]->blockSignals(true); - objects_tab_map[types[i]]->removeRows(); - objects_tab_map[types[i]]->blockSignals(false); - } - - if(this->new_object)// && !view->isModified()) - this->cancelConfiguration(); - - BaseObjectWidget::hideEvent(evento); -} - void ViewWidget::clearReferenceForm(void) { column_sel->clearSelector(); @@ -510,25 +486,22 @@ void ViewWidget::handleReference(int ref_idx) if(static_cast(ref_type_cmb->currentIndex())==Reference::REFER_COLUMN) { ref=Reference(dynamic_cast
(table_sel->getSelectedObject()), - dynamic_cast(column_sel->getSelectedObject()), - tab_alias_edt->text().toUtf8(), col_alias_edt->text().toUtf8()); + dynamic_cast(column_sel->getSelectedObject()), + tab_alias_edt->text().toUtf8(), col_alias_edt->text().toUtf8()); } //Creating a reference to an expression else { - ref=Reference(expression_txt->toPlainText(), - expr_alias_edt->text().toUtf8()); + ref=Reference(expression_txt->toPlainText(), expr_alias_edt->text().toUtf8()); } /* The reference must have an SQL application (be between SELECT-FROM, FROM-WHERE or after WHERE), if the user do not check some of these attributes raises an error */ - if(!select_from_chk->isChecked() && - !from_where_chk->isChecked() && - !after_where_chk->isChecked() && + if(!select_from_chk->isChecked() && !from_where_chk->isChecked() && + !after_where_chk->isChecked() && !end_expr_chk->isChecked() && !view_def_chk->isChecked()) throw Exception(ERR_SQL_SCOPE_INV_VIEW_REF,__PRETTY_FUNCTION__,__FILE__,__LINE__); - if(view_def_chk->isChecked()) { select_from_chk->setChecked(false); @@ -537,7 +510,7 @@ void ViewWidget::handleReference(int ref_idx) } showReferenceData(ref, select_from_chk->isChecked(), from_where_chk->isChecked(), - after_where_chk->isChecked(), view_def_chk->isChecked() ,ref_idx); + after_where_chk->isChecked(), end_expr_chk->isChecked(), view_def_chk->isChecked() ,ref_idx); clearReferenceForm(); references_tab->clearSelection(); @@ -580,7 +553,8 @@ void ViewWidget::editReference(int ref_idx) select_from_chk->setChecked(str_aux[0]=='1'); from_where_chk->setChecked(str_aux[1]=='1'); after_where_chk->setChecked(str_aux[2]=='1'); - view_def_chk->setChecked(str_aux[3]=='1'); + end_expr_chk->setChecked(str_aux[3]=='1'); + view_def_chk->setChecked(str_aux[4]=='1'); } void ViewWidget::showObjectName(void) @@ -613,7 +587,7 @@ void ViewWidget::showObjectName(void) } } -void ViewWidget::showReferenceData(Reference refer, bool selec_from, bool from_where, bool after_where, bool view_def, unsigned row) +void ViewWidget::showReferenceData(Reference refer, bool selec_from, bool from_where, bool after_where, bool end_expr, bool view_def, unsigned row) { Table *tab=nullptr; Column *col=nullptr; @@ -648,6 +622,7 @@ void ViewWidget::showReferenceData(Reference refer, bool selec_from, bool from_w str_aux+=(selec_from ? QString("1") : QString("0")); str_aux+=(from_where ? QString("1") : QString("0")); str_aux+=(after_where ? QString("1") : QString("0")); + str_aux+=(end_expr ? QString("1") : QString("0")); str_aux+=(view_def ? QString("1") : QString("0")); references_tab->setCellText(str_aux,row,3); @@ -665,10 +640,12 @@ void ViewWidget::updateCodePreview(void) Reference refer; QString str_aux; TableObject *tab_obj=nullptr; - map::iterator itr, itr_end; - unsigned i, count, i1, expr_type[]={Reference::SQL_REFER_SELECT, + map::iterator itr, itr_end; + unsigned i, count, i1, expr_type[]={ + Reference::SQL_REFER_SELECT, Reference::SQL_REFER_FROM, Reference::SQL_REFER_WHERE, + Reference::SQL_REFER_END_EXPR, Reference::SQL_VIEW_DEFINITION}; aux_view.BaseObject::setName(name_edt->text().toUtf8()); @@ -739,7 +716,7 @@ void ViewWidget::updateCodePreview(void) void ViewWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Schema *schema, View *view, double px, double py) { unsigned i, count; - bool sel_from, from_where, after_where, view_def; + bool sel_from = false, from_where = false, after_where = false, view_def = false, end_expr = false; Reference refer; if(!view) @@ -785,9 +762,10 @@ void ViewWidget::setAttributes(DatabaseModel *model, OperationList *op_list, Sch sel_from=(view->getReferenceIndex(refer,Reference::SQL_REFER_SELECT) >= 0); from_where=(view->getReferenceIndex(refer,Reference::SQL_REFER_FROM) >= 0); after_where=(view->getReferenceIndex(refer,Reference::SQL_REFER_WHERE)>= 0); + end_expr=(view->getReferenceIndex(refer,Reference::SQL_REFER_END_EXPR)>= 0); view_def=(view->getReferenceIndex(refer,Reference::SQL_VIEW_DEFINITION)>= 0); - showReferenceData(refer, sel_from, from_where, after_where, view_def, i); + showReferenceData(refer, sel_from, from_where, after_where, end_expr, view_def, i); } references_tab->blockSignals(false); @@ -805,9 +783,10 @@ void ViewWidget::applyConfiguration(void) View *view=nullptr; ObjectType types[]={ OBJ_TRIGGER, OBJ_RULE, OBJ_INDEX }; unsigned expr_type[]={ Reference::SQL_REFER_SELECT, - Reference::SQL_REFER_FROM, - Reference::SQL_REFER_WHERE, - Reference::SQL_VIEW_DEFINITION}; + Reference::SQL_REFER_FROM, + Reference::SQL_REFER_WHERE, + Reference::SQL_REFER_END_EXPR, + Reference::SQL_VIEW_DEFINITION}; Reference refer; QString str_aux; diff --git a/libpgmodeler_ui/src/viewwidget.h b/libpgmodeler_ui/src/viewwidget.h index de73a85a3..f499437f1 100644 --- a/libpgmodeler_ui/src/viewwidget.h +++ b/libpgmodeler_ui/src/viewwidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -28,7 +28,7 @@ #include #include "baseobjectwidget.h" #include "ui_viewwidget.h" -#include "objecttablewidget.h" +#include "objectstablewidget.h" #include "codecompletionwidget.h" #include "numberedtexteditor.h" @@ -48,9 +48,9 @@ class ViewWidget: public BaseObjectWidget, public Ui::ViewWidget { NumberedTextEditor *cte_expression_txt, *code_txt, *expression_txt; //! \brief Stores all the view references - ObjectTableWidget *references_tab; + ObjectsTableWidget *references_tab; - map objects_tab_map; + map objects_tab_map; SyntaxHighlighter *expression_hl, *code_hl, @@ -64,14 +64,12 @@ class ViewWidget: public BaseObjectWidget, public Ui::ViewWidget { //! \brief Shows the reference at the reference's table void showReferenceData(Reference refer, bool selec_from, bool from_where, - bool after_where, bool view_def, unsigned row); + bool after_where, bool end_expr, bool view_def, unsigned row); void clearReferenceForm(void); - void hideEvent(QHideEvent *); - //! \brief Returns the object table according with the child type - ObjectTableWidget *getObjectTable(ObjectType obj_type); + ObjectsTableWidget *getObjectTable(ObjectType obj_type); ObjectType getObjectType(QObject *sender); void showObjectData(TableObject *object, int row); diff --git a/libpgmodeler_ui/src/welcomewidget.cpp b/libpgmodeler_ui/src/welcomewidget.cpp index 432be4795..13d28a796 100644 --- a/libpgmodeler_ui/src/welcomewidget.cpp +++ b/libpgmodeler_ui/src/welcomewidget.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/src/welcomewidget.h b/libpgmodeler_ui/src/welcomewidget.h index 010d35b26..93bce54e3 100644 --- a/libpgmodeler_ui/src/welcomewidget.h +++ b/libpgmodeler_ui/src/welcomewidget.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libpgmodeler_ui/ui/aboutwidget.ui b/libpgmodeler_ui/ui/aboutwidget.ui index 4eb52f501..5df306c8f 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 - - - - <a href="http://pgmodeler.com.br">http://pgmodeler.com.br</a> - - - 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 &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.com.br</span></a>&gt;</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,458 +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 &lt;</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';">&gt;</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 - - - - - 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. - - - - - - - + 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 &lt;</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';">&gt;</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 &lt;<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.io</span></a>&gt;</p></body></html> + + + Qt::AutoText + + + 5 + + + true + + + + + diff --git a/libpgmodeler_ui/ui/aggregatewidget.ui b/libpgmodeler_ui/ui/aggregatewidget.ui index f310d74a0..059fdfffa 100644 --- a/libpgmodeler_ui/ui/aggregatewidget.ui +++ b/libpgmodeler_ui/ui/aggregatewidget.ui @@ -56,7 +56,7 @@ - + 0 0 diff --git a/libpgmodeler_ui/ui/baseobjectwidget.ui b/libpgmodeler_ui/ui/baseobjectwidget.ui index 13a1cccae..6d8136f24 100644 --- a/libpgmodeler_ui/ui/baseobjectwidget.ui +++ b/libpgmodeler_ui/ui/baseobjectwidget.ui @@ -109,28 +109,6 @@ Comment: - - - - 80 - 170 - 114 - 25 - - - - - 0 - 0 - - - - - 0 - 0 - - - @@ -508,10 +486,34 @@ This will disable the code of all child and referrer objects. + + + + 90 + 160 + 104 + 70 + + + + + 0 + 0 + + + + + 16777215 + 80 + + + + true + + name_edt - comment_edt append_sql_tb edt_perms_tb disable_sql_chk diff --git a/libpgmodeler_ui/ui/bulkdataeditwidget.ui b/libpgmodeler_ui/ui/bulkdataeditwidget.ui new file mode 100644 index 000000000..5cbae3bf3 --- /dev/null +++ b/libpgmodeler_ui/ui/bulkdataeditwidget.ui @@ -0,0 +1,46 @@ + + + BulkDataEditWidget + + + + 0 + 0 + 350 + 40 + + + + + 350 + 40 + + + + Bulk data edit + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + true + + + + + + + + diff --git a/libpgmodeler_ui/ui/columnwidget.ui b/libpgmodeler_ui/ui/columnwidget.ui index c4fc1d246..7bcc7008d 100644 --- a/libpgmodeler_ui/ui/columnwidget.ui +++ b/libpgmodeler_ui/ui/columnwidget.ui @@ -7,7 +7,7 @@ 0 0 347 - 124 + 171 @@ -44,6 +44,20 @@ 4 + + + + false + + + + + + + Identity: + + + @@ -54,10 +68,17 @@ - + + + + Se&quence: + + + + - + 0 0 @@ -67,14 +88,7 @@ - - - - Se&quence: - - - - + @@ -111,7 +125,6 @@ expression_rb def_value_txt sequence_rb - notnull_chk diff --git a/libpgmodeler_ui/ui/configurationform.ui b/libpgmodeler_ui/ui/configurationform.ui index 1f4618b13..e2e72b046 100644 --- a/libpgmodeler_ui/ui/configurationform.ui +++ b/libpgmodeler_ui/ui/configurationform.ui @@ -10,7 +10,7 @@ 0 0 813 - 600 + 660 @@ -22,7 +22,7 @@ 800 - 600 + 660 @@ -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/connectionsconfigwidget.ui b/libpgmodeler_ui/ui/connectionsconfigwidget.ui index 0c551a97a..d1710ec20 100644 --- a/libpgmodeler_ui/ui/connectionsconfigwidget.ui +++ b/libpgmodeler_ui/ui/connectionsconfigwidget.ui @@ -410,7 +410,7 @@ - 1025 + 1 65535 @@ -449,6 +449,9 @@ + + false + @@ -491,7 +494,14 @@ - + + + QLineEdit::Password + + + false + + diff --git a/libpgmodeler_ui/ui/databaseexplorerwidget.ui b/libpgmodeler_ui/ui/databaseexplorerwidget.ui index 07a16d444..82082236c 100644 --- a/libpgmodeler_ui/ui/databaseexplorerwidget.ui +++ b/libpgmodeler_ui/ui/databaseexplorerwidget.ui @@ -6,7 +6,7 @@ 0 0 - 315 + 285 697 @@ -35,46 +35,79 @@ - + true - - - 0 - 0 - + + + 8 + - Toggles the display of system objects. + Toggle the display of filter widget as well the system/extension objects. - System + Data &Grid - - false + + + :/icones/icones/filter.png:/icones/icones/filter.png + + + + 22 + 22 + + + + Alt+G + + + QToolButton::InstantPopup + + + Qt::ToolButtonIconOnly - + true - - - 0 - 0 - + + + 8 + - Toggles the display of extension objects + Sort items alphabetically. When unchecked, items are sorted by OID. - Extension + Sort alphabetically + + + + :/icones/icones/sortasc.png:/icones/icones/sortasc.png + + + + 22 + 22 + + + + + + + true - false + true + + + Qt::ToolButtonIconOnly @@ -159,9 +192,6 @@ 22 - - Ctrl+S - @@ -187,6 +217,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + diff --git a/libpgmodeler_ui/ui/databaseimportform.ui b/libpgmodeler_ui/ui/databaseimportform.ui index 8b0fed15c..39235995f 100644 --- a/libpgmodeler_ui/ui/databaseimportform.ui +++ b/libpgmodeler_ui/ui/databaseimportform.ui @@ -32,7 +32,7 @@ - Database Import + Import database @@ -119,7 +119,7 @@ - Database import + Import database @@ -195,129 +195,7 @@ - - - - - 0 - 0 - - - - Origin point: - - - - - - - Starting point where objects will be put. - - - 1 - - - 1000.000000000000000 - - - 50.000000000000000 - - - - - - - - 0 - 0 - - - - Tables per row: - - - - - - - - 0 - 0 - - - - Tables per row - - - 1 - - - 20 - - - 5 - - - - - - - - 0 - 0 - - - - Spacing: - - - - - - - Schemas per row - - - 1 - - - 20 - - - 3 - - - - - - - Spacing between objects - - - 1 - - - 1000.000000000000000 - - - 50.000000000000000 - - - - - - - - 0 - 0 - - - - Schemas per row: - - - - + @@ -365,7 +243,7 @@ - + Qt::Vertical @@ -378,46 +256,68 @@ - - + + - + 0 0 - - QComboBox::AdjustToMinimumContentsLengthWithIcon + + All catalog queries as well the created objects' source code are printed to standard output (stdout). - + + + + + Debug mode + + + + + + + + 0 + 0 + + + - 18 - 18 + 22 + 22 + + + + + 22 + 22 - - + + - + - Random colors will be assigned to imported relationships facilitating the identification of links between tables mainly in large models. + Create all imported objects in the current working model instead of create a new one. - Random colors for relationships + Import objects to the working model - true + false - + 0 @@ -440,7 +340,7 @@ - + @@ -485,7 +385,7 @@ - + @@ -530,7 +430,7 @@ - + @@ -575,68 +475,46 @@ - - + + - + 0 0 - - All catalog queries as well the created objects' source code are printed to standard output (stdout). - - - - - - Debug mode - - - - - - - - 0 - 0 - - - - - 22 - 22 - + + QComboBox::AdjustToMinimumContentsLengthWithIcon - + - 22 - 22 + 18 + 18 - - + + - + - Create all imported objects in the current working model instead of create a new one. + Random colors will be assigned to imported relationships facilitating the identification of links between tables mainly in large models. - Import objects to the working model + Random colors for relationships - false + true - + 0 @@ -1321,10 +1199,6 @@ connections_cmb - origin_sb - tabs_per_row_sb - obj_spacing_sb - sch_per_row_sb resolve_deps_chk import_sys_objs_chk import_ext_objs_chk diff --git a/libpgmodeler_ui/ui/databasewidget.ui b/libpgmodeler_ui/ui/databasewidget.ui index 9d495e1c6..4bf82b86a 100644 --- a/libpgmodeler_ui/ui/databasewidget.ui +++ b/libpgmodeler_ui/ui/databasewidget.ui @@ -6,8 +6,8 @@ 0 0 - 428 - 198 + 453 + 223 @@ -51,71 +51,45 @@ 4 - - - - - 0 - 25 - - - - true - - - QComboBox::InsertAlphabetically - - - - - + + - + 0 0 - 85 + 96 0 - - - 50 - false - false - - - LC_COLLATE: + Template DB: - - - - - 0 - 0 - - + + - 70 - 0 + 0 + 25 - - - 50 - false - false - + + + + + + + 0 + 0 + - LC_CTYPE: + Model Author: @@ -129,18 +103,8 @@ - - - - - 0 - 25 - - - - - - + + 0 @@ -154,50 +118,60 @@ - Template DB: + Encoding: - - - - - 0 - 0 - - - - Model Author: + + + + + 0 + 25 + - - + + - + 0 0 - 96 + 85 0 + + + 50 + false + false + + - Encoding: + LC_COLLATE: - - + + 0 25 + + true + + + QComboBox::InsertAlphabetically + @@ -245,6 +219,32 @@ + + + + + 0 + 0 + + + + + 70 + 0 + + + + + 50 + false + false + + + + LC_CTYPE: + + + @@ -261,7 +261,67 @@ - + + + + + 0 + 0 + + + + + 96 + 0 + + + + + 50 + false + false + + + + Options: + + + + + + + + + Allow connections + + + true + + + + + + + Is template + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + Qt::Vertical diff --git a/libpgmodeler_ui/ui/datamanipulationform.ui b/libpgmodeler_ui/ui/datamanipulationform.ui index 5f45f6d49..995d5ea70 100644 --- a/libpgmodeler_ui/ui/datamanipulationform.ui +++ b/libpgmodeler_ui/ui/datamanipulationform.ui @@ -531,9 +531,6 @@ 22 - - Ctrl+X - QToolButton::InstantPopup @@ -669,6 +666,43 @@ + + + + false + + + + 0 + 0 + + + + + 8 + + + + Change the values of all selected cells at once + + + + :/icones/icones/bulkedit.png:/icones/icones/bulkedit.png + + + + 22 + 22 + + + + Ctrl+E + + + Qt::ToolButtonIconOnly + + + @@ -1422,10 +1456,13 @@ 0 - 999999 + 1000000 + + + 50 - 500 + 1000 diff --git a/libpgmodeler_ui/ui/domainwidget.ui b/libpgmodeler_ui/ui/domainwidget.ui index 97d16c2af..4e4061931 100644 --- a/libpgmodeler_ui/ui/domainwidget.ui +++ b/libpgmodeler_ui/ui/domainwidget.ui @@ -6,111 +6,132 @@ 0 0 - 471 - 187 + 487 + 132 - 0 + 4 - 0 + 4 - 0 + 4 - 0 + 4 - - - - Default Value: + + + + 0 - - - - - - - - - Constraint - - - - 4 - - - 4 - - - 4 - - - 4 - - - - - Name: - - - - - - - - - - Not Null: - - - - - - - - - - - - - - Check Expr.: - - - - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 16777215 - 16777215 - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - - - - + + + Attributes + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + Default Value: + + + + + + + + + + + + Not null + + + + + + + + + + Check constraints + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + Name: + + + + + + + + + + Expression: + + + + + + + + 0 + 0 + + + + + 0 + 50 + + + + + 16777215 + 16777215 + + + + Qt::ScrollBarAsNeeded + + + Qt::ScrollBarAsNeeded + + + + + diff --git a/libpgmodeler_ui/ui/donatewidget.ui b/libpgmodeler_ui/ui/donatewidget.ui index d150e9660..82b6988a5 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 9bdea1a4c..d5972e866 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/functionwidget.ui b/libpgmodeler_ui/ui/functionwidget.ui index 1699ee59b..bbc468d9c 100644 --- a/libpgmodeler_ui/ui/functionwidget.ui +++ b/libpgmodeler_ui/ui/functionwidget.ui @@ -205,6 +205,12 @@ 16777215 + + + 50 + false + + Language: diff --git a/libpgmodeler_ui/ui/generalconfigwidget.ui b/libpgmodeler_ui/ui/generalconfigwidget.ui index e361adc35..19c46a92c 100644 --- a/libpgmodeler_ui/ui/generalconfigwidget.ui +++ b/libpgmodeler_ui/ui/generalconfigwidget.ui @@ -1011,50 +1011,14 @@ 4 - - - - - - - false - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - SQL history max. length: - - - - - - - true - - - - - + + - Souce code editor: + Souce code editor args: - + @@ -1074,7 +1038,7 @@ 100 - 2000 + 10000 100 @@ -1184,15 +1148,30 @@ - - - - Configurations directory: + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + - - + + 0 @@ -1212,7 +1191,7 @@ - Browse the source code editor application + Open in file manager @@ -1229,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 @@ -1243,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 @@ -1280,7 +1257,14 @@ - + + + + true + + + + @@ -1290,42 +1274,44 @@ - - - - Souce code editor args: - - - - + User interface language: - - - - 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 - 22 - 22 + 0 + 0 + + 16777215 + 16777215 + + + + Browse the source code editor application + + + + + + + :/icones/icones/abrir.png:/icones/icones/abrir.png + + 22 22 @@ -1333,6 +1319,20 @@ + + + + Souce code editor: + + + + + + + Configurations directory: + + + diff --git a/libpgmodeler_ui/ui/mainwindow.ui b/libpgmodeler_ui/ui/mainwindow.ui index fa4888bde..fa5ee1db0 100644 --- a/libpgmodeler_ui/ui/mainwindow.ui +++ b/libpgmodeler_ui/ui/mainwindow.ui @@ -1381,7 +1381,7 @@ - false + true @@ -1391,7 +1391,7 @@ &Diff - Determine the changes between model and database + Determine the changes between model/database and another database Ctrl+Shift+D @@ -1511,7 +1511,7 @@ Arrange objects - Rearrange objects on the canvas hierarchically + Rearrange objects over the canvas diff --git a/libpgmodeler_ui/ui/messagebox.ui b/libpgmodeler_ui/ui/messagebox.ui index 9f1a23511..38e5e05b2 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/modeldatabasediffform.ui b/libpgmodeler_ui/ui/modeldatabasediffform.ui index 69fd7a711..4fccfe761 100644 --- a/libpgmodeler_ui/ui/modeldatabasediffform.ui +++ b/libpgmodeler_ui/ui/modeldatabasediffform.ui @@ -10,7 +10,7 @@ 0 0 680 - 500 + 570 @@ -22,7 +22,7 @@ 680 - 500 + 570 @@ -32,7 +32,7 @@ - Database model diff + Diff tool @@ -130,7 +130,7 @@ - Generate diff from model + Generate diff code @@ -177,6 +177,198 @@ + + + + + 0 + 0 + + + + + 0 + 0 + + + + Source database + + + false + + + false + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + 0 + + + + + + 0 + 0 + + + + Current model: + + + true + + + + + + + + 0 + 0 + + + + + 75 + false + true + + + + (model) + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + 0 + 0 + + + + Database: + + + + + + + false + + + + 50 + 30 + + + + + 20 + + + 0 + + + 0 + + + 0 + + + + + Connection: + + + + + + + + 0 + 0 + + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + + 18 + 18 + + + + + + + + false + + + + 0 + 0 + + + + Database: + + + -1 + + + + + + + false + + + + 0 + 0 + + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + + 18 + 18 + + + + + + + + + + @@ -192,7 +384,7 @@ - Input database + Compare to @@ -582,22 +774,22 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - + + + + Qt::Vertical + + + + 0 + 0 + + + + @@ -709,9 +901,9 @@ - - - + + + @@ -726,8 +918,65 @@ - - + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 12 + 21 + + + + + + + + false + + + + + + Froce the generation of DROP commands for columns and constraints that exist in database but not in the model. This is useful when diff a partial model against the complete database and the user needs to drop columns and constraint but preserve the rest of the objects. + + + Drop missing columns and constraints + + + false + + + + + 0 @@ -851,7 +1100,7 @@ Clears the data of all tables which will have columns modified. This is useful to avoid errors related to type casting. <strong>WARNING:</strong> DO NOT use this option on production servers and always make a backup before use it. - Trucate tables before alter columns + Truncate tables before alter columns diff --git a/libpgmodeler_ui/ui/modelexportform.ui b/libpgmodeler_ui/ui/modelexportform.ui index 1774bf317..e0003788a 100644 --- a/libpgmodeler_ui/ui/modelexportform.ui +++ b/libpgmodeler_ui/ui/modelexportform.ui @@ -32,7 +32,7 @@ - Model Export + Export model diff --git a/libpgmodeler_ui/ui/modelobjectswidget.ui b/libpgmodeler_ui/ui/modelobjectswidget.ui index 1eeafdb64..abbf155e5 100644 --- a/libpgmodeler_ui/ui/modelobjectswidget.ui +++ b/libpgmodeler_ui/ui/modelobjectswidget.ui @@ -9,8 +9,8 @@ 0 0 - 372 - 457 + 489 + 580 @@ -54,87 +54,6 @@ 4 - - - - - 9 - - - - - 0 - - - 2 - - - 2 - - - 2 - - - 0 - - - - - - 9 - false - - - - Model Objects - - - - - - - Qt::Horizontal - - - - 156 - 5 - - - - - - - - - 20 - 20 - - - - - 20 - 20 - - - - Hide this widget - - - ... - - - - :/icones/icones/fechar1.png:/icones/icones/fechar1.png - - - true - - - - - - @@ -466,7 +385,7 @@ - Visible Object Types + Visible object types false @@ -581,6 +500,144 @@ + + + + + 9 + + + + + 0 + + + 2 + + + 2 + + + 2 + + + 0 + + + + + + 9 + false + + + + Model objects + + + + + + + Qt::Horizontal + + + + 156 + 5 + + + + + + + + + 20 + 20 + + + + + 20 + 20 + + + + Hide this widget + + + ... + + + + :/icones/icones/fechar1.png:/icones/icones/fechar1.png + + + true + + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + 0 + 0 + + + + Filter: + + + + + + + true + + + true + + + + + + + By ID + + + + + + @@ -767,7 +824,7 @@ - :/icones/icones/config.png:/icones/icones/config.png + :/icones/icones/filter.png:/icones/icones/filter.png @@ -855,49 +912,6 @@ - - - - 0 - - - 0 - - - - - true - - - - 0 - 0 - - - - Filter: - - - - - - - true - - - true - - - - - - - By ID - - - - - diff --git a/libpgmodeler_ui/ui/modelvalidationwidget.ui b/libpgmodeler_ui/ui/modelvalidationwidget.ui index 653056064..fdc016a93 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/newobjectoverlaywidget.ui b/libpgmodeler_ui/ui/newobjectoverlaywidget.ui index 01b7f374c..54d72ddc2 100644 --- a/libpgmodeler_ui/ui/newobjectoverlaywidget.ui +++ b/libpgmodeler_ui/ui/newobjectoverlaywidget.ui @@ -7,7 +7,7 @@ 0 0 408 - 638 + 702 @@ -107,7 +107,7 @@ 6 - + 0 @@ -130,11 +130,11 @@ Qt::NoFocus - Tag + Schema - :/icones/icones/tag.png:/icones/icones/tag.png + :/icones/icones/schema.png:/icones/icones/schema.png @@ -150,8 +150,8 @@ - - + + 0 @@ -174,11 +174,11 @@ Qt::NoFocus - Cast + Tablespace - :/icones/icones/cast.png:/icones/icones/cast.png + :/icones/icones/tablespace.png:/icones/icones/tablespace.png @@ -186,9 +186,6 @@ 32 - - A - QToolButton::InstantPopup @@ -197,8 +194,8 @@ - - + + 0 @@ -221,11 +218,11 @@ Qt::NoFocus - Textbox + Cast - :/icones/icones/textbox.png:/icones/icones/textbox.png + :/icones/icones/cast.png:/icones/icones/cast.png @@ -233,6 +230,9 @@ 32 + + A + QToolButton::InstantPopup @@ -242,7 +242,7 @@ - + 0 @@ -265,11 +265,11 @@ Qt::NoFocus - Tablespace + Role - :/icones/icones/tablespace.png:/icones/icones/tablespace.png + :/icones/icones/role.png:/icones/icones/role.png @@ -286,7 +286,7 @@ - + 0 @@ -309,11 +309,11 @@ Qt::NoFocus - Schema + Extension - :/icones/icones/schema.png:/icones/icones/schema.png + :/icones/icones/extension.png:/icones/icones/extension.png @@ -329,8 +329,8 @@ - - + + 0 @@ -353,11 +353,11 @@ Qt::NoFocus - Language + Event Trigger - :/icones/icones/language.png:/icones/icones/language.png + :/icones/icones/eventtrigger.png:/icones/icones/eventtrigger.png @@ -374,7 +374,7 @@ - + 0 @@ -397,11 +397,11 @@ Qt::NoFocus - Role + Language - :/icones/icones/role.png:/icones/icones/role.png + :/icones/icones/language.png:/icones/icones/language.png @@ -417,8 +417,8 @@ - - + + 0 @@ -441,11 +441,11 @@ Qt::NoFocus - Event Trigger + Generic SQL - :/icones/icones/eventtrigger.png:/icones/icones/eventtrigger.png + :/icones/icones/genericsql.png:/icones/icones/genericsql.png @@ -461,35 +461,8 @@ - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 6 - - - + + 0 @@ -509,14 +482,14 @@ - Qt::StrongFocus + Qt::NoFocus - Type + Tag - :/icones/icones/usertype.png:/icones/icones/usertype.png + :/icones/icones/tag.png:/icones/icones/tag.png @@ -532,8 +505,8 @@ - - + + 0 @@ -556,11 +529,11 @@ Qt::NoFocus - Conversion + Textbox - :/icones/icones/conversion.png:/icones/icones/conversion.png + :/icones/icones/textbox.png:/icones/icones/textbox.png @@ -576,8 +549,35 @@ - - + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 6 + + + 0 @@ -597,14 +597,14 @@ - Qt::NoFocus + Qt::StrongFocus - Sequence + Type - :/icones/icones/sequence.png:/icones/icones/sequence.png + :/icones/icones/usertype.png:/icones/icones/usertype.png @@ -620,8 +620,8 @@ - - + + 0 @@ -644,11 +644,11 @@ Qt::NoFocus - Table + Conversion - :/icones/icones/table.png:/icones/icones/table.png + :/icones/icones/conversion.png:/icones/icones/conversion.png @@ -664,8 +664,8 @@ - - + + 0 @@ -688,11 +688,11 @@ Qt::NoFocus - Operator + Aggregate - :/icones/icones/operator.png:/icones/icones/operator.png + :/icones/icones/aggregate.png:/icones/icones/aggregate.png @@ -708,8 +708,8 @@ - - + + 0 @@ -732,11 +732,11 @@ Qt::NoFocus - Aggregate + Operator - :/icones/icones/aggregate.png:/icones/icones/aggregate.png + :/icones/icones/operator.png:/icones/icones/operator.png @@ -752,8 +752,8 @@ - - + + 0 @@ -776,11 +776,11 @@ Qt::NoFocus - Collation + Domain - :/icones/icones/collation.png:/icones/icones/collation.png + :/icones/icones/domain.png:/icones/icones/domain.png @@ -796,8 +796,8 @@ - - + + 0 @@ -820,11 +820,11 @@ Qt::NoFocus - Op. Class + Collation - :/icones/icones/opclass.png:/icones/icones/opclass.png + :/icones/icones/collation.png:/icones/icones/collation.png @@ -840,8 +840,8 @@ - - + + 0 @@ -864,11 +864,11 @@ Qt::NoFocus - Domain + Sequence - :/icones/icones/domain.png:/icones/icones/domain.png + :/icones/icones/sequence.png:/icones/icones/sequence.png @@ -884,7 +884,7 @@ - + @@ -928,8 +928,8 @@ - - + + 0 @@ -952,11 +952,11 @@ Qt::NoFocus - Extension + Table - :/icones/icones/extension.png:/icones/icones/extension.png + :/icones/icones/table.png:/icones/icones/table.png @@ -972,7 +972,7 @@ - + @@ -1016,7 +1016,7 @@ - + @@ -1060,8 +1060,8 @@ - - + + 0 @@ -1084,11 +1084,11 @@ Qt::NoFocus - Permissions + Op. Class - :/icones/icones/permission.png:/icones/icones/permission.png + :/icones/icones/opclass.png:/icones/icones/opclass.png @@ -1104,8 +1104,8 @@ - - + + 0 @@ -1128,11 +1128,11 @@ Qt::NoFocus - Generic SQL + Permissions - :/icones/icones/genericsql.png:/icones/icones/genericsql.png + :/icones/icones/permission.png:/icones/icones/permission.png @@ -1351,7 +1351,51 @@ - + + + + + 0 + 0 + + + + + 95 + 50 + + + + + 50 + false + + + + Qt::NoFocus + + + Rule + + + + :/icones/icones/rule.png:/icones/icones/rule.png + + + + 32 + 32 + + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextUnderIcon + + + + @@ -1395,8 +1439,8 @@ - - + + 0 @@ -1419,11 +1463,11 @@ Qt::NoFocus - Rule + Policy - :/icones/icones/rule.png:/icones/icones/rule.png + :/icones/icones/policy.png:/icones/icones/policy.png diff --git a/libpgmodeler_ui/ui/objectfinderwidget.ui b/libpgmodeler_ui/ui/objectfinderwidget.ui index 2131cc0b5..48375a48b 100644 --- a/libpgmodeler_ui/ui/objectfinderwidget.ui +++ b/libpgmodeler_ui/ui/objectfinderwidget.ui @@ -38,22 +38,19 @@ 4 - - + + 0 0 - - - 50 - 0 - - - Pattern: + ... + + + 10 @@ -73,10 +70,10 @@ - - + + - true + false @@ -91,14 +88,14 @@ - Defines the search filter + Clears the search results - Filter + Clear - :/icones/icones/filter.png:/icones/icones/filter.png + :/icones/icones/limpartexto.png:/icones/icones/limpartexto.png @@ -106,54 +103,77 @@ 20 - - true - Qt::ToolButtonTextBesideIcon - - - - false - + + - + 0 0 - 0 + 50 0 + + Pattern: + + + + + + + + 20 + 20 + + + + + 20 + 20 + + - Clears the search results + Hide this widget - Clear + ... - :/icones/icones/limpartexto.png:/icones/icones/limpartexto.png + :/icones/icones/fechar1.png:/icones/icones/fechar1.png - + + true + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + - 20 + 40 20 - - Qt::ToolButtonTextBesideIcon - - + - - + + true @@ -170,14 +190,14 @@ - Highlight graphical objects when selecting them or their children on the result list + Defines the search filter - Highlight + Filter - :/icones/icones/selmovobjeto.png:/icones/icones/selmovobjeto.png + :/icones/icones/filter.png:/icones/icones/filter.png @@ -193,68 +213,51 @@ - - + + + + false + - + 0 0 - - ... - - - 10 - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 40 - 20 - - - - - - - 20 - 20 - - - - - 20 - 20 + 0 + 0 - Hide this widget + (Un)selects the graphical objects in the results grid - ... + Select - :/icones/icones/fechar1.png:/icones/icones/fechar1.png + :/icones/icones/selmovobjeto.png:/icones/icones/selmovobjeto.png - - true + + + 20 + 20 + + + + false + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon - + Qt::Vertical @@ -651,6 +654,50 @@ + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + Fades outs all the graphical objects in the results grid (or those not listed). The current fade in/out state of all objects is modified. + + + Fade out + + + + :/icones/icones/fadeout.png:/icones/icones/fadeout.png + + + + 20 + 20 + + + + false + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + @@ -658,7 +705,7 @@ find_btn filter_btn clear_res_btn - highlight_btn + select_btn obj_types_lst regexp_chk exact_match_chk diff --git a/libpgmodeler_ui/ui/objecttablewidget.ui b/libpgmodeler_ui/ui/objectstablewidget.ui similarity index 99% rename from libpgmodeler_ui/ui/objecttablewidget.ui rename to libpgmodeler_ui/ui/objectstablewidget.ui index 105745451..6a9d6b268 100644 --- a/libpgmodeler_ui/ui/objecttablewidget.ui +++ b/libpgmodeler_ui/ui/objectstablewidget.ui @@ -1,7 +1,7 @@ - ObjectTableWidget - + ObjectsTableWidget + 0 diff --git a/libpgmodeler_ui/ui/policywidget.ui b/libpgmodeler_ui/ui/policywidget.ui new file mode 100644 index 000000000..e06bde08b --- /dev/null +++ b/libpgmodeler_ui/ui/policywidget.ui @@ -0,0 +1,174 @@ + + + PolicyWidget + + + + 0 + 0 + 520 + 400 + + + + + 520 + 380 + + + + + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + Basics + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + Command: + + + + + + + Permissive + + + true + + + + + + + + + + Qt::Horizontal + + + + 200 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + + + 0 + + + + Roles + + + + + Expressions + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + USING: + + + + + + + + 0 + 0 + + + + + + + + CHECK: + + + + + + + + 0 + 0 + + + + + + + + + + + + + diff --git a/libpgmodeler_ui/ui/relationshipconfigwidget.ui b/libpgmodeler_ui/ui/relationshipconfigwidget.ui index 192ef6c27..76c7f8e4b 100644 --- a/libpgmodeler_ui/ui/relationshipconfigwidget.ui +++ b/libpgmodeler_ui/ui/relationshipconfigwidget.ui @@ -6,8 +6,8 @@ 0 0 - 577 - 410 + 584 + 605 @@ -81,12 +81,216 @@ 4 + + + + + + + + This mode renders the relationships in crow's foot notation which has a better semantics and readability. It also determines the optimal point where the relationship is connected on the tables' edges taking their position into account. + + + Crow's foot notation + + + true + + + true + + + true + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + + + Qt::Horizontal + + + + 368 + 20 + + + + + + + + true + + + + 0 + 0 + + + + + 555 + 81 + + + + + 555 + 81 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + Qt::PlainText + + + :/imagens/imagens/crows_foot_notation.png + + + Qt::NoTextInteraction + + + + + + + + + + + + + This mode determines the optimal point where the relationship is connected on the tables' edges taking their position into account. It implies the usage of the classical ER notation. + + + Connect tables' edges + + + true + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + + 22 + 22 + + + + + + + + + + Qt::Horizontal + + + + 338 + 20 + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 0 + + + + + 555 + 16777215 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + Qt::PlainText + + + :/imagens/imagens/rel_tab_edges.png + + + Qt::NoTextInteraction + + + + + - + 0 @@ -94,12 +298,15 @@ - This mode is available only for <strong>one-to-one</strong>, <strong>one-to-many</strong> and <strong>fk relationships</strong> but provides a better semantics when linking tables by placing the lines on the exact point where the relationship occurs. + This mode is available only for <strong>one-to-one</strong>, <strong>one-to-many</strong> and <strong>fk relationships</strong> but provides a better semantics when linking tables by placing the lines on the exact point where the relationship occurs. It implies the usage of the classical ER notation. Connect FK to PK columns + false + + true @@ -143,6 +350,9 @@ + + false + 0 @@ -157,7 +367,7 @@ - 561 + 555 101 @@ -188,13 +398,16 @@ - + - This mode is the classical one. It connects the relationship to tables through their central points. + This mode is the classical one. It connects the relationship to tables through their central points. It implies the usage of the classical ER notation. Connect tables' center points + + true + @@ -253,7 +466,7 @@ - 561 + 555 101 @@ -283,7 +496,7 @@ - + Qt::Vertical @@ -834,8 +1047,8 @@ settings_twg - fk_to_pk_chk - center_pnts_chk + fk_to_pk_rb + center_pnts_rb deferrable_chk deferral_cmb del_action_cmb diff --git a/libpgmodeler_ui/ui/rolewidget.ui b/libpgmodeler_ui/ui/rolewidget.ui index 57ca17886..9d746c737 100644 --- a/libpgmodeler_ui/ui/rolewidget.ui +++ b/libpgmodeler_ui/ui/rolewidget.ui @@ -6,7 +6,7 @@ 0 0 - 530 + 517 455 @@ -131,38 +131,45 @@ - + - Inherit Permissions + Inherit permissions - + - Can create Database + Can create database - - + + - Can Login + Bypass RLS - - + + - Can create Role + Can use replication - - + + + + Can login + + + + + - Can use Replication + Can create role @@ -230,11 +237,7 @@ validity_dte conn_limit_sb superusr_chk - inh_perm_chk create_db_chk - can_login_chk - create_role_chk - can_replicate_chk members_twg diff --git a/libpgmodeler_ui/ui/sceneinfowidget.ui b/libpgmodeler_ui/ui/sceneinfowidget.ui index 516448513..ef15a45fc 100644 --- a/libpgmodeler_ui/ui/sceneinfowidget.ui +++ b/libpgmodeler_ui/ui/sceneinfowidget.ui @@ -111,12 +111,12 @@ - + 6 - + 0 @@ -136,7 +136,7 @@ - Currently selected object(s) + Current zoom factor QFrame::NoFrame @@ -148,7 +148,7 @@ - :/icones/icones/table.png + :/icones/icones/objselect.png true @@ -162,7 +162,7 @@ - + 50 @@ -176,7 +176,7 @@ - Currently selected object(s) + Current zoom factor - @@ -186,12 +186,12 @@ - + 6 - + 0 @@ -211,7 +211,7 @@ - Dimensions of the selected object(s) + Currently selected object(s) QFrame::NoFrame @@ -223,7 +223,7 @@ - :/icones/icones/alinhargrade.png + :/icones/icones/table.png true @@ -237,7 +237,7 @@ - + 50 @@ -251,7 +251,7 @@ - Dimensions of the selected object(s) + Currently selected object(s) - @@ -261,12 +261,12 @@ - + 6 - + 0 @@ -286,7 +286,7 @@ - Current zoom factor + Dimensions of the selected object(s) QFrame::NoFrame @@ -298,7 +298,7 @@ - :/icones/icones/objselect.png + :/icones/icones/alinhargrade.png true @@ -312,7 +312,7 @@ - + 50 @@ -326,7 +326,7 @@ - Current zoom factor + Dimensions of the selected object(s) - diff --git a/libpgmodeler_ui/ui/sourcecodewidget.ui b/libpgmodeler_ui/ui/sourcecodewidget.ui index aab09a0b3..4fd516dcc 100644 --- a/libpgmodeler_ui/ui/sourcecodewidget.ui +++ b/libpgmodeler_ui/ui/sourcecodewidget.ui @@ -60,7 +60,7 @@ - 30 + 15 20 @@ -96,22 +96,6 @@ - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - diff --git a/libpgmodeler_ui/ui/sqlexecutionwidget.ui b/libpgmodeler_ui/ui/sqlexecutionwidget.ui index 186808550..16305c675 100644 --- a/libpgmodeler_ui/ui/sqlexecutionwidget.ui +++ b/libpgmodeler_ui/ui/sqlexecutionwidget.ui @@ -198,9 +198,6 @@ 22 - - Ctrl+S - true @@ -316,7 +313,7 @@ - Alt+X + Alt+T false @@ -360,7 +357,7 @@ - Alt+X + Alt+X false @@ -584,7 +581,7 @@ 4 - + @@ -608,14 +605,8 @@ 0 - - - - true - - - true - + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed @@ -625,34 +616,24 @@ QAbstractItemView::ContiguousSelection - - QAbstractItemView::ScrollPerItem - - - QAbstractItemView::ScrollPerPixel - - + + true + + false - + true + + true + 25 25 - - - ... - - - - - ... - - diff --git a/libpgmodeler_ui/ui/sqltoolwidget.ui b/libpgmodeler_ui/ui/sqltoolwidget.ui index 4649c3c38..5f32cd53d 100644 --- a/libpgmodeler_ui/ui/sqltoolwidget.ui +++ b/libpgmodeler_ui/ui/sqltoolwidget.ui @@ -6,7 +6,7 @@ 0 0 - 707 + 658 469 @@ -228,7 +228,7 @@ - 310 + 285 0 diff --git a/libpgmodeler_ui/ui/tablewidget.ui b/libpgmodeler_ui/ui/tablewidget.ui index faadb57cd..b04805a16 100644 --- a/libpgmodeler_ui/ui/tablewidget.ui +++ b/libpgmodeler_ui/ui/tablewidget.ui @@ -6,8 +6,8 @@ 0 0 - 473 - 255 + 513 + 348 @@ -39,17 +39,40 @@ - 2 + 4 - 2 + 4 - 2 + 4 - 2 + 4 + + + + With OID + + + false + + + + + + + + 0 + 0 + + + + Unlogged + + + @@ -69,18 +92,24 @@ - - - - With OID + + + + + 0 + 0 + - - false + + Enable row level security - - + + + + true + 0 @@ -88,14 +117,20 @@ - Generate ALTER for columns/constraints + Force RLS for owner - - + + + + + 0 + 0 + + - Unlogged + Generate ALTER for columns/constraints @@ -132,6 +167,11 @@ &Indexes + + + &Policies + + &Tables diff --git a/libpgmodeler_ui/ui/viewwidget.ui b/libpgmodeler_ui/ui/viewwidget.ui index a4225c832..8f2ede6e1 100644 --- a/libpgmodeler_ui/ui/viewwidget.ui +++ b/libpgmodeler_ui/ui/viewwidget.ui @@ -6,7 +6,7 @@ 0 0 - 639 + 816 453 @@ -34,37 +34,51 @@ - 4 + 6 - 4 + 6 - 4 + 6 - 4 + 6 6 - - - - - 0 - 0 - + + + + + 100 + 0 + - Expression Alias: + Reference Type: - - + + + + + Column + + + + + Expression + + + + + + - Column: + Used in: @@ -88,25 +102,38 @@ - - + + + + + 0 + 0 + + + + + + - Used in: + Column: - - + + - + 0 0 + + Column Alias: + - - + + 0 @@ -115,21 +142,27 @@ - - - - - Column - - - - - Expression - - + + + + Expression: + + + + + + + + 0 + 0 + + + + Expression Alias: + - + @@ -152,22 +185,9 @@ - - - - - 100 - 0 - - - - Reference Type: - - - - - + + @@ -175,38 +195,53 @@ 0 + + The element will be used as part of the SELECT statement to retrieve columns or expressions that will compose the view's columns + - SELECT-FROM + SELECT ... - - + + 0 0 + + The element will be used as part of the WHERE clause in form of conditional expression + - FROM-WHERE + WHERE ... - - + + 0 0 + + + 137 + 0 + + + + The element is used in the FROM portion of the command in order to reference tables or construct JOIN statements + - After WHERE + FROM ... - + @@ -214,33 +249,45 @@ 0 + + The element's expression is used exclusively as the view's definition + View Definition + + + + + 0 + 0 + + + + The element will be appended to the very end of the view's definition. This is useful when using GROUP BY/HAVING statements + + + End expression + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - - - Expression: - - - - - - - - 0 - 0 - - - - Column Alias: - - - diff --git a/libutils/src/exception.cpp b/libutils/src/exception.cpp index 66e35d6e2..7e731343e 100644 --- a/libutils/src/exception.cpp +++ b/libutils/src/exception.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -126,7 +126,7 @@ QString Exception::messages[ERROR_COUNT][2]={ {"ERR_ASG_INV_MAX_SIZE_OP_LIST", QT_TR_NOOP("Assignment of invalid maximum size to operation list!")}, {"ERR_FILE_DIR_NOT_WRITTEN", QT_TR_NOOP("Unable to write the file or directory `%1'! Make sure the output directory exists, or if the user has write permissions over it!")}, {"ERR_FILE_NOT_WRITTER_INV_DEF", QT_TR_NOOP("Unable to write the file `%1' due to one or more errors in the definition generation process!")}, - {"ERR_DUPLIC_RELATIONSHIP", QT_TR_NOOP("There is already a relationship between `%1' (%2) and `%3' (%4) in the model!")}, + {"ERR_DUPLIC_RELATIONSHIP", QT_TR_NOOP("There is already a relationship between `%1' (%2) and `%3' (%4) in the model! When using relationships of the type generalization, copy and one-to-one there can't be other relationships linked to the pair of tables.")}, {"ERR_INS_REL_GENS_REDUNDACY", QT_TR_NOOP("The configuration of the relationship `%1' generates a redundancy between the relationships `%2'. Redundancy on identifier or generalization/copy relationships are not accepted since they result in incorrect column spreading making the model inconsistent!")}, {"ERR_INVALIDATED_OBJECTS", QT_TR_NOOP("One or more objects were invalidated and automatically removed because they were referencing table columns which were included through relationships and which no longer exists due to disconnection of relationships or exclusion of such generated columns!")}, {"ERR_INV_PRIM_KEY_ALOCATION", QT_TR_NOOP("The primary key `%1' can only be allocated if declared within a block of code that defines a table or relationship!")}, @@ -227,7 +227,7 @@ QString Exception::messages[ERROR_COUNT][2]={ {"ERR_INV_ID_SWAP_SAME_OBJECT", QT_TR_NOOP("Invalid object id swapping operation! The objects involved are the same!")}, {"ERR_INV_ID_SWAP_INV_OBJ_TYPE", QT_TR_NOOP("Invalid object id swapping operation! The database itself, tablespaces or roles cannot have the ids swapped!")}, {"ERR_ASG_WGT_ALREADY_HAS_PARENT", QT_TR_NOOP("The widget already has a parent and cannot be assigned to a different object!")}, - {"ERR_OBJECT_NOT_IMPORTED", QT_TR_NOOP("The object `%1' (%2), oid `%3', could not be imported due to one or more errors! Check the exception stack for more details.")}, + {"ERR_OBJECT_NOT_IMPORTED", QT_TR_NOOP("The object `%1' (%2), oid `%3', could not be imported due to one or more errors! Check the exception stack for more details. `HINT:' if the object somehow references objects in `pg_catalog' or `information_schema' consider enable the importing of system objects.")}, {"ERR_MODEL_FILE_NOT_LOADED", QT_TR_NOOP("Could not load the database model file `%1'. Check the error stack to see details. Try to run `pgmodeler-cli --fix-model' in order to correct the structure of the file if that is the case.")}, {"ERR_INV_COLUMN_TABLE_TYPE", QT_TR_NOOP("The column `%1' cannot reference it's parent table `%2' as data type!")}, {"ERR_OPR_INV_ELEMENT_ID", QT_TR_NOOP("Operation with an invalid element id `%1'!")}, @@ -247,7 +247,11 @@ QString Exception::messages[ERROR_COUNT][2]={ {"ERR_ASG_ENUM_LONG_NAME", QT_TR_NOOP("The enumeration `%1' can't be assigned to the type `%2' because is too long!")}, {"ERR_CONNECTION_TIMEOUT", QT_TR_NOOP("The connection was idle for too long and was automatically closed!")}, {"ERR_CONNECTION_BROKEN", QT_TR_NOOP("The connection was unexpectedly closed by the database server `%1' at port `%2'!")}, - {"ERR_DROP_CURRDB_DEFAULT", QT_TR_NOOP("Failed to drop the database `%1' because it is defined as the default database for the connection `%2'!")} + {"ERR_DROP_CURRDB_DEFAULT", QT_TR_NOOP("Failed to drop the database `%1' because it is defined as the default database for the connection `%2'!")}, + {"ERR_NULL_PK_COLUMN", QT_TR_NOOP("The column `%1' must be `NOT NULL' because it composes the primary key of the table `%2'. You need to remove the column from the mentioned contraint in order to disable the `NOT NULL' on it!")}, + {"ERR_ASG_INV_IDENTITY_COLUMN", QT_TR_NOOP("The identity column `%1' has an invalid data type! The data type must be `smallint', `integer' or `bigint'.")}, + {"ERR_REF_INV_AFFECTED_CMD", QT_TR_NOOP("Reference to an invalid affected command in policy `%1'!")}, + {"ERR_REF_INV_SPECIAL_ROLE", QT_TR_NOOP("Reference to an invalid special role in policy `%1'!")}, }; Exception::Exception(void) diff --git a/libutils/src/exception.h b/libutils/src/exception.h index 5ff742ad7..24682bbc4 100644 --- a/libutils/src/exception.h +++ b/libutils/src/exception.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -33,7 +33,6 @@ #include using namespace std; -static const int ERROR_COUNT=229; /* ErrorType enum format: ERR_[[OPERATION_CODE][ERROR_CODE]] where: @@ -276,11 +275,16 @@ enum ErrorType { ERR_ASG_ENUM_LONG_NAME, ERR_CONNECTION_TIMEOUT, ERR_CONNECTION_BROKEN, - ERR_DROP_CURRDB_DEFAULT + ERR_DROP_CURRDB_DEFAULT, + ERR_NULL_PK_COLUMN, + ERR_INV_IDENTITY_COLUMN, + ERR_REF_INV_AFFECTED_CMD, + ERR_REF_INV_SPECIAL_ROLE }; class Exception { private: + static const int ERROR_COUNT=233; /*! \brief Stores other exceptions before raise the 'this' exception. This structure can be used to simulate a stack trace to improve the debug */ diff --git a/libutils/src/globalattributes.cpp b/libutils/src/globalattributes.cpp index b3c3a6350..7410b5116 100644 --- a/libutils/src/globalattributes.cpp +++ b/libutils/src/globalattributes.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -23,18 +23,18 @@ namespace GlobalAttributes { const QString PGMODELER_APP_NAME=QString("pgmodeler"), - PGMODELER_URI=QString("pgmodeler.com.br"), - PGMODELER_REVERSE_URI=QString("br.com.pgmodeler"), - PGMODELER_VERSION=QString("0.9.0"), + PGMODELER_URI=QString("pgmodeler.io"), + PGMODELER_REVERSE_URI=QString("io.pgmodeler"), + PGMODELER_VERSION=QString("0.9.1"), PGMODELER_BUILD_NUMBER=QString(BUILDNUM), - PGMODELER_SITE=QString("https://www.pgmodeler.com.br"), + PGMODELER_SITE=QString("https://pgmodeler.io"), PGMODELER_SUPPORT=QString("https://github.com/pgmodeler/pgmodeler/issues"), PGMODELER_SRC_URL=QString("https://github.com/pgmodeler/pgmodeler/releases"), PGMODELER_DOWNLOAD_URL=QString("%1/download").arg(PGMODELER_SITE), PGMODELER_DONATE_URL=QString("%1/#donationForm").arg(PGMODELER_SITE), PGMODELER_UPD_CHECK_URL=QString("%1/checkupdate?version=").arg(PGMODELER_SITE), - BUG_REPORT_EMAIL=QString("bug@pgmodeler.com.br"), + BUG_REPORT_EMAIL=QString("bug@pgmodeler.io"), BUG_REPORT_FILE=QString("pgmodeler%1.bug"), STACKTRACE_FILE=QString(".stacktrace"), diff --git a/libutils/src/globalattributes.h b/libutils/src/globalattributes.h index 52bf1795e..3127fc6c6 100644 --- a/libutils/src/globalattributes.h +++ b/libutils/src/globalattributes.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/libutils/src/pgsqlversions.cpp b/libutils/src/pgsqlversions.cpp index d0997f287..39c00ad80 100644 --- a/libutils/src/pgsqlversions.cpp +++ b/libutils/src/pgsqlversions.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -27,11 +27,12 @@ namespace PgSQLVersions { PGSQL_VERSION_94=QString("9.4"), PGSQL_VERSION_95=QString("9.5"), PGSQL_VERSION_96=QString("9.6"), - DEFAULT_VERSION=PGSQL_VERSION_96; + PGSQL_VERSION_100=QString("10.0"), + DEFAULT_VERSION=PGSQL_VERSION_100; const QStringList ALL_VERSIONS={ - PGSQL_VERSION_96, + PGSQL_VERSION_100, PGSQL_VERSION_96, PGSQL_VERSION_95, PGSQL_VERSION_94, PGSQL_VERSION_93, PGSQL_VERSION_92, PGSQL_VERSION_91, PGSQL_VERSION_90 }; diff --git a/libutils/src/pgsqlversions.h b/libutils/src/pgsqlversions.h index d6a0a5450..9470d7ca6 100644 --- a/libutils/src/pgsqlversions.h +++ b/libutils/src/pgsqlversions.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -37,6 +37,7 @@ namespace PgSQLVersions { PGSQL_VERSION_94, PGSQL_VERSION_95, PGSQL_VERSION_96, + PGSQL_VERSION_100, DEFAULT_VERSION; extern const QStringList ALL_VERSIONS; diff --git a/linuxdeploy.sh b/linuxdeploy.sh index de5512d90..045c9c975 100755 --- a/linuxdeploy.sh +++ b/linuxdeploy.sh @@ -4,7 +4,7 @@ case `uname -m` in "x86_64") ARCH="linux64" - FALLBACK_QT_ROOT=/opt/qt-5.6.2/5.6/gcc_64 + FALLBACK_QT_ROOT=/opt/qt-5.9.3/5.9.3/gcc_64 FALLBACK_QMAKE_ROOT="$FALLBACK_QT_ROOT/bin" ;; @@ -146,8 +146,8 @@ fi clear echo echo "pgModeler Linux deployment script" -echo "PostgreSQL Database Modeler Project - pgmodeler.com.br" -echo "Copyright 2006-2017 Raphael A. Silva " +echo "PostgreSQL Database Modeler Project - pgmodeler.io" +echo "Copyright 2006-2018 Raphael A. Silva " # Identifying System Qt version if [ -e "$QMAKE_ROOT/$QMAKE_CMD" ]; then diff --git a/macdeploy.sh b/macdeploy.sh index 92ea6a05d..94b50fe82 100755 --- a/macdeploy.sh +++ b/macdeploy.sh @@ -1,8 +1,8 @@ #!/bin/bash USR=`whoami` -PGSQL_ROOT=/Library/PostgreSQL/9.6 -QT_ROOT=/Users/$USR/Qt5.6.2/5.6/clang_64 +PGSQL_ROOT=/Library/PostgreSQL/10.1 +QT_ROOT=/Users/$USR/Qt5.9.3/5.9.3/clang_64 QMAKE_ARGS="-r CONFIG+=x86_64 CONFIG+=release -spec macx-clang" LOG=macdeploy.log @@ -40,8 +40,8 @@ BUNDLE="$INSTALL_ROOT/$APP_PREFIX/$APPNAME.app" clear echo echo "pgModeler Mac OSX deployment script" -echo "PostgreSQL Database Modeler Project - pgmodeler.com.br" -echo "Copyright 2006-2017 Raphael A. Silva " +echo "PostgreSQL Database Modeler Project - pgmodeler.io" +echo "Copyright 2006-2018 Raphael A. Silva " # Identifying System Qt version if [ -e "$QT_ROOT/bin/qmake" ]; then diff --git a/main-cli/src/main.cpp b/main-cli/src/main.cpp index 61ca2b9e9..979f0f809 100644 --- a/main-cli/src/main.cpp +++ b/main-cli/src/main.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/main-cli/src/pgmodelercli.cpp b/main-cli/src/pgmodelercli.cpp index 9f11fa0b3..a61881766 100644 --- a/main-cli/src/pgmodelercli.cpp +++ b/main-cli/src/pgmodelercli.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -19,12 +19,19 @@ #include "pgmodelercli.h" QTextStream PgModelerCLI::out(stdout); + +const QRegExp PgModelerCLI::PASSWORD_REGEXP=QRegExp("(password)(=)(.)*( )"); +const QString PgModelerCLI::PASSWORD_PLACEHOLDER=QString("password=******"); + const QString PgModelerCLI::INPUT=QString("--input"); const QString PgModelerCLI::OUTPUT=QString("--output"); +const QString PgModelerCLI::INPUT_DB=QString("--input-db"); const QString PgModelerCLI::EXPORT_TO_FILE=QString("--export-to-file"); const QString PgModelerCLI::EXPORT_TO_PNG=QString("--export-to-png"); const QString PgModelerCLI::EXPORT_TO_SVG=QString("--export-to-svg"); const QString PgModelerCLI::EXPORT_TO_DBMS=QString("--export-to-dbms"); +const QString PgModelerCLI::IMPORT_DB=QString("--import-db"); +const QString PgModelerCLI::DIFF=QString("--diff"); const QString PgModelerCLI::DROP_DATABASE=QString("--drop-database"); const QString PgModelerCLI::DROP_OBJECTS=QString("--drop-objects"); const QString PgModelerCLI::PGSQL_VER=QString("--pgsql-ver"); @@ -50,6 +57,24 @@ const QString PgModelerCLI::USE_TMP_NAMES=QString("--use-tmp-names"); const QString PgModelerCLI::DBM_MIME_TYPE=QString("--dbm-mime-type"); const QString PgModelerCLI::INSTALL=QString("install"); const QString PgModelerCLI::UNINSTALL=QString("uninstall"); +const QString PgModelerCLI::IGNORE_IMPORT_ERRORS=QString("--ignore-errors"); +const QString PgModelerCLI::IMPORT_SYSTEM_OBJS=QString("--import-sys-objs"); +const QString PgModelerCLI::IMPORT_EXTENSION_OBJS=QString("--import-ext-objs"); +const QString PgModelerCLI::DEBUG_MODE=QString("--debug-mode"); +const QString PgModelerCLI::COMPARE_TO=QString("--compare-to"); +const QString PgModelerCLI::SAVE_DIFF=QString("--save-diff"); +const QString PgModelerCLI::APPLY_DIFF=QString("--apply-diff"); +const QString PgModelerCLI::NO_DIFF_PREVIEW=QString("--no-diff-preview"); +const QString PgModelerCLI::DROP_CLUSTER_OBJS=QString("--drop-cluster-objs"); +const QString PgModelerCLI::REVOKE_PERMISSIONS=QString("--revoke-perms"); +const QString PgModelerCLI::DROP_MISSING_OBJS=QString("--drop-missing"); +const QString PgModelerCLI::FORCE_DROP_COLS_CONSTRS=QString("--force-drop-cols"); +const QString PgModelerCLI::RENAME_DB=QString("--rename-db"); +const QString PgModelerCLI::TRUNC_ON_COLS_TYPE_CHANGE=QString("--trunc-type-change"); +const QString PgModelerCLI::NO_SEQUENCE_REUSE=QString("--no-sequence-reuse"); +const QString PgModelerCLI::NO_CASCADE_DROP_TRUNC=QString("--no-cascade"); +const QString PgModelerCLI::NO_FORCE_OBJ_RECREATION=QString("--no-force-recreation"); +const QString PgModelerCLI::NO_UNMOD_OBJ_RECREATION=QString("--no-unmod-recreation"); const QString PgModelerCLI::TAG_EXPR=QString("<%1"); const QString PgModelerCLI::END_TAG_EXPR=QString("setConnectionParam(Connection::PARAM_SERVER_FQDN, parsed_opts[HOST + chr]); + conn->setConnectionParam(Connection::PARAM_USER, parsed_opts[USER + chr]); + conn->setConnectionParam(Connection::PARAM_PORT, parsed_opts[PORT + chr]); + conn->setConnectionParam(Connection::PARAM_PASSWORD, parsed_opts[PASSWD + chr]); + conn->setConnectionParam(Connection::PARAM_DB_NAME, parsed_opts[INITIAL_DB + chr]); + } +} + void PgModelerCLI::initializeOptions(void) { long_opts[INPUT]=true; long_opts[OUTPUT]=true; + long_opts[INPUT_DB]=true; long_opts[EXPORT_TO_FILE]=false; long_opts[EXPORT_TO_PNG]=false; long_opts[EXPORT_TO_SVG]=false; long_opts[EXPORT_TO_DBMS]=false; + long_opts[IMPORT_DB]=false; + long_opts[DIFF]=false; long_opts[DROP_DATABASE]=false; long_opts[DROP_OBJECTS]=false; long_opts[PGSQL_VER]=true; @@ -205,116 +266,204 @@ void PgModelerCLI::initializeOptions(void) long_opts[ZOOM_FACTOR]=true; long_opts[USE_TMP_NAMES]=false; long_opts[DBM_MIME_TYPE]=true; - - short_opts[INPUT]=QString("-i"); - short_opts[OUTPUT]=QString("-o"); - short_opts[EXPORT_TO_FILE]=QString("-f"); - short_opts[EXPORT_TO_PNG]=QString("-p"); - short_opts[EXPORT_TO_SVG]=QString("-G"); - short_opts[EXPORT_TO_DBMS]=QString("-d"); - short_opts[DROP_DATABASE]=QString("-T"); - short_opts[DROP_OBJECTS]=QString("-J"); + long_opts[IGNORE_IMPORT_ERRORS]=false; + long_opts[IMPORT_SYSTEM_OBJS]=false; + long_opts[IMPORT_EXTENSION_OBJS]=false; + long_opts[DEBUG_MODE]=false; + long_opts[COMPARE_TO]=true; + long_opts[SAVE_DIFF]=false; + long_opts[APPLY_DIFF]=false; + long_opts[NO_DIFF_PREVIEW]=false; + long_opts[DROP_CLUSTER_OBJS]=false; + long_opts[REVOKE_PERMISSIONS]=false; + long_opts[DROP_MISSING_OBJS]=false; + long_opts[FORCE_DROP_COLS_CONSTRS]=false; + long_opts[RENAME_DB]=false; + long_opts[TRUNC_ON_COLS_TYPE_CHANGE]=false; + long_opts[NO_SEQUENCE_REUSE]=false; + long_opts[NO_CASCADE_DROP_TRUNC]=false; + long_opts[NO_FORCE_OBJ_RECREATION]=false; + long_opts[NO_UNMOD_OBJ_RECREATION]=false; + + short_opts[INPUT]=QString("-if"); + short_opts[OUTPUT]=QString("-of"); + short_opts[INPUT_DB]=QString("-id"); + short_opts[EXPORT_TO_FILE]=QString("-ef"); + short_opts[EXPORT_TO_PNG]=QString("-ep"); + short_opts[EXPORT_TO_SVG]=QString("-es"); + short_opts[EXPORT_TO_DBMS]=QString("-ed"); + short_opts[IMPORT_DB]=QString("-im"); + short_opts[DIFF]=QString("-df"); + short_opts[DROP_DATABASE]=QString("-dd"); + short_opts[DROP_OBJECTS]=QString("-do"); short_opts[PGSQL_VER]=QString("-v"); short_opts[HELP]=QString("-h"); - short_opts[SHOW_GRID]=QString("-g"); - short_opts[SHOW_DELIMITERS]=QString("-l"); - short_opts[PAGE_BY_PAGE]=QString("-b"); - short_opts[IGNORE_DUPLICATES]=QString("-I"); - short_opts[IGNORE_ERROR_CODES]=QString("-x"); - short_opts[CONN_ALIAS]=QString("-c"); + short_opts[SHOW_GRID]=QString("-sg"); + short_opts[SHOW_DELIMITERS]=QString("-sl"); + short_opts[PAGE_BY_PAGE]=QString("-pp"); + short_opts[IGNORE_DUPLICATES]=QString("-ir"); + short_opts[IGNORE_ERROR_CODES]=QString("-ic"); + short_opts[CONN_ALIAS]=QString("-ca"); short_opts[HOST]=QString("-H"); - short_opts[PORT]=QString("-P"); + short_opts[PORT]=QString("-p"); short_opts[USER]=QString("-u"); short_opts[PASSWD]=QString("-w"); short_opts[INITIAL_DB]=QString("-D"); short_opts[SILENT]=QString("-s"); - short_opts[LIST_CONNS]=QString("-L"); - short_opts[SIMULATE]=QString("-S"); - short_opts[FIX_MODEL]=QString("-F"); - short_opts[FIX_TRIES]=QString("-t"); - short_opts[ZOOM_FACTOR]=QString("-z"); - short_opts[USE_TMP_NAMES]=QString("-n"); - short_opts[DBM_MIME_TYPE]=QString("-m"); + short_opts[LIST_CONNS]=QString("-lc"); + short_opts[SIMULATE]=QString("-sm"); + short_opts[FIX_MODEL]=QString("-fm"); + short_opts[FIX_TRIES]=QString("-ft"); + short_opts[ZOOM_FACTOR]=QString("-zf"); + short_opts[USE_TMP_NAMES]=QString("-tn"); + short_opts[DBM_MIME_TYPE]=QString("-mt"); + short_opts[IGNORE_IMPORT_ERRORS]=QString("-ie"); + short_opts[IMPORT_SYSTEM_OBJS]=QString("-is"); + short_opts[IMPORT_EXTENSION_OBJS]=QString("-ix"); + short_opts[DEBUG_MODE]=QString("-d"); + short_opts[COMPARE_TO]=QString("-ct"); + short_opts[SAVE_DIFF]=QString("-sd"); + short_opts[APPLY_DIFF]=QString("-ad"); + short_opts[NO_DIFF_PREVIEW]=QString("-np"); + short_opts[DROP_CLUSTER_OBJS]=QString("-dc"); + short_opts[REVOKE_PERMISSIONS]=QString("-rv"); + short_opts[DROP_MISSING_OBJS]=QString("-dm"); + short_opts[FORCE_DROP_COLS_CONSTRS]=QString("-fd"); + short_opts[RENAME_DB]=QString("-rn"); + short_opts[TRUNC_ON_COLS_TYPE_CHANGE]=QString("-tt"); + short_opts[NO_SEQUENCE_REUSE]=QString("-ns"); + short_opts[NO_CASCADE_DROP_TRUNC]=QString("-nd"); + short_opts[NO_FORCE_OBJ_RECREATION]=QString("-nf"); + short_opts[NO_UNMOD_OBJ_RECREATION]=QString("-nu"); } bool PgModelerCLI::isOptionRecognized(QString &op, bool &accepts_val) { - attribs_map::iterator itr=short_opts.begin(); - bool found=false; + bool found=false, append_chr = false; - while(itr!=short_opts.end() && !found) + if(op.endsWith('1')) { - found=(op==itr->first || op==itr->second); - accepts_val=(found && long_opts[itr->first]); - if(found) op=itr->first; - itr++; + op.chop(1); + append_chr = true; + } + + for(auto &itr : short_opts) + { + found=(op==itr.first || op==itr.second); + accepts_val=(found && long_opts[itr.first]); + + if(found) + { + op = itr.first; + break; + } } + if(append_chr) op += '1'; return(found); } 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.com.br") << endl; - out << trUtf8("Copyright 2006-2015 Raphael A. Silva ") << 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 the operations to export pgModeler's database models without\n\ -the need to load them on graphical interface as well to fix model files to the most recent\n\ -accepted structure. 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). Mandatory use when fixing a model or exporting it.").arg(short_opts[INPUT]).arg(INPUT) << endl; - out << trUtf8(" %1, %2=[FILE]\t\t Output file. Mandatory use when fixing model or export to file or png.").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\t\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\t\t Export to a sql script file.").arg(short_opts[EXPORT_TO_FILE]).arg(EXPORT_TO_FILE)<< endl; - out << trUtf8(" %1, %2\t\t Export to a png image.").arg(short_opts[EXPORT_TO_PNG]).arg(EXPORT_TO_PNG) << endl; - out << trUtf8(" %1, %2\t\t Export to a svg file.").arg(short_opts[EXPORT_TO_SVG]).arg(EXPORT_TO_SVG) << endl; - out << trUtf8(" %1, %2\t\t Export directly to a PostgreSQL server.").arg(short_opts[EXPORT_TO_DBMS]).arg(EXPORT_TO_DBMS) << endl; - out << trUtf8(" %1, %2\t\t List available connections on %3 file.").arg(short_opts[LIST_CONNS]).arg(LIST_CONNS).arg(GlobalAttributes::CONNECTIONS_CONF + GlobalAttributes::CONFIGURATION_EXT) << endl; - out << trUtf8(" %1, %2\t\t Version of generated SQL code. Only for file or dbms export.").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 Show this help menu.").arg(short_opts[HELP]).arg(HELP) << 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 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 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 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 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\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=[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 Generates temporary names for database, roles and tablespaces when in simulation mode.").arg(short_opts[USE_TMP_NAMES]).arg(USE_TMP_NAMES) << 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 export 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 << 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 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; + out << trUtf8(" %1, %2\t\t Ignore all errors and try to create as many as possible objects.").arg(short_opts[IGNORE_IMPORT_ERRORS]).arg(IGNORE_IMPORT_ERRORS) << endl; + out << trUtf8(" %1, %2\t Import system built-in objects. This option causes the model bloating due to the importing of unneeded objects.").arg(short_opts[IMPORT_SYSTEM_OBJS]).arg(IMPORT_SYSTEM_OBJS) << endl; + out << trUtf8(" %1, %2\t Import extension objects. This option causes the model bloating due to the importing of unneeded objects.").arg(short_opts[IMPORT_EXTENSION_OBJS]).arg(IMPORT_EXTENSION_OBJS) << endl; + out << trUtf8(" %1, %2\t\t Run import in debug mode printing all queries executed in the server.").arg(short_opts[DEBUG_MODE]).arg(DEBUG_MODE) << endl; + out << endl; + 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 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 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; + out << trUtf8(" %1, %2\t Don't force the recreation of objects. Avoids the usage of a DROP and CREATE commands to create a new version of the objects.").arg(short_opts[NO_FORCE_OBJ_RECREATION]).arg(NO_FORCE_OBJ_RECREATION) << endl; + out << trUtf8(" %1, %2\t Don't recreate the unmodifiable objects. These objects are the ones which can't be changed via ALTER command.").arg(short_opts[NO_UNMOD_OBJ_RECREATION]).arg(NO_UNMOD_OBJ_RECREATION) << endl; out << endl; #ifndef Q_OS_MAC out << trUtf8("Miscellaneous options: ") << endl; - out << trUtf8(" %1, %2=[ACTION]\t Handles the file association to .dbm files. The ACTION can be [%3 | %4].").arg(short_opts[DBM_MIME_TYPE]).arg(DBM_MIME_TYPE).arg(INSTALL).arg(UNINSTALL) << endl; + out << trUtf8(" %1, %2 [ACTION]\t Handles the file association to .dbm files. The ACTION can be [%3 | %4].").arg(short_opts[DBM_MIME_TYPE]).arg(DBM_MIME_TYPE).arg(INSTALL).arg(UNINSTALL) << endl; out << endl; #endif + + out << trUtf8("** The diff process allows the usage of the following options related to import and export operations: ") << endl; + out << " " << QStringList({ trUtf8("* Export: "), IGNORE_DUPLICATES, IGNORE_ERROR_CODES, "\n ", trUtf8("* Import: "), IMPORT_SYSTEM_OBJS, IMPORT_EXTENSION_OBJS, IGNORE_IMPORT_ERRORS, DEBUG_MODE }).join(" ") << endl; + out << endl; + out << trUtf8("** When running the diff using two databases (%1 and %2) there's the need to specify two connections/aliases. ").arg(INPUT_DB).arg(COMPARE_TO) << endl; + out << trUtf8(" If only one connection is set it will be used to import the input database as well to retrieve database used in the comparison.") << endl; + out << trUtf8(" A second connection can be specified by appending a 1 on any connection configuration parameter listed above.") << endl; + out << endl; } void PgModelerCLI::parseOptions(attribs_map &opts) { //Loading connections - if(opts.count(LIST_CONNS) || opts.count(EXPORT_TO_DBMS)) + if(opts.count(LIST_CONNS) || opts.count(EXPORT_TO_DBMS) || opts.count(IMPORT_DB) || opts.count(DIFF)) { conn_conf.loadConfiguration(); conn_conf.getConnections(connections, false); } + //Loading general and relationship settings when exporting to image formats + else if(opts.count(EXPORT_TO_PNG) || opts.count(EXPORT_TO_SVG)) + { + general_conf.loadConfiguration(); + rel_conf.loadConfiguration(); + } if(opts.empty() || opts.count(HELP)) showMenu(); @@ -329,10 +478,12 @@ void PgModelerCLI::parseOptions(attribs_map &opts) { unsigned id=0; - out << endl << trUtf8("Available connections (alias : conn. string)") << endl; + out << endl << trUtf8("Available connections (alias : connection string)") << endl; while(itr != connections.end()) { - out << QString("[") << id++ << QString("] ") << itr->first << QString(" : ") << itr->second->getConnectionString() << endl; + out << QString("[") << id++ << QString("] ") << itr->first << QString(" : ") << + itr->second->getConnectionString().replace(PASSWORD_REGEXP, PASSWORD_PLACEHOLDER) << endl; + itr++; } out << endl; @@ -340,9 +491,9 @@ void PgModelerCLI::parseOptions(attribs_map &opts) } else { - int mode_cnt=0; - bool fix_model=(opts.count(FIX_MODEL) > 0), upd_mime=(opts.count(DBM_MIME_TYPE) > 0); - QFileInfo input_fi(opts[INPUT]), output_fi(opts[OUTPUT]); + int mode_cnt=0, other_modes_cnt=0; + bool fix_model=(opts.count(FIX_MODEL) > 0), upd_mime=(opts.count(DBM_MIME_TYPE) > 0), + import_db=(opts.count(IMPORT_DB) > 0), diff=(opts.count(DIFF) > 0); //Checking if multiples export modes were specified mode_cnt+=opts.count(EXPORT_TO_FILE); @@ -350,33 +501,72 @@ void PgModelerCLI::parseOptions(attribs_map &opts) mode_cnt+=opts.count(EXPORT_TO_SVG); mode_cnt+=opts.count(EXPORT_TO_DBMS); + other_modes_cnt+=opts.count(FIX_MODEL); + other_modes_cnt+=opts.count(IMPORT_DB); + other_modes_cnt+=opts.count(DIFF); + other_modes_cnt+=opts.count(DBM_MIME_TYPE); + if(opts.count(ZOOM_FACTOR)) zoom=opts[ZOOM_FACTOR].toDouble()/static_cast(100); - if(!fix_model && !upd_mime && mode_cnt==0) - throw Exception(trUtf8("No export mode specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - if((mode_cnt > 0 && (fix_model || upd_mime)) || - (mode_cnt==0 && fix_model && upd_mime)) - throw Exception(trUtf8("Export, fix model and update mime operations can't be used at the same time!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(!fix_model && !upd_mime && mode_cnt > 1) - throw Exception(trUtf8("Multiple export mode specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(!upd_mime && opts[INPUT].isEmpty()) - throw Exception(trUtf8("No input file specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(!opts.count(EXPORT_TO_DBMS) && !upd_mime && opts[OUTPUT].isEmpty()) - throw Exception(trUtf8("No output file specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(!opts.count(EXPORT_TO_DBMS) && !upd_mime && input_fi.absoluteFilePath()==output_fi.absoluteFilePath()) + if(other_modes_cnt==0 && mode_cnt==0) + throw Exception(trUtf8("No operation mode was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if((mode_cnt > 0 && (fix_model || upd_mime || import_db || diff)) || (mode_cnt==0 && other_modes_cnt > 1)) + throw Exception(trUtf8("Export, fix model, import database, diff and update mime operations can't be used at the same time!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!fix_model && !upd_mime && mode_cnt > 1) + throw Exception(trUtf8("Multiple export mode was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!upd_mime && !import_db && !diff && opts[INPUT].isEmpty()) + throw Exception(trUtf8("No input file was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(import_db && opts[INPUT_DB].isEmpty()) + throw Exception(trUtf8("No input database was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(EXPORT_TO_DBMS) && !upd_mime && !diff && opts[OUTPUT].isEmpty()) + throw Exception(trUtf8("No output file was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(EXPORT_TO_DBMS) && !upd_mime && !import_db && + !opts[INPUT].isEmpty() && !opts[OUTPUT].isEmpty() && + QFileInfo(opts[INPUT]).absoluteFilePath() == QFileInfo(opts[OUTPUT]).absoluteFilePath()) throw Exception(trUtf8("Input file must be different from output!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(opts.count(EXPORT_TO_DBMS) && !opts.count(CONN_ALIAS) && - (!opts.count(HOST) || !opts.count(USER) || !opts.count(PASSWD) || !opts.count(INITIAL_DB)) ) + + if(opts.count(EXPORT_TO_DBMS) && !opts.count(CONN_ALIAS) && + (!opts.count(HOST) || !opts.count(USER) || !opts.count(PASSWD) || !opts.count(INITIAL_DB)) ) throw Exception(trUtf8("Incomplete connection information!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(opts.count(EXPORT_TO_PNG) && (zoom < ModelWidget::MINIMUM_ZOOM || zoom > ModelWidget::MAXIMUM_ZOOM)) + + if(opts.count(EXPORT_TO_PNG) && (zoom < ModelWidget::MINIMUM_ZOOM || zoom > ModelWidget::MAXIMUM_ZOOM)) throw Exception(trUtf8("Invalid zoom specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); - else if(upd_mime && opts[DBM_MIME_TYPE]!=INSTALL && opts[DBM_MIME_TYPE]!=UNINSTALL) + + if(upd_mime && opts[DBM_MIME_TYPE]!=INSTALL && opts[DBM_MIME_TYPE]!=UNINSTALL) throw Exception(trUtf8("Invalid action specified to update mime option!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(DIFF)) + { + if(opts[INPUT].isEmpty() && opts[INPUT_DB].isEmpty()) + throw Exception(trUtf8("No input file or database was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + if(!opts[INPUT].isEmpty() && !opts[INPUT_DB].isEmpty()) + throw Exception(trUtf8("The input file and database can't be used at the same time!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(COMPARE_TO)) + throw Exception(trUtf8("No database to be compared was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(!opts.count(SAVE_DIFF) && !opts.count(APPLY_DIFF)) + throw Exception(trUtf8("No diff action (save or apply) was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + + if(opts.count(SAVE_DIFF) && opts[OUTPUT].isEmpty()) + throw Exception(trUtf8("No output file for the diff code was specified!"), ERR_CUSTOM,__PRETTY_FUNCTION__,__FILE__,__LINE__); + } + //Converting input and output files to absolute paths to avoid that they are read/written on the app's working dir - opts[INPUT]=input_fi.absoluteFilePath(); - opts[OUTPUT]=output_fi.absoluteFilePath(); + if(!opts[INPUT].isEmpty()) + opts[INPUT]=QFileInfo(opts[INPUT]).absoluteFilePath(); + + if(!opts[OUTPUT].isEmpty()) + opts[OUTPUT]=QFileInfo(opts[OUTPUT]).absoluteFilePath(); + parsed_opts=opts; } } @@ -387,111 +577,29 @@ int PgModelerCLI::exec(void) { if(!parsed_opts.empty()) { - if(!silent_mode) - { - out << endl << QString("pgModeler ") << GlobalAttributes::PGMODELER_VERSION << trUtf8(" command line interface.") << endl; - - if(parsed_opts.count(FIX_MODEL)) - out << trUtf8("Starting model fixing...") << endl; - else if(parsed_opts.count(DBM_MIME_TYPE)) - out << trUtf8("Starting mime update...") << endl; - else - out << trUtf8("Starting model export...") << endl; - - if(parsed_opts.count(DBM_MIME_TYPE)==0) - out << trUtf8("Loading input file: ") << parsed_opts[INPUT] << endl; - } + printMessage(QString("\npgModeler %1 %2").arg(GlobalAttributes::PGMODELER_VERSION).arg(trUtf8(" command line interface."))); if(parsed_opts.count(FIX_MODEL)) - { - if(!silent_mode) - out << trUtf8("Fixed model file: ") << parsed_opts[OUTPUT] << endl; - - extractObjectXML(); - recreateObjects(); - model->updateTablesFKRelationships(); - model->saveModel(parsed_opts[OUTPUT], SchemaParser::XML_DEFINITION); - - if(!silent_mode) - out << trUtf8("Model successfully fixed!") << endl << endl; - } + fixModel(); else if(parsed_opts.count(DBM_MIME_TYPE)) - { -#ifndef Q_OS_MAC - handleMimeDatabase(parsed_opts[DBM_MIME_TYPE]==UNINSTALL); - - if(!silent_mode) - PgModelerCLI::out << trUtf8("Mime database successfully updated.") << endl << endl; -#endif - } + updateMimeType(); + else if(parsed_opts.count(IMPORT_DB)) + importDatabase(); + else if(parsed_opts.count(DIFF)) + diffModelDatabase(); else - { - //Create the systems objects on model before loading it - model->createSystemObjects(false); - - //Load the model file - model->loadModel(parsed_opts[INPUT]); - - //Export to PNG - if(parsed_opts.count(EXPORT_TO_PNG)) - { - if(!silent_mode) - out << trUtf8("Export to PNG image: ") << parsed_opts[OUTPUT] << endl; - - export_hlp.exportToPNG(scene, parsed_opts[OUTPUT], zoom, - parsed_opts.count(SHOW_GRID) > 0, - parsed_opts.count(SHOW_DELIMITERS) > 0, - parsed_opts.count(PAGE_BY_PAGE) > 0); - } - //Export to SVG - else if(parsed_opts.count(EXPORT_TO_SVG)) - { - if(!silent_mode) - out << trUtf8("Export to SVG file: ") << parsed_opts[OUTPUT] << endl; - - export_hlp.exportToSVG(scene, parsed_opts[OUTPUT], - parsed_opts.count(SHOW_GRID) > 0, - parsed_opts.count(SHOW_DELIMITERS) > 0); - } - //Export to SQL file - else if(parsed_opts.count(EXPORT_TO_FILE)) - { - if(!silent_mode) - out << trUtf8("Export to SQL script file: ") << parsed_opts[OUTPUT] << endl; - - export_hlp.exportToSQL(model, parsed_opts[OUTPUT], parsed_opts[PGSQL_VER]); - } - //Export to DBMS - else - { - if(!silent_mode) - out << trUtf8("Export to DBMS: ") << connection.getConnectionString() << endl; - - if(parsed_opts.count(IGNORE_ERROR_CODES)) - export_hlp.setIgnoredErrors(parsed_opts[IGNORE_ERROR_CODES].split(',')); - - export_hlp.exportToDBMS(model, connection, parsed_opts[PGSQL_VER], - parsed_opts.count(IGNORE_DUPLICATES) > 0, - parsed_opts.count(DROP_DATABASE) > 0, - parsed_opts.count(DROP_OBJECTS) > 0, - parsed_opts.count(SIMULATE) > 0, - parsed_opts.count(USE_TMP_NAMES) > 0); - } - - if(!silent_mode) - out << trUtf8("Export successfully ended!") << endl << endl; - } + exportModel(); } return(0); } catch(Exception &e) { - throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + throw e; } } -void PgModelerCLI::updateProgress(int progress, QString msg) +void PgModelerCLI::updateProgress(int progress, QString msg, ObjectType) { if(progress > 0) out << QString("[%1%] ").arg(progress > 100 ? 100 : progress) << msg << endl; @@ -499,6 +607,15 @@ void PgModelerCLI::updateProgress(int progress, QString msg) out << msg << endl; } +void PgModelerCLI::printIgnoredError(QString err_cod, QString err_msg, QString cmd) +{ + out << endl; + out << trUtf8("** Error code `%1' found and ignored. Proceeding with export.").arg(err_cod) << endl; + out << trUtf8("** Command: %1").arg(cmd) << endl; + out << err_msg << endl; + out << endl; +} + void PgModelerCLI::handleObjectAddition(BaseObject *object) { BaseGraphicObject *graph_obj=dynamic_cast(object); @@ -572,8 +689,7 @@ void PgModelerCLI::extractObjectXML(void) int start=-1, end=-1; bool open_tag=false, close_tag=false, is_rel=false, short_tag=false, end_extract_rel; - if(!silent_mode) - out << trUtf8("Extracting objects' XML...") << endl; + printMessage(trUtf8("Extracting objects' XML...")); input.setFileName(parsed_opts[INPUT]); input.open(QFile::ReadOnly); @@ -711,8 +827,7 @@ void PgModelerCLI::recreateObjects(void) unsigned tries=0, max_tries=parsed_opts[FIX_TRIES].toUInt(); int start_pos=-1, end_pos=-1, len=0; - if(!silent_mode) - out << trUtf8("Recreating objects...") << endl; + printMessage(trUtf8("Recreating objects...")); if(max_tries==0) max_tries=1; @@ -843,9 +958,7 @@ void PgModelerCLI::recreateObjects(void) } else { - if(!silent_mode) - out << trUtf8("WARNING: There are objects that maybe can't be fixed. Trying again... (tries %1/%2)").arg(tries).arg(max_tries) << endl; - + printMessage(trUtf8("WARNING: There are objects that maybe can't be fixed. Trying again... (tries %1/%2)").arg(tries).arg(max_tries)); model->validateRelationships(); objs_xml=fail_objs; objs_xml.append(constr); @@ -969,6 +1082,28 @@ void PgModelerCLI::fixObjectAttributes(QString &obj_xml) obj_xml.replace(END_TAG_EXPR.arg(QString("grant")), END_TAG_EXPR.arg(BaseObject::getSchemaName(OBJ_PERMISSION))); } + //Replace the constraint attribute and tag expression by constraint tag in . + if(obj_xml.contains(TAG_EXPR.arg(BaseObject::getSchemaName(OBJ_DOMAIN))) && + obj_xml.contains(TAG_EXPR.arg(ParsersAttributes::EXPRESSION))) + { + int start_idx=-1, end_idx=-1; + QRegExp regexp = QRegExp(ATTRIBUTE_EXPR.arg(ParsersAttributes::CONSTRAINT)); + QString constr_name; + + regexp.indexIn(obj_xml); + constr_name = regexp.capturedTexts().at(0); + constr_name.remove(QString("%1=\"").arg(ParsersAttributes::CONSTRAINT)); + constr_name.remove(constr_name.length() - 1, 1); + + obj_xml.remove(QRegExp(ATTRIBUTE_EXPR.arg(ParsersAttributes::CONSTRAINT))); + + start_idx = obj_xml.indexOf(TAG_EXPR.arg(ParsersAttributes::EXPRESSION)); + obj_xml.insert(start_idx, QString("\n\t\n\t\t").arg(constr_name)); + + end_idx = obj_xml.indexOf(END_TAG_EXPR.arg(ParsersAttributes::EXPRESSION)); + obj_xml.insert(end_idx + END_TAG_EXPR.arg(ParsersAttributes::EXPRESSION).length() + 1, QString("\n\t\n")); + } + //Fix the references to op. classes and families if needed fixOpClassesFamiliesReferences(obj_xml); } @@ -1037,6 +1172,289 @@ void PgModelerCLI::fixOpClassesFamiliesReferences(QString &obj_xml) while(pos >= 0); } +void PgModelerCLI::fixModel(void) +{ + printMessage(trUtf8("Starting model fixing...")); + printMessage(trUtf8("Loading input file: %1").arg(parsed_opts[INPUT])); + printMessage(trUtf8("Fixed model file: %1").arg(parsed_opts[OUTPUT])); + + extractObjectXML(); + recreateObjects(); + model->updateTablesFKRelationships(); + model->saveModel(parsed_opts[OUTPUT], SchemaParser::XML_DEFINITION); + + printMessage(trUtf8("Model successfully fixed!")); +} + +void PgModelerCLI::exportModel(void) +{ + printMessage(trUtf8("Starting model export...")); + printMessage(trUtf8("Loading input file: %1").arg(parsed_opts[INPUT])); + + //Create the systems objects on model before loading it + model->createSystemObjects(false); + + //Load the model file + model->loadModel(parsed_opts[INPUT]); + + //Export to PNG + if(parsed_opts.count(EXPORT_TO_PNG)) + { + printMessage(trUtf8("Export to PNG image: %1").arg(parsed_opts[OUTPUT])); + + export_hlp.exportToPNG(scene, parsed_opts[OUTPUT], zoom, + parsed_opts.count(SHOW_GRID) > 0, + parsed_opts.count(SHOW_DELIMITERS) > 0, + parsed_opts.count(PAGE_BY_PAGE) > 0); + } + //Export to SVG + else if(parsed_opts.count(EXPORT_TO_SVG)) + { + printMessage(trUtf8("Export to SVG file: %1").arg(parsed_opts[OUTPUT])); + + export_hlp.exportToSVG(scene, parsed_opts[OUTPUT], + parsed_opts.count(SHOW_GRID) > 0, + parsed_opts.count(SHOW_DELIMITERS) > 0); + } + //Export to SQL file + else if(parsed_opts.count(EXPORT_TO_FILE)) + { + printMessage(trUtf8("Export to SQL script file: %1").arg(parsed_opts[OUTPUT])); + + export_hlp.exportToSQL(model, parsed_opts[OUTPUT], parsed_opts[PGSQL_VER]); + } + //Export to DBMS + else + { + printMessage(trUtf8("Export to DBMS: %1").arg(connection.getConnectionString().replace(PASSWORD_REGEXP, PASSWORD_PLACEHOLDER))); + + if(parsed_opts.count(IGNORE_ERROR_CODES)) + export_hlp.setIgnoredErrors(parsed_opts[IGNORE_ERROR_CODES].split(',')); + + export_hlp.exportToDBMS(model, connection, parsed_opts[PGSQL_VER], + parsed_opts.count(IGNORE_DUPLICATES) > 0, + parsed_opts.count(DROP_DATABASE) > 0, + parsed_opts.count(DROP_OBJECTS) > 0, + parsed_opts.count(SIMULATE) > 0, + parsed_opts.count(USE_TMP_NAMES) > 0); + } + + printMessage(trUtf8("Export successfully ended!\n")); +} + +void PgModelerCLI::importDatabase(void) +{ + printMessage(trUtf8("Starting database import...")); + printMessage(trUtf8("Input database: %1").arg(connection.getConnectionId(true, true))); + + ModelWidget *model_wgt = new ModelWidget; + + importDatabase(model_wgt->getDatabaseModel(), connection); + model_wgt->rearrangeSchemasInGrid(); + + printMessage(trUtf8("Saving the imported database to file...")); + + model_wgt->getDatabaseModel()->saveModel(parsed_opts[OUTPUT], SchemaParser::XML_DEFINITION); + + printMessage(trUtf8("Import successfully ended!\n")); + + delete(model_wgt); +} + +void PgModelerCLI::importDatabase(DatabaseModel *model, Connection conn) +{ + try + { + map> obj_oids; + map> col_oids; + Catalog catalog; + QString db_oid; + + catalog.setConnection(conn); + + //For diff we don't need the oids of all system objects + catalog.setFilter(Catalog::LIST_ALL_OBJS | Catalog::EXCL_BUILTIN_ARRAY_TYPES | + Catalog::EXCL_EXTENSION_OBJS | Catalog::EXCL_SYSTEM_OBJS); + + catalog.getObjectsOIDs(obj_oids, col_oids, {{ParsersAttributes::FILTER_TABLE_TYPES, ParsersAttributes::_TRUE_}}); + + db_oid = catalog.getObjectOID(conn.getConnectionParam(Connection::PARAM_DB_NAME), OBJ_DATABASE); + obj_oids[OBJ_DATABASE].push_back(db_oid.toUInt()); + + catalog.closeConnection(); + + import_hlp.setConnection(conn); + import_hlp.setImportOptions(parsed_opts.count(IMPORT_SYSTEM_OBJS) > 0, + parsed_opts.count(IMPORT_EXTENSION_OBJS) > 0, + true, + parsed_opts.count(IGNORE_IMPORT_ERRORS) > 0, + parsed_opts.count(DEBUG_MODE) > 0, + !parsed_opts.count(DIFF), !parsed_opts.count(DIFF)); + + model->createSystemObjects(true); + import_hlp.setSelectedOIDs(model, obj_oids, col_oids); + import_hlp.importDatabase(); + import_hlp.closeConnection(); + } + catch(Exception &e) + { + throw Exception(e.getErrorMessage(), e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__, &e); + } +} + +void PgModelerCLI::diffModelDatabase(void) +{ + DatabaseModel *model_aux = new DatabaseModel(); + QString dbname; + + printMessage(trUtf8("Starting diff process...")); + + if(!parsed_opts[INPUT].isEmpty()) + printMessage(trUtf8("Input model: %1").arg(parsed_opts[INPUT])); + else + printMessage(trUtf8("Input database: %1").arg(connection.getConnectionId(true, true))); + + dbname = extra_connection.getConnectionId(true, true); + printMessage(trUtf8("Compare to: %1").arg(dbname)); + + if(!parsed_opts[INPUT].isEmpty()) + { + printMessage(trUtf8("Loading input model...")); + model->createSystemObjects(false); + model->loadModel(parsed_opts[INPUT]); + } + else + { + printMessage(trUtf8("Importing the database `%1'...").arg(connection.getConnectionId(true, true))); + importDatabase(model, connection); + } + + printMessage(trUtf8("Importing the database `%1'...").arg(dbname)); + importDatabase(model_aux, extra_connection); + + diff_hlp.setModels(model, model_aux); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_KEEP_CLUSTER_OBJS, !parsed_opts.count(DROP_CLUSTER_OBJS)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_CASCADE_MODE, !parsed_opts.count(NO_CASCADE_DROP_TRUNC)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_TRUCANTE_TABLES, parsed_opts.count(TRUNC_ON_COLS_TYPE_CHANGE)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_FORCE_RECREATION, !parsed_opts.count(NO_FORCE_OBJ_RECREATION)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_RECREATE_UNCHANGEBLE, !parsed_opts.count(NO_UNMOD_OBJ_RECREATION)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_KEEP_OBJ_PERMS, !parsed_opts.count(REVOKE_PERMISSIONS)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_REUSE_SEQUENCES, !parsed_opts.count(NO_SEQUENCE_REUSE)); + diff_hlp.setDiffOption(ModelsDiffHelper::OPT_PRESERVE_DB_NAME, !parsed_opts.count(RENAME_DB)); + 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(); + + if(diff_hlp.getDiffDefinition().isEmpty()) + printMessage(trUtf8("No differences were detected.")); + else + { + if(parsed_opts.count(SAVE_DIFF)) + { + QFile output; + + printMessage(trUtf8("Saving diff to file `%1'").arg(parsed_opts[OUTPUT])); + output.setFileName(parsed_opts[OUTPUT]); + + if(!output.open(QFile::WriteOnly)) + throw Exception(Exception::getErrorMessage(ERR_FILE_DIR_NOT_WRITTEN).arg(parsed_opts[OUTPUT]), + ERR_FILE_DIR_NOT_WRITTEN, __PRETTY_FUNCTION__,__FILE__,__LINE__); + + output.write(diff_hlp.getDiffDefinition().toUtf8()); + output.close(); + } + else + { + bool apply_diff = true; + + if(!parsed_opts.count(NO_DIFF_PREVIEW)) + { + 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 OF PREVIEW ###\n\n"; + + preview.setString(&buff, QIODevice::ReadOnly); + + while(!preview.atEnd()) + { + line = preview.readLine(); + res.append(line + '\n'); + + if(res.count(QChar('\n')) >= 30 || preview.atEnd()) + { + out << res; + out.flush(); + res.clear(); + + if(!preview.atEnd()) + in.readLine(); + } + } + + out << 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 + { + out << trUtf8("** Proceed with the diff applying? (yes/no) > "); + out.flush(); + + in.skipWhiteSpace(); + res = in.readLine(); + } + while(res.toLower() != trUtf8("yes") && res.toLower() != trUtf8("no")); + + if(res.toLower() == trUtf8("no")) + { + apply_diff = false; + printMessage(trUtf8("Diff code not applied to the server.")); + } + } + + if(apply_diff) + { + printMessage(trUtf8("Applying diff to the database `%1'...").arg(dbname)); + export_hlp.setExportToDBMSParams(diff_hlp.getDiffDefinition(), + &extra_connection, + parsed_opts[COMPARE_TO], parsed_opts.count(IGNORE_DUPLICATES)); + + if(parsed_opts.count(IGNORE_ERROR_CODES)) + export_hlp.setIgnoredErrors(parsed_opts[IGNORE_ERROR_CODES].split(',')); + + export_hlp.exportToDBMS(); + } + } + } + + printMessage(trUtf8("Diff successfully ended!\n")); +} + +void PgModelerCLI::updateMimeType(void) +{ +#ifndef Q_OS_MAC + printMessage(trUtf8("Starting mime update...")); + + handleMimeDatabase(parsed_opts[DBM_MIME_TYPE]==UNINSTALL); + + printMessage(trUtf8("Mime database successfully updated!\n")); +#endif +} + QStringList PgModelerCLI::extractForeignKeys(QString &obj_xml) { QStringList constr_lst; @@ -1098,11 +1516,7 @@ void PgModelerCLI::handleMimeDatabase(bool uninstall) QString msg_file_associated=trUtf8("Database model files (.dbm) are already associated to pgModeler!"), msg_no_association=trUtf8("There is no file association related to pgModeler and .dbm files!"); - if(!silent_mode) - { - out << trUtf8("Mime database operation: %1") - .arg(uninstall ? QString("uninstall") : QString("install")) << endl; - } + printMessage(trUtf8("Mime database operation: %1").arg(uninstall ? QString("uninstall") : QString("install"))); #ifdef Q_OS_LINUX attribs_map attribs; @@ -1236,8 +1650,7 @@ void PgModelerCLI::handleMimeDatabase(bool uninstall) } //Update the mime database - if(!silent_mode) - PgModelerCLI::out << trUtf8("Running update-mime-database command...") << endl; + printMessage(trUtf8("Running update-mime-database command...")); QProcess::execute(QString("update-mime-database"), QStringList { mime_db_dir }); } diff --git a/main-cli/src/pgmodelercli.h b/main-cli/src/pgmodelercli.h index 82bc159c0..ab240d1c4 100644 --- a/main-cli/src/pgmodelercli.h +++ b/main-cli/src/pgmodelercli.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -34,6 +34,10 @@ #include "modelexporthelper.h" #include "generalconfigwidget.h" #include "connectionsconfigwidget.h" +#include "relationshipconfigwidget.h" +#include "generalconfigwidget.h" +#include "databaseimporthelper.h" +#include "modelsdiffhelper.h" class PgModelerCLI: public QApplication { private: @@ -44,6 +48,12 @@ class PgModelerCLI: public QApplication { //! \brief Export helper object ModelExportHelper export_hlp; + //! \brief Import helper object + DatabaseImportHelper import_hlp; + + //! \brief Diff helper object + ModelsDiffHelper diff_hlp; + //! \brief Reference database model DatabaseModel *model; @@ -51,7 +61,10 @@ class PgModelerCLI: public QApplication { ObjectsScene *scene; //! \brief Stores the configured connection - Connection connection; + Connection connection, + + //! \brief Stores the extra configured connection (only for diff) + extra_connection; //! \brief Loaded connections map connections; @@ -59,6 +72,11 @@ class PgModelerCLI: public QApplication { //! \brief Connection configuration widget used to load available connections from file ConnectionsConfigWidget conn_conf; + //! \brief Relationship configuration widget used to load custom relationship settings + RelationshipConfigWidget rel_conf; + + GeneralConfigWidget general_conf; + //! \brief Creates an standard out to handles QStrings static QTextStream out; @@ -80,13 +98,20 @@ class PgModelerCLI: public QApplication { //! \brief Zoom to be applied onto the png export double zoom; + static const QRegExp PASSWORD_REGEXP; + + static const QString PASSWORD_PLACEHOLDER; + //! \brief Option names constants static const QString INPUT, OUTPUT, + INPUT_DB, EXPORT_TO_FILE, EXPORT_TO_PNG, EXPORT_TO_SVG, EXPORT_TO_DBMS, + IMPORT_DB, + DIFF, DROP_DATABASE, DROP_OBJECTS, PGSQL_VER, @@ -113,6 +138,26 @@ class PgModelerCLI: public QApplication { INSTALL, UNINSTALL, + IGNORE_IMPORT_ERRORS, + IMPORT_SYSTEM_OBJS, + IMPORT_EXTENSION_OBJS, + DEBUG_MODE, + + COMPARE_TO, + SAVE_DIFF, + APPLY_DIFF, + NO_DIFF_PREVIEW, + DROP_CLUSTER_OBJS, + REVOKE_PERMISSIONS, + DROP_MISSING_OBJS, + FORCE_DROP_COLS_CONSTRS, + RENAME_DB, + TRUNC_ON_COLS_TYPE_CHANGE, + NO_SEQUENCE_REUSE, + NO_CASCADE_DROP_TRUNC, + NO_FORCE_OBJ_RECREATION, + NO_UNMOD_OBJ_RECREATION, + TAG_EXPR, END_TAG_EXPR, ATTRIBUTE_EXPR; @@ -155,6 +200,17 @@ class PgModelerCLI: public QApplication { only over operator classes, indexes and constraints */ void fixOpClassesFamiliesReferences(QString &obj_xml); + void fixModel(void); + void exportModel(void); + void importDatabase(void); + void diffModelDatabase(void); + void updateMimeType(void); + + void configureConnection(bool extra_conn); + void importDatabase(DatabaseModel *model, Connection conn); + + void printMessage(const QString &msg); + public: PgModelerCLI(int argc, char **argv); ~PgModelerCLI(void); @@ -162,7 +218,8 @@ class PgModelerCLI: public QApplication { private slots: void handleObjectAddition(BaseObject *); - void updateProgress(int progress, QString msg); + void updateProgress(int progress, QString msg, ObjectType = BASE_OBJECT); + void printIgnoredError(QString err_cod, QString err_msg, QString cmd); void handleObjectRemoval(BaseObject *object); }; diff --git a/main/src/application.cpp b/main/src/application.cpp index 204692d43..014e3eb64 100644 --- a/main/src/application.cpp +++ b/main/src/application.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 @@ -39,18 +39,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc,argv) //Adding paths which executable will find plugins and it's dependecies this->addLibraryPath(this->applicationDirPath()); - this->addLibraryPath(GlobalAttributes::PLUGINS_DIR); - //Try to create plugins dir if it does not exists - if(!dir.exists(GlobalAttributes::PLUGINS_DIR)) - { - if(!dir.mkdir(GlobalAttributes::PLUGINS_DIR)) - { - Messagebox msg; - msg.show(Exception(Exception::getErrorMessage(ERR_FILE_DIR_NOT_WRITTEN).arg(GlobalAttributes::PLUGINS_DIR), - ERR_FILE_DIR_NOT_WRITTEN,__PRETTY_FUNCTION__,__FILE__,__LINE__)); - } - } + //If pgModeler bundles plugins, add the root plugins path to lib search paths + if(dir.exists(GlobalAttributes::PLUGINS_DIR)) + this->addLibraryPath(GlobalAttributes::PLUGINS_DIR); //Check if the temporary dir exists, if not, creates it. if(!dir.exists(GlobalAttributes::TEMPORARY_DIR)) diff --git a/main/src/application.h b/main/src/application.h index ab12bc8b4..ae9c530c9 100644 --- a/main/src/application.h +++ b/main/src/application.h @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/main/src/main.cpp b/main/src/main.cpp index 9cb84b354..8c29ccaaa 100644 --- a/main/src/main.cpp +++ b/main/src/main.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/pgmodeler.pri b/pgmodeler.pri index 27fa65153..d74b69a94 100644 --- a/pgmodeler.pri +++ b/pgmodeler.pri @@ -146,18 +146,18 @@ unix:!macx { } macx { - PGSQL_LIB = /Library/PostgreSQL/9.6/lib/libpq.dylib - PGSQL_INC = /Library/PostgreSQL/9.6/include + PGSQL_LIB = /Library/PostgreSQL/10/lib/libpq.dylib + PGSQL_INC = /Library/PostgreSQL/10/include XML_INC = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/libxml2 XML_LIB = /usr/lib/libxml2.dylib INCLUDEPATH += $$PGSQL_INC $$XML_INC } windows { - !defined(PGSQL_LIB, var): PGSQL_LIB = C:/PostgreSQL/9.6/lib/libpq.dll - !defined(PGSQL_INC, var): PGSQL_INC = C:/PostgreSQL/9.6/include - !defined(XML_INC, var): XML_INC = C:/PostgreSQL/9.6/include - !defined(XML_LIB, var): XML_LIB = C:/PostgreSQL/9.6/bin/libxml2.dll + !defined(PGSQL_LIB, var): PGSQL_LIB = C:/PostgreSQL/10.1/lib/libpq.dll + !defined(PGSQL_INC, var): PGSQL_INC = C:/PostgreSQL/10.1/include + !defined(XML_INC, var): XML_INC = C:/PostgreSQL/10.1/include + !defined(XML_LIB, var): XML_LIB = C:/PostgreSQL/10.1/bin/libxml2.dll # Workaround to solve bug of timespec struct on MingW + PostgreSQL < 9.4 QMAKE_CXXFLAGS+="-DHAVE_STRUCT_TIMESPEC" diff --git a/plugins/dummy/src/dummy.cpp b/plugins/dummy/src/dummy.cpp index 6bb21ca47..e74b5980f 100644 --- a/plugins/dummy/src/dummy.cpp +++ b/plugins/dummy/src/dummy.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/plugins/dummy/src/dummy.h b/plugins/dummy/src/dummy.h index 1a6e2fb70..a9f7ed13e 100644 --- a/plugins/dummy/src/dummy.h +++ b/plugins/dummy/src/dummy.h @@ -1,7 +1,7 @@ /* # Projeto: Modelador de Banco de Dados PostgreSQL (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/plugins/xml2object/src/xml2object.cpp b/plugins/xml2object/src/xml2object.cpp index 0e89d30c6..1b8d722c7 100644 --- a/plugins/xml2object/src/xml2object.cpp +++ b/plugins/xml2object/src/xml2object.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/plugins/xml2object/src/xml2object.h b/plugins/xml2object/src/xml2object.h index 63cfbdea4..005d7d660 100644 --- a/plugins/xml2object/src/xml2object.h +++ b/plugins/xml2object/src/xml2object.h @@ -1,7 +1,7 @@ /* # Projeto: Modelador de Banco de Dados PostgreSQL (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/samples/pagila.dbm b/samples/pagila.dbm index 454a0e32a..f5555d99c 100644 --- a/samples/pagila.dbm +++ b/samples/pagila.dbm @@ -47,11 +47,13 @@ CAUTION: Do not modify this file unless you know what you are doing. - + - - = 1901) AND (VALUE <= 2155))]]> + + + = 1901) AND (VALUE <= 2155))]]> + =f "9.5") %then + + %if {allow-conns} %or {is-template} %then + + [ALTER ] {sql-object} $sp {signature} [ WITH ] + + %if {allow-conns} %then + $br $tb [ ALLOW_CONNECTIONS ] {allow-conns} + %end + + %if {is-template} %then + $br $tb [ IS_TEMPLATE ] {is-template} + %end + + ; $br + + [-- ddl-end --] $br + + %end + +%end diff --git a/schemas/alter/diff.sch b/schemas/alter/diff.sch index 568927598..d0d91af49 100644 --- a/schemas/alter/diff.sch +++ b/schemas/alter/diff.sch @@ -4,8 +4,11 @@ # Code generation can be broken if incorrect changes are made. %if {has-changes} %then - [-- Database diff generated with pgModeler (PostgreSQL Database Modeler).] $br - [-- pgModeler version: ] {pgmodeler-ver} $br + [-- Diff code generated with pgModeler (PostgreSQL Database Modeler)] $br + [-- pgModeler version: ] {pgmodeler-ver} $br + [-- Diff date: ] {date} $br + [-- Source model: ] {dbmodel} $br + [-- Database: ] {database} $br [-- PostgreSQL version: ] {pgsql-ver} $br $br diff --git a/schemas/alter/domain.sch b/schemas/alter/domain.sch index 70d05112b..c65758dc3 100644 --- a/schemas/alter/domain.sch +++ b/schemas/alter/domain.sch @@ -31,30 +31,6 @@ %end #Changing CHECK expression -%if {expression} %then - [ALTER ] {sql-object} $sp {signature} - - %if ({expression} == "unset") %then - [ DROP CONSTRAINT ] - %else - [ ADD CONSTRAINT ] - %end - - %if {constraint} %then - {constraint} - %end - - %if ({expression} != "unset") %then - $sp CHECK({expression}) - %end - - ; $br - [-- ddl-end --] $br -%end - -#Changing constraint name (only in 9.2 or above) -%if ({pgsql-ver} >=f "9.2") %and {old-name} %and {new-name} %then - [ALTER ] {sql-object} $sp {signature} - [ RENAME CONSTRAINT ] {old-name} [ TO ] {new-name} ; $br - [-- ddl-end --] $br +%if {constraints} %then + {constraints} %end diff --git a/schemas/alter/domconstraint.sch b/schemas/alter/domconstraint.sch new file mode 100644 index 000000000..74145e32f --- /dev/null +++ b/schemas/alter/domconstraint.sch @@ -0,0 +1,23 @@ +# SQL definition for domain's constraints change +# PostgreSQL Version: 9.x +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[ALTER ] {sql-object} $sp {signature} + + %if ({expression} == "unset") %then + [ DROP CONSTRAINT ] + %else + [ ADD CONSTRAINT ] + %end + + %if {name} %then + {name} + %end + + %if ({expression} != "unset") %then + $sp CHECK $sp ({expression}) + %end + +; $br +[-- ddl-end --] $br diff --git a/schemas/alter/policy.sch b/schemas/alter/policy.sch new file mode 100644 index 000000000..66d9f1107 --- /dev/null +++ b/schemas/alter/policy.sch @@ -0,0 +1,29 @@ +# SQL definition for policy's attributes change +# PostgreSQL Version: 9.x +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +{alter-cmds} + +%if {has-changes} %then + [ALTER ] {sql-object} $sp {signature} + + %if {roles} %then + $br $tb [TO ] + + %if ({roles} == "unset") %then + PUBLIC + %else + {roles} + %end + %end + + %if {using-exp} %then + $br $tb [USING (] {using-exp} [)] + %end + + %if {check-exp} %then + $br $tb [WITH CHECK (] {check-exp} [)] + %end + {ddl-end} +%end diff --git a/schemas/alter/role.sch b/schemas/alter/role.sch index 636d2b274..33ed88e86 100644 --- a/schemas/alter/role.sch +++ b/schemas/alter/role.sch @@ -44,6 +44,12 @@ REPLICATION %end + %if {bypassrls} %and ({pgsql-ver} >=f "9.5") %then + $br $tb + %if ({bypassrls}=="unset") %then NO %end + BYPASSRLS + %end + %if {password} %then $br $tb diff --git a/schemas/alter/table.sch b/schemas/alter/table.sch index 066e3c98e..5d28bd1e0 100644 --- a/schemas/alter/table.sch +++ b/schemas/alter/table.sch @@ -6,20 +6,57 @@ {alter-cmds} %if {has-changes} %then - ALTER $sp {sql-object} $sp {signature} - + %set {alter} ALTER $sp {sql-object} $sp {signature} + %set {rls} [ROW LEVEL SECURITY] + %set {ddl-end} ; $br [-- ddl-end --] $br + %if {oids} %then - [ SET ] - + {alter} [ SET ] + %if ({oids}=="unset") %then WITHOUT %else WITH %end - + [ OIDS] + {ddl-end} + %end + + %if {unlogged} %then + {alter} [ SET ] + + %if ({unlogged}=="unset") %then + [LOGGED] + %else + [UNLOGGED] + %end + + {ddl-end} + %end + + %if {rls-enabled} %then + {alter} + + %if ({rls-enabled}=="unset") %then + [ DISABLE ] + %else + [ ENABLE ] + %end + + {rls} + {ddl-end} + %end + + %if {rls-forced} %then + {alter} + + %if ({rls-forced}=="unset") %then + [ NO] + %end + + [ FORCE ] {rls} + {ddl-end} %end - ; $br - [-- ddl-end --] $br %end diff --git a/schemas/alter/truncate.sch b/schemas/alter/truncate.sch index f7b26cbb4..39a822b51 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/column.sch b/schemas/catalog/column.sch index 67e0762f1..40cba2e28 100644 --- a/schemas/catalog/column.sch +++ b/schemas/catalog/column.sch @@ -17,6 +17,16 @@ cl.attacl AS permission, df.adsrc AS default_value, ds.description AS comment, tb.oid AS table, ] + %if ({pgsql-ver} >=f "10.0") %then + [ CASE + WHEN cl.attidentity = 'a' THEN 'ALWAYS' + WHEN cl.attidentity = 'd' THEN 'BY DEFAULT' + ELSE NULL + END AS identity_type, ] + %else + [ NULL AS identity_type, ] + %end + #Creating an attribute to indicate if the column is inherited or not [ CASE WHEN cl.attinhcount > 0 THEN TRUE diff --git a/schemas/catalog/getcomment.sch b/schemas/catalog/comment.sch similarity index 100% rename from schemas/catalog/getcomment.sch rename to schemas/catalog/comment.sch diff --git a/schemas/catalog/constraint.sch b/schemas/catalog/constraint.sch index 055cb0612..22d125f48 100644 --- a/schemas/catalog/constraint.sch +++ b/schemas/catalog/constraint.sch @@ -39,7 +39,7 @@ %else %if {attribs} %then - [SELECT cs.oid, cs.conname AS name, cs.conrelid AS table, ds.description AS comment, + [SELECT cs.oid, cs.conname AS name, cs.conrelid AS table, cs.conkey AS src_columns, cs.confkey AS dst_columns, cs.consrc AS expression, cs.condeferrable AS deferrable_bool, cs.confrelid AS ref_table, cl.reltablespace AS tablespace, cs.conexclop AS operators, @@ -48,9 +48,9 @@ [ id.indkey::oid] $ob $cb [ AS columns, id. indclass::oid] $ob $cb [ AS opclasses, pg_get_expr(id.indpred, id.indexrelid) AS condition, - pg_get_expr(id.indexprs, id.indexrelid) AS expressions, ] + pg_get_constraintdef(cs.oid) AS expressions, ] - %if ({pgsql-ver} <=f "9.1") %then + %if ({pgsql-ver} <=f "9.1") %then [ FALSE AS no_inherit_bool, ] %else [ cs.connoinherit AS no_inherit_bool, ] @@ -97,13 +97,14 @@ WHEN 'f' THEN 'MATCH FULL' WHEN 'p' THEN 'MATCH PARTIAL' ] - [ WHEN ] %if ({pgsql-ver} >=f "9.3") %then 's' %else 'u' %end [ THEN 'MATCH SIMPLE' ] + [ WHEN ] %if ({pgsql-ver} >=f "9.3") %then 's' %else 'u' %end [ THEN 'MATCH SIMPLE' ] [ ELSE NULL - END AS comparison_type + END AS comparison_type, ] - FROM pg_constraint AS cs - LEFT JOIN pg_description AS ds ON ds.objoid=cs.oid + ({comment}) [ AS comment ] + + [ FROM pg_constraint AS cs LEFT JOIN pg_class AS cl ON cl.oid = cs.conindid LEFT JOIN pg_am AS am ON cl.relam = am.oid LEFT JOIN pg_index AS id ON id.indexrelid= cs.conindid ] diff --git a/schemas/catalog/database.sch b/schemas/catalog/database.sch index b995a6dac..3a7179aaa 100644 --- a/schemas/catalog/database.sch +++ b/schemas/catalog/database.sch @@ -17,6 +17,11 @@ datacl AS permission, dattablespace AS tablespace, datdba AS owner, NULL AS template, ] ({comment}) [ AS comment ] + + %if ({pgsql-ver} >=f "9.5") %then + [ , datallowconn AS allow_conns_bool, datistemplate AS is_template_bool ] + %end + [ FROM pg_database WHERE datistemplate = FALSE ] %if {last-sys-oid} %then diff --git a/schemas/catalog/domain.sch b/schemas/catalog/domain.sch index f731c1df7..04c8d0e53 100644 --- a/schemas/catalog/domain.sch +++ b/schemas/catalog/domain.sch @@ -25,7 +25,7 @@ dm.typbasetype AS type, ] #TODO: Discover which field is the acl for domain on PgSQL 9.0 and 9.1 - %if ({pgsql-ver} <=f "9.1") %then + %if ({pgsql-ver} <=f "9.1") %then [ NULL AS permission, NULL AS collation, ] %else [ dm.typacl AS permission, dm.typcollation AS collation, ] @@ -37,20 +37,20 @@ END AS length, CASE - WHEN _dm1.numeric_precision_radix IS NOT NULL THEN _dm1.numeric_scale ] %if ({pgsql-ver} <=f "9.1") %then [::varchar] %end - [ WHEN _dm1.datetime_precision IS NOT NULL THEN _dm1.datetime_precision ] %if ({pgsql-ver} <=f "9.1") %then [::varchar] %end - [ WHEN _dm1.interval_precision IS NOT NULL THEN _dm1.interval_precision ] %if ({pgsql-ver} <=f "9.1") %then [::varchar] %end + WHEN _dm1.numeric_precision_radix IS NOT NULL THEN _dm1.numeric_scale ] %if ({pgsql-ver} <=f "9.1") %then [::varchar] %end + [ WHEN _dm1.datetime_precision IS NOT NULL THEN _dm1.datetime_precision ] %if ({pgsql-ver} <=f "9.1") %then [::varchar] %end + [ WHEN _dm1.interval_precision IS NOT NULL THEN _dm1.interval_precision ] %if ({pgsql-ver} <=f "9.1") %then [::varchar] %end [ ELSE NULL END AS precision, dm.typnotnull AS not_null_bool, _dm1.interval_type, _dm1.domain_default AS default_value, - cn.conname AS constraint, cn.consrc AS expression, ] + (select array_agg(conname || ':' || consrc) from pg_constraint where contypid = dm.oid) as constraints, + ] ({comment}) [ AS comment ] [ FROM pg_type AS dm - LEFT JOIN pg_constraint AS cn ON cn.contypid=dm.oid LEFT JOIN information_schema.domains AS _dm1 ON dm.typname=_dm1.domain_name WHERE dm.typrelid=0 ] diff --git a/schemas/catalog/function.sch b/schemas/catalog/function.sch index 3616175af..fea8fbe3a 100644 --- a/schemas/catalog/function.sch +++ b/schemas/catalog/function.sch @@ -64,7 +64,7 @@ ELSE 'CALLED ON NULL INPUT' END AS behavior_type, ] - %if ({pgsql-ver} <=f "9.1") %then + %if ({pgsql-ver} <=f "9.1") %then [ NULL AS leakproof_bool, ] %else [ pr.proleakproof AS leakproof_bool, ] diff --git a/schemas/catalog/index.sch b/schemas/catalog/index.sch index 3efde49d8..4b90e409a 100644 --- a/schemas/catalog/index.sch +++ b/schemas/catalog/index.sch @@ -58,12 +58,15 @@ [ id.indkey::oid] $ob $cb [ AS columns, id.indclass::oid] $ob $cb [ AS opclasses, pg_get_expr(indexprs, indrelid) AS expressions, - pg_get_expr(indpred, indrelid, true) predicate, - ds.description AS comment + pg_get_expr(indpred, indrelid, true) predicate, ] + + ({comment}) [ AS comment ] + + [ FROM pg_index AS id LEFT JOIN pg_class AS cl ON cl.oid = id.indexrelid LEFT JOIN pg_am AS am ON cl.relam = am.oid - LEFT JOIN pg_description ds ON ds.objoid = id.indexrelid ] + ] %if {schema} %then [ LEFT JOIN pg_class AS tb ON id.indrelid = tb.oid diff --git a/schemas/catalog/policy.sch b/schemas/catalog/policy.sch new file mode 100644 index 000000000..5ef4071ac --- /dev/null +++ b/schemas/catalog/policy.sch @@ -0,0 +1,86 @@ +# Catalog queries for policies +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} >=f "9.5") %then + + %if {list} %then + [SELECT pl.oid, polname AS name FROM pg_policy AS pl ] + + %if {schema} %then + [ LEFT JOIN pg_class AS tb ON pl.polrelid = tb.oid + LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace + WHERE nspname= ] '{schema}' + + %if {table} %then + [ AND tb.relkind='r' AND tb.relname=] '{table}' + %end + + [ AND ] + %else + [ WHERE ] + %end + + %if {last-sys-oid} %then + [ pl.oid ] {oid-filter-op} $sp {last-sys-oid} + %end + + %if {not-ext-object} %then + + %if {last-sys-oid} %then + [ AND ] + %end + + ( {not-ext-object} ) + %end + + %else + [SELECT pl.oid, pl.polname AS name, pl.polrelid AS table, ] + + %if ({pgsql-ver} >=f "10.0") %then + [ pl.polpermissive AS permissive_bool, ] + %else + [ TRUE AS permissive_bool, ] + %end + + [ pg_get_expr(pl.polqual, pl.polrelid, true) AS using_exp, + pg_get_expr(pl.polwithcheck, pl.polrelid, true) AS check_exp, + + CASE pl.polcmd + WHEN '*' THEN 'ALL' + WHEN 'r' THEN 'SELECT' + WHEN 'a' THEN 'INSERT' + WHEN 'w' THEN 'UPDATE' + ELSE 'DELETE' + END AS command, + + pl.polroles AS roles, ] + + ({comment}) [ AS comment ] + + [ FROM pg_policy AS pl ] + + %if {last-sys-oid} %then + [ WHERE pl.oid ] {oid-filter-op} $sp {last-sys-oid} + %end + + %if {filter-oids} %then + %if {last-sys-oid} %then + [ AND] + %else + [ WHERE ] + %end + + [ pl.oid IN (] {filter-oids} ) + %end + + %if {not-ext-object} %then + %if {last-sys-oid} %or {filter-oids} %then + [ AND ] + %else + [ WHERE ] + %end + ( {not-ext-object} ) + %end + %end +%end diff --git a/schemas/catalog/role.sch b/schemas/catalog/role.sch index 1804bd1b4..3c4ebbd4f 100644 --- a/schemas/catalog/role.sch +++ b/schemas/catalog/role.sch @@ -25,6 +25,12 @@ %else [ NULL AS replication_bool, ] %end + + %if ({pgsql-ver} >=f "9.5") %then + [ rolbypassrls AS bypassrls_bool, ] + %else + [ NULL AS bypassrls_bool, ] + %end [ (SELECT array_agg(rl.oid) AS member_roles FROM pg_auth_members AS am LEFT JOIN pg_roles AS rl ON rl.oid=am.member diff --git a/schemas/catalog/sequence.sch b/schemas/catalog/sequence.sch index 5c0aa50bc..b01c7b0b2 100644 --- a/schemas/catalog/sequence.sch +++ b/schemas/catalog/sequence.sch @@ -23,24 +23,38 @@ %else %if {attribs} %then #Creates a temporary function to retrieve the sequence attributes - [CREATE OR REPLACE FUNCTION pg_temp.get_seq_attribs(text,text) + [CREATE OR REPLACE FUNCTION pg_temp.__pgmodeler_tmp_get_seq_attribs(text,text) RETURNS text AS $$ DECLARE res record; - BEGIN - EXECUTE 'SELECT start_value, min_value, max_value, increment_by, cache_value, ' || - ' CASE WHEN is_cycled IS FALSE THEN NULL ' || - ' ELSE is_cycled END FROM ' || '"' || $1 || '"' || '.' || '"' || $2 || '"' || ' LIMIT 1;' INTO res; - RETURN replace(replace(res::text,'(','{'),')','}'); + BEGIN ] + + %if ({pgsql-ver} <=f "9.6") %then + [ EXECUTE 'SELECT start_value, min_value, max_value, increment_by, cache_value, ' || + ' CASE WHEN is_cycled IS FALSE THEN NULL ' || + ' ELSE is_cycled END FROM ' || '"' || $1 || '"' || '.' || '"' || $2 || '"' || ' LIMIT 1;' INTO res; ] + %else + + [ EXECUTE 'SELECT s.seqstart AS start_value, s.seqmin AS min_value, s.seqmax AS max_value, ' || + ' s.seqincrement AS increment_by, seqcache as cache_value, ' || + ' CASE WHEN seqcycle IS FALSE THEN NULL ELSE seqcycle END AS is_cycled ' || + ' FROM pg_sequence AS s ' || + ' LEFT JOIN pg_class AS c ON s.seqrelid = c.oid ' || + ' LEFT JOIN pg_namespace AS n ON n.oid = c.relnamespace ' || + ' WHERE n.nspname = ''' || $1 ||''' AND c.relname = ''' || $2 ||''' LIMIT 1;' INTO res; ] + %end + + + [ RETURN replace(replace(res::text,'(','{'),')','}'); END $$ - LANGUAGE plpgsql;] + LANGUAGE plpgsql; ] [ SELECT sq.oid, sq.relname AS name, sq.relnamespace AS schema, sq.relowner AS owner, - (SELECT refobjid || ':' || refobjsubid FROM pg_depend WHERE objid=sq.oid AND deptype='a') AS owner_col, - (pg_temp.get_seq_attribs(ns.nspname, sq.relname)) AS attribute, ] + (SELECT refobjid || ':' || refobjsubid FROM pg_depend WHERE objid=sq.oid AND deptype in ('a', 'i')) AS owner_col, + (pg_temp.__pgmodeler_tmp_get_seq_attribs(ns.nspname, sq.relname)) AS attribute, ] ({comment}) [ AS comment ] diff --git a/schemas/catalog/table.sch b/schemas/catalog/table.sch index e0f6f66ca..aefff00e4 100644 --- a/schemas/catalog/table.sch +++ b/schemas/catalog/table.sch @@ -34,6 +34,14 @@ END AS unlogged_bool, ] %end + + %if ({pgsql-ver} 0) AS constraint_bool, ds.description AS comment, + (tg.tgconstraint > 0) AS constraint_bool, CASE WHEN B'0000010'::integer & tgtype = 2 THEN 'BEFORE' @@ -74,13 +74,14 @@ WHEN (tg.tgconstraint > 0) THEN regexp_replace(regexp_replace(pg_get_triggerdef(tg.oid), '(.)+((INSERT|DELETE|UPDATE)|( OF))', ''), '( ON)(.)*','') ELSE NULL - END AS columns + END AS columns, ] - FROM pg_trigger AS tg + ({comment}) [ AS comment ] + + [ FROM pg_trigger AS tg LEFT JOIN pg_constraint AS cs ON tg.tgconstraint = cs.oid LEFT JOIN pg_class AS tb ON tg.tgrelid = tb.oid LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace - LEFT JOIN pg_description ds ON ds.objoid = tg.oid LEFT JOIN information_schema.triggers AS it ON it.trigger_schema=ns.nspname AND it.trigger_name=tg.tgname AND diff --git a/schemas/catalog/usertype.sch b/schemas/catalog/usertype.sch index 79c5de5b0..f0c817564 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 @@ -130,7 +130,7 @@ LEFT JOIN pg_namespace AS ns ON tp.typnamespace = ns.oid ] #Excluding types related to tables/views/sequeces - [ WHERE typtype IN ('p','b','c','e','r') AND typname NOT LIKE 'pg_%' ] + [ WHERE typtype IN ('p','b','c','e','r', 'd') AND typname NOT LIKE 'pg_%' ] #Excluding types related to tables/views/sequeces/materialized views %if {filter-tab-types} %then diff --git a/schemas/sql/column.sch b/schemas/sql/column.sch index 2fc36a117..165be70e5 100644 --- a/schemas/sql/column.sch +++ b/schemas/sql/column.sch @@ -19,8 +19,12 @@ [ NOT NULL] %end -%if {default-value} %then - [ DEFAULT ] {default-value} +%if ({pgsql-ver} >=f "10.0") %and {identity-type} %then + [ GENERATED ] {identity-type} [ AS IDENTITY ] +%else + %if {default-value} %then + [ DEFAULT ] {default-value} + %end %end %if {decl-in-table} %then diff --git a/schemas/sql/database.sch b/schemas/sql/database.sch index e92114b12..deee7dfe1 100644 --- a/schemas/sql/database.sch +++ b/schemas/sql/database.sch @@ -5,8 +5,6 @@ [-- object: ] {name} [ | type: ] {sql-object} [ --] $br -%if {comment} %then [-- ] {comment} [ --] $br %end - [-- ] {drop} %if {prepended-sql} %then @@ -14,34 +12,44 @@ $br [-- ddl-end --] $br $br %end -[CREATE DATABASE ] {name} $br +[CREATE DATABASE ] {name} %if {template} %then - $tb [TEMPLATE = ] {template} $br + $br $tb [TEMPLATE = ] {template} %end %if {encoding} %then - $tb [ENCODING = ] {encoding} $br + $br $tb [ENCODING = ] {encoding} %end - %if {lc-collate} %then - $tb [LC_COLLATE = ] {lc-collate} $br - %end +%if {lc-collate} %then + $br $tb [LC_COLLATE = ] {lc-collate} +%end - %if {lc-ctype} %then - $tb [LC_CTYPE = ] {lc-ctype} $br - %end +%if {lc-ctype} %then + $br $tb [LC_CTYPE = ] {lc-ctype} +%end %if {tablespace} %then - $tb [TABLESPACE = ] {tablespace} $br + $br $tb [TABLESPACE = ] {tablespace} %end %if {owner} %then - $tb [OWNER = ] {owner} $br + $br $tb [OWNER = ] {owner} %end %if {connlimit} %then - $tb [CONNECTION LIMIT = ] {connlimit} $br + $br $tb [CONNECTION LIMIT = ] {connlimit} +%end + +%if ({pgsql-ver} >=f "9.5") %then + %if ({is-template} == "true") %then + $br $tb [IS_TEMPLATE = ] {is-template} + %end + + %if ({allow-conns} == "false") %then + $br $tb [ALLOW_CONNECTIONS = ] {allow-conns} + %end %end ; $br @@ -50,6 +58,8 @@ # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! [-- ddl-end --] $br +%if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} $br [-- ddl-end --] $br diff --git a/schemas/sql/dbmodel.sch b/schemas/sql/dbmodel.sch index 63f64dd78..4642eecdb 100644 --- a/schemas/sql/dbmodel.sch +++ b/schemas/sql/dbmodel.sch @@ -6,7 +6,7 @@ [-- Database generated with pgModeler (PostgreSQL Database Modeler).] $br [-- pgModeler version: ] {pgmodeler-ver} $br [-- PostgreSQL version: ] {pgsql-ver} $br -[-- Project Site: pgmodeler.com.br] $br +[-- Project Site: pgmodeler.io] $br [-- Model Author: ] %if {author} %then @@ -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/domain.sch b/schemas/sql/domain.sch index 876adebe0..d9d485767 100644 --- a/schemas/sql/domain.sch +++ b/schemas/sql/domain.sch @@ -26,15 +26,8 @@ $br $tb [NOT NULL] %end -%if {expression} %then - - $br $tb - - %if {constraint} %then - [CONSTRAINT ] {constraint} $sp - %end - - [CHECK ] ({expression}) +%if {constraints} %then + {constraints} %end ;$br diff --git a/schemas/sql/domconstraint.sch b/schemas/sql/domconstraint.sch new file mode 100644 index 000000000..47f67bc7d --- /dev/null +++ b/schemas/sql/domconstraint.sch @@ -0,0 +1,6 @@ +# SQL definition for domain's check constraint +# PostgreSQL Version: 9.x +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$br $tb CONSTRAINT $sp {name} $sp CHECK $sp ({expression}) diff --git a/schemas/sql/extension.sch b/schemas/sql/extension.sch index 4805f0fd3..845c7eacd 100644 --- a/schemas/sql/extension.sch +++ b/schemas/sql/extension.sch @@ -15,7 +15,10 @@ %end [CREATE EXTENSION ] {name} $br - [ WITH SCHEMA ] {schema} + + %if {schema} %then + [ WITH SCHEMA ] {schema} + %end %if {cur-version} %then $br [ VERSION ] '{cur-version}' diff --git a/schemas/sql/idxelement.sch b/schemas/sql/idxelement.sch index 2030a927a..2616540bc 100644 --- a/schemas/sql/idxelement.sch +++ b/schemas/sql/idxelement.sch @@ -7,7 +7,7 @@ $br $tb $sp $sp {column} %else %if {expression} %then - {expression} + ({expression}) %end %end diff --git a/schemas/sql/policy.sch b/schemas/sql/policy.sch new file mode 100644 index 000000000..4856c44fd --- /dev/null +++ b/schemas/sql/policy.sch @@ -0,0 +1,56 @@ +# SQL definition for policy +# PostgreSQL Version: 9.x +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +%if ({pgsql-ver} >=f "9.5") %then + [-- object: ] {name} [ | type: ] {sql-object} [ --] $br + [-- ] {drop} + + %if {prepended-sql} %then + {prepended-sql} + $br [-- ddl-end --] $br $br + %end + + [CREATE POLICY ] {name} [ ON ] {table} + + %if ({pgsql-ver} >=f "10.0") %then + %if {permissive} %then + $br $tb [AS PERMISSIVE] + %else + $br $tb [AS RESTRICTIVE] + %end + %end + + $br $tb [FOR ] {command} + $br $tb [TO ] + + %if {roles} %then + {roles} + %else + PUBLIC + %end + + %if {using-exp} %then + $br $tb [USING (] {using-exp} [)] + %end + + %if {check-exp} %then + $br $tb [WITH CHECK (] {check-exp} [)] + %end + + ;$br + + # This is a special token that pgModeler recognizes as end of DDL command + # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! + [-- ddl-end --] $br + + %if {comment} %then {comment} %end + + %if {appended-sql} %then + {appended-sql} + $br [-- ddl-end --] $br + %end + + $br +%end diff --git a/schemas/sql/role.sch b/schemas/sql/role.sch index c781e6f43..d73d511c5 100644 --- a/schemas/sql/role.sch +++ b/schemas/sql/role.sch @@ -19,7 +19,9 @@ %if {createrole} %then $br $tb CREATEROLE %end %if {inherit} %then $br $tb INHERIT %end %if {login} %then $br $tb LOGIN %end + %if {replication} %and ({pgsql-ver} != "9.0") %then $br $tb REPLICATION %end +%if {bypassrls} %and ({pgsql-ver} >=f "9.5") %then $br $tb BYPASSRLS %end %if {password} %then $br $tb diff --git a/schemas/sql/sequence.sch b/schemas/sql/sequence.sch index 52487602f..32a997fd7 100644 --- a/schemas/sql/sequence.sch +++ b/schemas/sql/sequence.sch @@ -45,7 +45,7 @@ $tb [OWNED BY ] %if {owner-col} %then {owner-col} %else NONE %end ; $br -%if {owner-col} %then +%if {owner-col} %and %not {col-is-identity} %then $br [ALTER TABLE ] {table} [ ALTER COLUMN ] {column} $br [ SET DEFAULT nextval('] {name} ['::regclass);] $br diff --git a/schemas/sql/table.sch b/schemas/sql/table.sch index 8ac0f984b..dcbdfd89c 100644 --- a/schemas/sql/table.sch +++ b/schemas/sql/table.sch @@ -63,6 +63,16 @@ $br ) %if {cols-comment} %then {cols-comment} %end %if {owner} %then {owner} %end +%if ({pgsql-ver} >=f "9.5") %and {rls-enabled} %then + [ALTER TABLE ] {name} [ ENABLE ROW LEVEL SECURITY;] + $br [-- ddl-end --] $br + + %if {rls-forced} %then + [ALTER TABLE ] {name} [ FORCE ROW LEVEL SECURITY;] + $br [-- ddl-end --] $br + %end +%end + %if {appended-sql} %then {appended-sql} $br [-- ddl-end --] $br diff --git a/schemas/sql/tablespace.sch b/schemas/sql/tablespace.sch index b07114e3c..b5b56f8a4 100644 --- a/schemas/sql/tablespace.sch +++ b/schemas/sql/tablespace.sch @@ -7,10 +7,6 @@ [-- ] {drop} -%if {comment} %then - -- {comment} -- $br -%end - %if {prepended-sql} %then {prepended-sql} $br [-- ddl-end --] $br $br @@ -28,6 +24,8 @@ $tb [LOCATION ] {directory}; $br # when exporting models directly to DBMS. DO NOT REMOVE THIS TOKEN! [-- ddl-end --] $br +%if {comment} %then {comment} %end + %if {appended-sql} %then {appended-sql} $br [-- ddl-end --] $br diff --git a/schemas/xml/aggregate.sch b/schemas/xml/aggregate.sch index 334375e71..a675c3412 100644 --- a/schemas/xml/aggregate.sch +++ b/schemas/xml/aggregate.sch @@ -22,7 +22,8 @@ %if {appended-sql} %then {appended-sql} %end %if {prepended-sql} %then {prepended-sql} %end - {types} + %if {types} %then {types} %end + {state-type} {transition} %if {final} %then {final} %end diff --git a/schemas/xml/cast.sch b/schemas/xml/cast.sch index 4bef92c47..64a60e08c 100644 --- a/schemas/xml/cast.sch +++ b/schemas/xml/cast.sch @@ -1,7 +1,11 @@ # XML definition for type casts # CAUTION: Do not modify this file unless you know what you are doing. # Code generation can be broken if incorrect changes are made. -[ $br diff --git a/schemas/xml/domain.sch b/schemas/xml/domain.sch index 2d69d17c0..2442b7be2 100644 --- a/schemas/xml/domain.sch +++ b/schemas/xml/domain.sch @@ -6,9 +6,10 @@ %if {reduced-form} %then /> $br %else - %if {constraint} %then - [ constraint=] "{constraint}" - %end + + #%if {constraint} %then + # [ constraint=] "{constraint}" + #%end [ not-null=] %if {not-null} %then "true" %else "false" %end %if {default-value} %then [ default-value=] "{default-value}" %end @@ -30,11 +31,11 @@ %if {appended-sql} %then {appended-sql} %end %if {prepended-sql} %then {prepended-sql} %end - $tb {type} + {type} - %if {expression} %then - $tb $br + %if {constraints} %then + {constraints} %end - $br $br + $br $br %end diff --git a/schemas/xml/domconstraint.sch b/schemas/xml/domconstraint.sch new file mode 100644 index 000000000..f165ea0fb --- /dev/null +++ b/schemas/xml/domconstraint.sch @@ -0,0 +1,8 @@ +# XML definition for domain's check constraint +# PostgreSQL Version: 9.x +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +$tb [] $br +$tb $tb $br +$tb [] $br diff --git a/schemas/xml/dtd/baseelements.dtd b/schemas/xml/dtd/baseelements.dtd index c4ad2f4b6..9b963d26c 100644 --- a/schemas/xml/dtd/baseelements.dtd +++ b/schemas/xml/dtd/baseelements.dtd @@ -11,7 +11,7 @@ - + diff --git a/schemas/xml/dtd/column.dtd b/schemas/xml/dtd/column.dtd index 5480ee807..4fc46fb71 100644 --- a/schemas/xml/dtd/column.dtd +++ b/schemas/xml/dtd/column.dtd @@ -9,3 +9,4 @@ + diff --git a/schemas/xml/dtd/conversion.dtd b/schemas/xml/dtd/conversion.dtd index 1b929cde6..90c41c157 100644 --- a/schemas/xml/dtd/conversion.dtd +++ b/schemas/xml/dtd/conversion.dtd @@ -7,4 +7,5 @@ + diff --git a/schemas/xml/dtd/database.dtd b/schemas/xml/dtd/database.dtd index a09dbe0fa..467dddaa3 100644 --- a/schemas/xml/dtd/database.dtd +++ b/schemas/xml/dtd/database.dtd @@ -9,6 +9,8 @@ + + diff --git a/schemas/xml/dtd/dbmodel.dtd b/schemas/xml/dtd/dbmodel.dtd index 7d9bf3dc3..32c45743a 100644 --- a/schemas/xml/dtd/dbmodel.dtd +++ b/schemas/xml/dtd/dbmodel.dtd @@ -64,6 +64,8 @@ %eventtrigger; %genericsql; + +%policy; diff --git a/schemas/xml/dtd/domain.dtd b/schemas/xml/dtd/domain.dtd index e14e2dc8d..fc681686e 100644 --- a/schemas/xml/dtd/domain.dtd +++ b/schemas/xml/dtd/domain.dtd @@ -2,7 +2,7 @@ CAUTION: Do not modify this file directly on it's code unless you know what you are doing. Unexpected results may occur if the code is changed deliberately. --> - + diff --git a/schemas/xml/dtd/extension.dtd b/schemas/xml/dtd/extension.dtd index 363cf7512..7deb70a31 100644 --- a/schemas/xml/dtd/extension.dtd +++ b/schemas/xml/dtd/extension.dtd @@ -2,7 +2,7 @@ CAUTION: Do not modify this file directly on it's code unless you know what you are doing. Unexpected results may occur if the code is changed deliberately. --> - + diff --git a/schemas/xml/dtd/policy.dtd b/schemas/xml/dtd/policy.dtd new file mode 100644 index 000000000..bc5c4d06b --- /dev/null +++ b/schemas/xml/dtd/policy.dtd @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/schemas/xml/dtd/relationship.dtd b/schemas/xml/dtd/relationship.dtd index b1cf092d3..01baad3ad 100644 --- a/schemas/xml/dtd/relationship.dtd +++ b/schemas/xml/dtd/relationship.dtd @@ -31,6 +31,7 @@ + diff --git a/schemas/xml/dtd/role.dtd b/schemas/xml/dtd/role.dtd index 4723b9bdf..da5223079 100644 --- a/schemas/xml/dtd/role.dtd +++ b/schemas/xml/dtd/role.dtd @@ -10,6 +10,7 @@ + diff --git a/schemas/xml/dtd/table.dtd b/schemas/xml/dtd/table.dtd index 01fd93ada..5e4c9aa92 100644 --- a/schemas/xml/dtd/table.dtd +++ b/schemas/xml/dtd/table.dtd @@ -20,3 +20,5 @@ + + diff --git a/schemas/xml/extension.sch b/schemas/xml/extension.sch index 2645b39f4..ad562e95f 100644 --- a/schemas/xml/extension.sch +++ b/schemas/xml/extension.sch @@ -24,7 +24,10 @@ > $br - {schema} + %if {schema} %then + {schema} + %end + %if {comment} %then {comment} %end %if {appended-sql} %then {appended-sql} %end %if {prepended-sql} %then {prepended-sql} %end diff --git a/schemas/xml/policy.sch b/schemas/xml/policy.sch new file mode 100644 index 000000000..d33cacec7 --- /dev/null +++ b/schemas/xml/policy.sch @@ -0,0 +1,31 @@ +# XML definition for policies +# CAUTION: Do not modify this file unless you know what you are doing. +# Code generation can be broken if incorrect changes are made. + +[ $br + +%if {comment} %then {comment} %end +%if {appended-sql} %then {appended-sql} %end +%if {prepended-sql} %then {prepended-sql} %end + +%if {roles} %then + $tb [] +%end + +%if {using-exp} %then + $br $tb [] +%end + +%if {check-exp} %then + $br $tb [] +%end + +$br + + diff --git a/schemas/xml/relationship.sch b/schemas/xml/relationship.sch index 966fa81db..beec9afdb 100644 --- a/schemas/xml/relationship.sch +++ b/schemas/xml/relationship.sch @@ -44,6 +44,10 @@ $br $tb [ src-table=] "{src-table}" $br $tb [ dst-table=] "{dst-table}" +%if {reference-fk} %then +[ reference-fk=] "{reference-fk}" +%end + %if %not {relgen} %and %not {reldep} %then $br $tb diff --git a/schemas/xml/role.sch b/schemas/xml/role.sch index f69c6a523..9e731932b 100644 --- a/schemas/xml/role.sch +++ b/schemas/xml/role.sch @@ -13,6 +13,7 @@ %if {createrole} %then $br [ createrole="true"] %end %if {inherit} %then $br [ inherit="true"] %end %if {login} %then $br [ login="true"] %end + %if {bypassrls} %then $br [ bypassrls="true"] %end %if {encrypted} %then $br [ encrypted="true"] %end %if {connlimit} %then $br [ connlimit=]"{connlimit}" %end %if {validity} %then $br [ validity=]"{validity}" %end diff --git a/schemas/xml/table.sch b/schemas/xml/table.sch index 9914da30d..f7d29dddf 100644 --- a/schemas/xml/table.sch +++ b/schemas/xml/table.sch @@ -9,6 +9,8 @@ %if {sql-disabled} %then [ sql-disabled=] "true" %end %if {hide-ext-attribs} %then [ hide-ext-attribs=] "true" %end %if {faded-out} %then [ faded-out=] "true" %end + %if {rls-enabled} %then [ rls-enabled=] "true" %end + %if {rls-forced} %then [ rls-forced=] "true" %end > $br {schema} diff --git a/schemas/xml/view.sch b/schemas/xml/view.sch index 69adcd1cd..fb4d9d0ef 100644 --- a/schemas/xml/view.sch +++ b/schemas/xml/view.sch @@ -34,6 +34,10 @@ %if {simple-exp} %then $tb [] {simple-exp} $br %end + + %if {end-exp} %then + $tb [] {end-exp} $br + %end %if {cte-exp} %then $tb [] $br diff --git a/tests/src/baseobjecttest/baseobjecttest.cpp b/tests/src/baseobjecttest/baseobjecttest.cpp index 6e171e2a5..374d7b041 100644 --- a/tests/src/baseobjecttest/baseobjecttest.cpp +++ b/tests/src/baseobjecttest/baseobjecttest.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/tests/src/databasemodeltest/databasemodeltest.cpp b/tests/src/databasemodeltest/databasemodeltest.cpp index 8ece2b81b..d6f319ae8 100644 --- a/tests/src/databasemodeltest/databasemodeltest.cpp +++ b/tests/src/databasemodeltest/databasemodeltest.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/tests/src/linenumberstest/linenumberstest.cpp b/tests/src/linenumberstest/linenumberstest.cpp new file mode 100644 index 000000000..8fe982325 --- /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 000000000..728f7a5aa --- /dev/null +++ b/tests/src/linenumberstest/linenumberstest.pro @@ -0,0 +1,3 @@ +include(../../tests.pri) +SOURCES += linenumberstest.cpp + diff --git a/tests/src/main/main.cpp b/tests/src/main/main.cpp index 21810e82a..65e12c491 100644 --- a/tests/src/main/main.cpp +++ b/tests/src/main/main.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/tests/src/roletest/roletest.cpp b/tests/src/roletest/roletest.cpp index 3676bef8a..d3d582472 100644 --- a/tests/src/roletest/roletest.cpp +++ b/tests/src/roletest/roletest.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/tests/src/schemaparsertest/schemaparsertest.cpp b/tests/src/schemaparsertest/schemaparsertest.cpp index 9a50fc263..da23dd864 100644 --- a/tests/src/schemaparsertest/schemaparsertest.cpp +++ b/tests/src/schemaparsertest/schemaparsertest.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/tests/src/syntaxhighlightertest/syntaxhighlightertest.cpp b/tests/src/syntaxhighlightertest/syntaxhighlightertest.cpp index a500b2e21..cd6abe642 100644 --- a/tests/src/syntaxhighlightertest/syntaxhighlightertest.cpp +++ b/tests/src/syntaxhighlightertest/syntaxhighlightertest.cpp @@ -1,7 +1,7 @@ /* # PostgreSQL Database Modeler (pgModeler) # -# Copyright 2006-2017 - Raphael Araújo e Silva +# 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 diff --git a/tests/tests.pro b/tests/tests.pro index 6e60d5c27..b8020f021 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 \ diff --git a/windeploy.sh b/windeploy.sh index f84b53200..cffd57d6b 100644 --- a/windeploy.sh +++ b/windeploy.sh @@ -1,8 +1,8 @@ #!/bin/bash -QT_INSTALL_VERSION='5.6.2' -QT_BASE_VERSION='5.6' -PGSQL_VERSION='9.6' +QT_INSTALL_VERSION='5.9.3' +QT_BASE_VERSION='5.9.3' +PGSQL_VERSION='10.1' INNOSETUP_CMD='/c/Program Files (x86)/Inno Setup 5/ISCC.exe' LOG=windeploy.log @@ -51,36 +51,41 @@ if [ $X64_BUILD = 1 ]; then # Settings for x64 build QT_ROOT="/c/Qt/Qt${QT_INSTALL_VERSION}-x64/" QMAKE_ROOT=$QT_ROOT/bin - MINGW_ROOT="/c/msys64/mingw64/bin" + MINGW_ROOT="/c/msys_64/mingw64/bin" PGSQL_ROOT="/c/PostgreSQL/${PGSQL_VERSION}-x64/bin" QMAKE_ARGS="-r -spec win32-g++ CONFIG+=release \ - XML_INC+=$PGSQL_ROOT/../include \ - XML_LIB=$PGSQL_ROOT/libxml2.dll \ - PGSQL_INC+=$PGSQL_ROOT/../include \ - PGSQL_LIB+=$PGSQL_ROOT/libpq.dll" - DEP_LIBS="$QMAKE_ROOT/icudt55.dll \ - $QMAKE_ROOT/icuin55.dll \ - $QMAKE_ROOT/icuuc55.dll \ - $MINGW_ROOT/libgcc_s_seh-1.dll \ + XML_INC+=$MINGW_ROOT/../include/libxml2 \ + XML_LIB+=$MINGW_ROOT/libxml2-2.dll \ + PGSQL_INC+=$MINGW_ROOT/../include \ + PGSQL_LIB+=$MINGW_ROOT/libpq.dll" + DEP_LIBS="$MINGW_ROOT/libgcc_s_seh-1.dll \ $MINGW_ROOT/libstdc++-6.dll \ $MINGW_ROOT/libwinpthread-1.dll \ - $PGSQL_ROOT/libiconv-2.dll \ - $PGSQL_ROOT/libintl-8.dll" + $MINGW_ROOT/libiconv-2.dll \ + $MINGW_ROOT/libintl-8.dll \ + $MINGW_ROOT/zlib1.dll \ + $MINGW_ROOT/libxml2-2.dll \ + $MINGW_ROOT/libpq.dll \ + $MINGW_ROOT/libeay32.dll \ + $MINGW_ROOT/ssleay32.dll \ + $MINGW_ROOT/liblzma-5.dll" else # Default setting for x86 build - QT_ROOT="/c/Qt/Qt${QT_INSTALL_VERSION}/${QT_BASE_VERSION}/mingw49_32/" + QT_ROOT="/c/Qt/Qt${QT_INSTALL_VERSION}/${QT_BASE_VERSION}/mingw53_32/" QMAKE_ROOT=$QT_ROOT/bin QMAKE_ARGS="-r -spec win32-g++ CONFIG+=release" - MINGW_ROOT="/c/Qt/Qt${QT_INSTALL_VERSION}/Tools/mingw492_32/bin" + MINGW_ROOT="/c/Qt/Qt${QT_INSTALL_VERSION}/Tools/mingw530_32/bin" PGSQL_ROOT="/c/PostgreSQL/${PGSQL_VERSION}/bin" - DEP_LIBS="$QMAKE_ROOT/icudt54.dll \ - $QMAKE_ROOT/icuin54.dll \ - $QMAKE_ROOT/icuuc54.dll \ - $QMAKE_ROOT/libgcc_s_dw2-1.dll \ + DEP_LIBS="$QMAKE_ROOT/libgcc_s_dw2-1.dll \ $QMAKE_ROOT/libstdc++-6.dll \ $QMAKE_ROOT/libwinpthread-1.dll \ $PGSQL_ROOT/libiconv-2.dll \ - $PGSQL_ROOT/libintl-8.dll" + $PGSQL_ROOT/libintl-8.dll \ + $PGSQL_ROOT/zlib1.dll \ + $PGSQL_ROOT/libxml2.dll \ + $PGSQL_ROOT/libpq.dll \ + $PGSQL_ROOT/libeay32.dll \ + $PGSQL_ROOT/ssleay32.dll" fi if [ $DEMO_VERSION = 1 ]; then @@ -102,17 +107,10 @@ DEP_LIBS+=" $QMAKE_ROOT/Qt5Core.dll \ $QMAKE_ROOT/Qt5Widgets.dll \ $QMAKE_ROOT/Qt5PrintSupport.dll \ $QMAKE_ROOT/Qt5Network.dll \ - $QMAKE_ROOT/Qt5Svg.dll \ - $PGSQL_ROOT/libxml2.dll \ - $PGSQL_ROOT/libpq.dll \ - $PGSQL_ROOT/libeay32.dll \ - $PGSQL_ROOT/ssleay32.dll \ - $PGSQL_ROOT/zlib1.dll" + $QMAKE_ROOT/Qt5Svg.dll " #Dependency qt plugins copied to build dir -DEP_PLUGINS="imageformats/qdds.dll \ - imageformats/qgif.dll \ - imageformats/qicns.dll \ +DEP_PLUGINS="imageformats/qicns.dll \ imageformats/qico.dll \ imageformats/qjpeg.dll \ imageformats/qsvg.dll \ @@ -128,8 +126,8 @@ export PATH=$QMAKE_ROOT:$MINGW_ROOT:$PATH clear echo echo "pgModeler Windows deployment script" -echo "PostgreSQL Database Modeler Project - pgmodeler.com.br" -echo "Copyright 2006-2017 Raphael A. Silva " +echo "PostgreSQL Database Modeler Project - pgmodeler.io" +echo "Copyright 2006-2018 Raphael A. Silva " # Identifying Qt version if [ -e "$QMAKE_ROOT/qmake" ]; then