├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── LICENSE
├── docs
└── images
│ ├── AccessViaMenu.png
│ ├── AccessViaToolbar.png
│ ├── CreateAndEditFile.gif
│ ├── FormatSelection.gif
│ ├── InstallationFolder.png
│ ├── MapFolders.png
│ ├── OrganizeScripts.png
│ ├── ProjectProperties.Debug.png
│ ├── ProjectProperties.VSIX.png
│ ├── Search.gif
│ ├── UnblockFile.png
│ └── VisualStudioExtensionDevelopment.png
├── readme.md
└── src
├── SQLScriptsExplorer.Addin
├── Commands
│ ├── ToolWindow
│ │ ├── MainToolWindow.cs
│ │ ├── MainToolWindowCommand.cs
│ │ ├── MainToolWindowControl.xaml
│ │ ├── MainToolWindowControl.xaml.cs
│ │ ├── MainToolWindowPackage.cs
│ │ └── MainToolWindowPackage.vsct
│ └── Toolbar
│ │ ├── MainToolbarCommand.cs
│ │ ├── MainToolbarCommandPackage.cs
│ │ └── MainToolbarCommandPackage.vsct
├── Controls
│ ├── FileExplorerTreeView.xaml
│ ├── FileExplorerTreeView.xaml.cs
│ └── HighlightTextBlock.cs
├── Infrastructure
│ ├── DocumentManager.cs
│ ├── Extensions
│ │ ├── CollectionExtensions.cs
│ │ └── TreeViewItemExtensions.cs
│ ├── Helpers
│ │ ├── PathHelper.cs
│ │ └── TreeViewHelper.cs
│ ├── RegistryManager.cs
│ └── Utils.cs
├── Key.snk
├── Models
│ ├── Enums
│ │ ├── ScriptFileDoubleClickBehaviour.cs
│ │ └── TreeNodeType.cs
│ ├── FolderMapping.cs
│ ├── ITreeNode.cs
│ └── TreeNode.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Repository
│ ├── Interfaces
│ │ ├── ISettingsRepository.cs
│ │ └── ITreeNodeRepository.cs
│ ├── SettingsRepository.cs
│ └── TreeNodeRepository.cs
├── Resources
│ └── Images
│ │ ├── CollapseAll.png
│ │ ├── Delete.png
│ │ ├── Error.png
│ │ ├── ExpandAll.png
│ │ ├── File.png
│ │ ├── Folder.png
│ │ ├── FormatScript.png
│ │ ├── NewFile.png
│ │ ├── NewFolder.png
│ │ ├── NewSQLFile.png
│ │ ├── OpenFile.png
│ │ ├── OpenFolder.png
│ │ ├── Refresh.png
│ │ ├── Rename.png
│ │ ├── RootFolder.png
│ │ ├── Run.png
│ │ ├── SQLScriptsManager.png
│ │ ├── Settings.png
│ │ ├── Success.png
│ │ ├── TextFile.png
│ │ ├── ToolWindow1Package.ico
│ │ ├── ToolbarCommand.png
│ │ └── ToolbarCommandPackage.ico
├── SQLScriptsExplorer.Addin.csproj
├── SQLScriptsExplorer.AddinPackage.cs
├── Styling
│ └── Converter
│ │ ├── LeftMarginMultiplierConverter.cs
│ │ └── SortableConverter.cs
├── VSPackage.Designer.cs
├── VSPackage.resx
├── frmSettings.Designer.cs
├── frmSettings.cs
├── frmSettings.resx
└── source.extension.vsixmanifest
└── SQLScriptsExplorer.sln
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Environment Information (please complete the following information):**
27 | - OS: [e.g. Window]
28 | - Microsoft SQL Server Studio Version [e.g. 2014, 17, 18]
29 | - .NET Framework [e.g. 4.6]
30 |
31 | **Additional context**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 joaoribe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/images/AccessViaMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/AccessViaMenu.png
--------------------------------------------------------------------------------
/docs/images/AccessViaToolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/AccessViaToolbar.png
--------------------------------------------------------------------------------
/docs/images/CreateAndEditFile.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/CreateAndEditFile.gif
--------------------------------------------------------------------------------
/docs/images/FormatSelection.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/FormatSelection.gif
--------------------------------------------------------------------------------
/docs/images/InstallationFolder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/InstallationFolder.png
--------------------------------------------------------------------------------
/docs/images/MapFolders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/MapFolders.png
--------------------------------------------------------------------------------
/docs/images/OrganizeScripts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/OrganizeScripts.png
--------------------------------------------------------------------------------
/docs/images/ProjectProperties.Debug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/ProjectProperties.Debug.png
--------------------------------------------------------------------------------
/docs/images/ProjectProperties.VSIX.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/ProjectProperties.VSIX.png
--------------------------------------------------------------------------------
/docs/images/Search.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/Search.gif
--------------------------------------------------------------------------------
/docs/images/UnblockFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/UnblockFile.png
--------------------------------------------------------------------------------
/docs/images/VisualStudioExtensionDevelopment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/docs/images/VisualStudioExtensionDevelopment.png
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
SQL Scripts Explorer
2 | Microsoft SQL Server Management Studio 20 extension to open, create, edit, organize, search and share SQL Scripts. Its purpose is to allow quick access to scripts that are frequently used.
3 | Contents
4 |
33 |
34 |
35 | Getting Started
36 |
37 | Requirements
38 |
39 | Microsoft SQL Server Management Studio 20 (supposed to support versions 13-20, only tested in 18 and 20 )
40 | .NET 4.8.1
41 |
42 | Installation
43 |
44 | Close all instances of Microsoft SQL Server Management Studio 20
45 | Download the most recent release
46 | Add release folder SQLScriptsExplorer to
47 |
48 | C:\Program Files (x86)\Microsoft SQL Server Management Studio 20\Common7\IDE\Extensions
49 |
50 |
51 |
52 |
53 | Launch
54 | You can access the addin via the View menu.
55 |
56 | Or you can add a quick launch button by enabling the toolbar.
57 |
58 |
59 |
60 | Features
61 |
62 | Manage multiple SQL Scripts repositories
63 | Map local folders to store your own SQL Scripts or collaborate/share knowledge with your team by mapping shared SQL Scripts folders.
64 |
65 |
66 | Organize SQL Scripts using folders
67 | Use the explorer to organize scripts using folders.
68 |
69 |
70 | Open, create and edit SQL Script files
71 | Use the explorer to manage your scripts without living your workspace.
72 |
73 |
74 | Search SQL Scripts across repositories
75 | Easily search SQL Scripts across different mapped repositories.
76 |
77 |
78 | Format SQL Scripts
79 | Use Format Selection button to format SQL statements.
80 |
81 |
82 |
83 | Contributing
84 | Feel free to report an issue or suggest a feature. If you would like to introduce a functionality or fix an issue, please create a pull request.
85 |
86 | Debugging
87 |
88 | Install Visual Studio 2022 with Visual Studio Extension Development enabled
89 |
90 |
91 |
92 | Open solution in Visual Studio 2022 in Administrator Mode
93 | Right click the project SQLScriptsExplorer.Addin
94 | Select Debug tab
95 |
96 | In the Start external program option, change it to
97 |
98 | C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\ssms.exe
99 |
100 | In the Command line arguments option, remove all the text
101 |
102 |
103 |
104 |
105 | Select VSIX tab
106 |
107 | Ensure Copy VSIX content to the following location is
108 |
109 | C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Extensions\SQLScriptsExplorer
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | Known Issues
119 | Extension does not Load
120 | Sometimes when you download the release zip file, Windows blocks it for security reasons. If you get an error after the plugin installation or the plugin does not appear in Microsoft SQL Server Management Studio 18, ensure the release ZIP file you have downloaded is unblocked.
121 |
122 |
123 | Docking Issue
124 | Note: Issue is related to Windows and .NET Framework, not the addin.
125 | There's an issue with docking any Toolbar in Microsoft SQL Server Management Studio 18. Here are two options to solve it:
126 |
127 |
128 |
129 | Install Microsoft's official cumulative update
130 |
131 |
132 |
133 | Manual fix by changing SSMS.config file. (Source: Microsoft Docs Q&A )
134 |
135 | Navigate to C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE
136 | Find "Ssms.exe.config" file, open up a Notepad in Administrator Mode, and edit this file
137 | You will then need to find an xml tag called <AppContextSwitchOverrides>, and APPEND (not replace) the following exactly:
138 |
139 |
140 | ;Switch.System.Windows.Interop.MouseInput.OptOutOfMoveToChromedWindowFix=true; Switch.System.Windows.Interop.MouseInput.DoNotOptOutOfMoveToChromedWindowFix=true
141 |
142 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/ToolWindow/MainToolWindow.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.Shell;
2 | using System;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace SQLScriptsExplorer.Addin.Commands.ToolWindow
6 | {
7 | ///
8 | /// This class implements the tool window exposed by this package and hosts a user control.
9 | ///
10 | ///
11 | /// In Visual Studio tool windows are composed of a frame (implemented by the shell) and a pane,
12 | /// usually implemented by the package implementer.
13 | ///
14 | /// This class derives from the ToolWindowPane class provided from the MPF in order to use its
15 | /// implementation of the IVsUIElementPane interface.
16 | ///
17 | ///
18 | [Guid("5c8f670c-aaa2-41bb-91dd-52902369733e")]
19 | public class MainToolWindow : ToolWindowPane
20 | {
21 | ///
22 | /// Initializes a new instance of the class.
23 | ///
24 | public MainToolWindow() : base(null)
25 | {
26 | this.Caption = "SQL Scripts Explorer";
27 |
28 | // This is the user control hosted by the tool window; Note that, even if this class implements IDisposable,
29 | // we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on
30 | // the object returned by the Content property.
31 | this.Content = new MainToolWindowControl();
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/ToolWindow/MainToolWindowCommand.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.Shell;
2 | using Microsoft.VisualStudio.Shell.Interop;
3 | using System;
4 | using System.ComponentModel.Design;
5 | using System.Globalization;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 | using Task = System.Threading.Tasks.Task;
9 |
10 | namespace SQLScriptsExplorer.Addin.Commands.ToolWindow
11 | {
12 | ///
13 | /// Command handler
14 | ///
15 | internal sealed class MainToolWindowCommand
16 | {
17 | ///
18 | /// Command ID.
19 | ///
20 | public const int CommandId = 0x0100;
21 |
22 | ///
23 | /// Command menu group (command set GUID).
24 | ///
25 | public static readonly Guid CommandSet = new Guid("00c595cc-9857-4264-8d37-09710a9af9cc");
26 |
27 | ///
28 | /// VS Package that provides this command, not null.
29 | ///
30 | private readonly AsyncPackage package;
31 |
32 | ///
33 | /// Initializes a new instance of the class.
34 | /// Adds our command handlers for menu (commands must exist in the command table file)
35 | ///
36 | /// Owner package, not null.
37 | /// Command service to add command to, not null.
38 | public MainToolWindowCommand(AsyncPackage package, OleMenuCommandService commandService)
39 | {
40 | this.package = package ?? throw new ArgumentNullException(nameof(package));
41 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
42 |
43 | var menuCommandID = new CommandID(CommandSet, CommandId);
44 | var menuItem = new MenuCommand(this.Execute, menuCommandID);
45 | commandService.AddCommand(menuItem);
46 | }
47 |
48 | ///
49 | /// Gets the instance of the command.
50 | ///
51 | public static MainToolWindowCommand Instance
52 | {
53 | get;
54 | private set;
55 | }
56 |
57 | ///
58 | /// Gets the service provider from the owner package.
59 | ///
60 | private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
61 | {
62 | get
63 | {
64 | return this.package;
65 | }
66 | }
67 |
68 | ///
69 | /// Initializes the singleton instance of the command.
70 | ///
71 | /// Owner package, not null.
72 | public static async Task InitializeAsync(AsyncPackage package)
73 | {
74 | // Switch to the main thread - the call to AddCommand in ToolWindow1Command's constructor requires
75 | // the UI thread.
76 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
77 |
78 | OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
79 | Instance = new MainToolWindowCommand(package, commandService);
80 | }
81 |
82 | ///
83 | /// Shows the tool window when the menu item is clicked.
84 | ///
85 | /// The event sender.
86 | /// The event args.
87 | internal void Execute(object sender, EventArgs e)
88 | {
89 | ThreadHelper.ThrowIfNotOnUIThread();
90 |
91 | // Get the instance number 0 of this tool window. This window is single instance so this instance
92 | // is actually the only one.
93 | // The last flag is set to true so that if the tool window does not exists it will be created.
94 | ToolWindowPane window = this.package.FindToolWindow(typeof(MainToolWindow), 0, true);
95 | if ((null == window) || (null == window.Frame))
96 | {
97 | throw new NotSupportedException("Cannot create tool window");
98 | }
99 |
100 | IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
101 | Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/ToolWindow/MainToolWindowControl.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/ToolWindow/MainToolWindowControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using SQLScriptsExplorer.Addin.Infrastructure;
2 | using SQLScriptsExplorer.Addin.Infrastructure.Helpers;
3 | using SQLScriptsExplorer.Addin.Models;
4 | using SQLScriptsExplorer.Addin.Repository;
5 | using SQLScriptsExplorer.Addin.Repository.Interfaces;
6 | using System;
7 | using System.Linq;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Input;
11 |
12 | namespace SQLScriptsExplorer.Addin.Commands.ToolWindow
13 | {
14 | ///
15 | /// Interaction logic for MainToolWindowControl.
16 | ///
17 | public partial class MainToolWindowControl : UserControl
18 | {
19 | ISettingsRepository settingsRepository = null;
20 | ITreeNodeRepository treeNodeRepository = null;
21 |
22 | public bool IsSearchResultsView
23 | {
24 | get { return FileExplorerSearchResults.Visibility == Visibility.Visible; }
25 | }
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | public MainToolWindowControl()
31 | {
32 | this.InitializeComponent();
33 |
34 | settingsRepository = new SettingsRepository();
35 | treeNodeRepository = new TreeNodeRepository();
36 |
37 | RefreshTreeView();
38 | }
39 |
40 | private void btnFormatSelection_Click(object sender, RoutedEventArgs e)
41 | {
42 | try
43 | {
44 | DocumentManager.FormatSelection();
45 | }
46 | catch (Exception ex)
47 | {
48 | MessageBox.Show(ex.Message);
49 | }
50 | }
51 |
52 | private void btnRefresh_Click(object sender, RoutedEventArgs e)
53 | {
54 | RefreshTreeView();
55 |
56 | if (IsSearchResultsView)
57 | {
58 | txtSearch_KeyUp(sender, null);
59 | }
60 | }
61 |
62 | private void btnSettings_Click(object sender, RoutedEventArgs e)
63 | {
64 | var frmSettings = new frmSettings();
65 | var frmSettingsResult = frmSettings.ShowDialog();
66 |
67 | settingsRepository.Refresh();
68 |
69 | if (frmSettingsResult == System.Windows.Forms.DialogResult.OK)
70 | {
71 | RefreshTreeView();
72 | }
73 | }
74 |
75 | private void btnCollapseAll_Click(object sender, RoutedEventArgs e)
76 | {
77 | if (IsSearchResultsView)
78 | {
79 | TreeViewHelper.CollapseTreeView(treeNodeRepository.TreeSearchResult);
80 |
81 | FileExplorerSearchResults.RefreshTreeView();
82 | }
83 | else
84 | {
85 | TreeViewHelper.CollapseTreeView(treeNodeRepository.Tree);
86 |
87 | FileExplorerAll.RefreshTreeView();
88 | }
89 | }
90 |
91 | private void btnExpandAll_Click(object sender, RoutedEventArgs e)
92 | {
93 | if (IsSearchResultsView)
94 | {
95 | TreeViewHelper.ExpandTreeView(treeNodeRepository.TreeSearchResult);
96 |
97 | FileExplorerSearchResults.RefreshTreeView();
98 | }
99 | else
100 | {
101 | TreeViewHelper.ExpandTreeView(treeNodeRepository.Tree);
102 |
103 | FileExplorerAll.RefreshTreeView();
104 | }
105 | }
106 |
107 | public void RefreshTreeViewDataSource()
108 | {
109 | try
110 | {
111 | treeNodeRepository.Load(
112 | settingsRepository.FolderMapping,
113 | settingsRepository.ExpandMappedFoldersOnLoad,
114 | settingsRepository.AllowedFileTypes);
115 | }
116 | catch (Exception ex)
117 | {
118 | MessageBox.Show(ex.Message);
119 | }
120 | }
121 |
122 | public void RefreshTreeView()
123 | {
124 | RefreshTreeViewDataSource();
125 |
126 | FileExplorerAll.DataSourceList = treeNodeRepository.Tree;
127 | FileExplorerAll.DataSourceDictionary = treeNodeRepository.TreeDictionary;
128 |
129 | FileExplorerAll.RefreshTreeView();
130 | }
131 |
132 | private void txtSearch_KeyUp(object sender, KeyEventArgs e)
133 | {
134 | if (!string.IsNullOrWhiteSpace(txtSearch.Text))
135 | {
136 | treeNodeRepository.Search(txtSearch.Text);
137 |
138 | TreeViewHelper.ExpandTreeView(treeNodeRepository.TreeSearchResult);
139 |
140 | FileExplorerSearchResults.DataSourceList = treeNodeRepository.TreeSearchResult;
141 | FileExplorerSearchResults.DataSourceDictionary = treeNodeRepository.TreeSearchResultsDictionary;
142 |
143 | FileExplorerSearchResults.RefreshTreeView();
144 |
145 | FileExplorerSearchResults.Visibility = Visibility.Visible;
146 | FileExplorerAll.Visibility = Visibility.Collapsed;
147 | }
148 | else
149 | {
150 | FileExplorerSearchResults.Visibility = Visibility.Collapsed;
151 | FileExplorerAll.Visibility = Visibility.Visible;
152 | }
153 |
154 | FileExplorerSearchResults.Filter = txtSearch.Text;
155 | }
156 |
157 | private void FileExplorerSearchResults_TreeNodeAdded(object sender, System.EventArgs e)
158 | {
159 | var treeNodeSearchResults = sender as TreeNode;
160 |
161 | var treeNodeParent = FileExplorerAll.DataSourceDictionary[treeNodeSearchResults.Parent.Id];
162 | var treeNode = treeNodeSearchResults.Clone(treeNodeParent);
163 |
164 | treeNodeParent.Children.Add(treeNode);
165 | treeNodeParent.Children = treeNodeParent.Children.OrderBy(p => p.Type).ThenBy(p => p.FileName).ToList();
166 |
167 | FileExplorerAll.DataSourceDictionary.Add(treeNode.Id, treeNode);
168 |
169 | FileExplorerAll.RefreshTreeView();
170 | }
171 |
172 | private void FileExplorerSearchResults_TreeNodeDeleted(object sender, System.EventArgs e)
173 | {
174 | var treeNodeSearchResults = sender as TreeNode;
175 | var treeNode = FileExplorerAll.DataSourceDictionary[treeNodeSearchResults.Id];
176 |
177 | treeNode.Parent.Children.Remove(treeNode);
178 |
179 | FileExplorerAll.DataSourceDictionary.Remove(treeNode.Id);
180 |
181 | FileExplorerAll.RefreshTreeView();
182 | }
183 |
184 | private void FileExplorerSearchResults_TreeNodeRenamed(object sender, System.EventArgs e)
185 | {
186 | var treeNodeSearchResults = sender as TreeNode;
187 | var treeNode = FileExplorerAll.DataSourceDictionary[treeNodeSearchResults.Id];
188 |
189 | treeNode.FileName = treeNodeSearchResults.FileName;
190 | treeNode.FileFullPath = treeNodeSearchResults.FileFullPath;
191 |
192 | treeNode.Parent.Children = treeNode.Parent.Children.OrderBy(p => p.Type).ThenBy(p => p.FileName).ToList();
193 |
194 | FileExplorerAll.RefreshTreeView();
195 | }
196 |
197 | #region UI
198 |
199 | private void ToolBar_Loaded(object sender, RoutedEventArgs e)
200 | {
201 | ToolBar toolBar = sender as ToolBar;
202 |
203 | var overflowGrid = toolBar.Template.FindName("OverflowGrid", toolBar) as FrameworkElement;
204 | if (overflowGrid != null)
205 | {
206 | overflowGrid.Visibility = Visibility.Collapsed;
207 | }
208 |
209 | var mainPanelBorder = toolBar.Template.FindName("MainPanelBorder", toolBar) as FrameworkElement;
210 | if (mainPanelBorder != null)
211 | {
212 | mainPanelBorder.Margin = new Thickness(0);
213 | }
214 | }
215 |
216 | #endregion
217 | }
218 | }
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/ToolWindow/MainToolWindowPackage.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio;
2 | using Microsoft.VisualStudio.OLE.Interop;
3 | using Microsoft.VisualStudio.Shell;
4 | using Microsoft.VisualStudio.Shell.Interop;
5 | using Microsoft.Win32;
6 | using System;
7 | using System.ComponentModel.Design;
8 | using System.Diagnostics;
9 | using System.Diagnostics.CodeAnalysis;
10 | using System.Globalization;
11 | using System.Runtime.InteropServices;
12 | using System.Threading;
13 | using System.Threading.Tasks;
14 | using Task = System.Threading.Tasks.Task;
15 |
16 | namespace SQLScriptsExplorer.Addin.Commands.ToolWindow
17 | {
18 | ///
19 | /// This is the class that implements the package exposed by this assembly.
20 | ///
21 | ///
22 | ///
23 | /// The minimum requirement for a class to be considered a valid package for Visual Studio
24 | /// is to implement the IVsPackage interface and register itself with the shell.
25 | /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
26 | /// to do it: it derives from the Package class that provides the implementation of the
27 | /// IVsPackage interface and uses the registration attributes defined in the framework to
28 | /// register itself and its components with the shell. These attributes tell the pkgdef creation
29 | /// utility what data to put into .pkgdef file.
30 | ///
31 | ///
32 | /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
33 | ///
34 | ///
35 | [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
36 | [ProvideMenuResource("Menus.ctmenu", 1)]
37 | [ProvideToolWindow(typeof(MainToolWindow))]
38 | [Guid(MainToolWindowPackage.PackageGuidString)]
39 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
40 | public sealed class MainToolWindowPackage : AsyncPackage
41 | {
42 | ///
43 | /// ToolWindow1Package GUID string.
44 | ///
45 | public const string PackageGuidString = "4bd9e3b7-73c4-4203-82b2-317dddfad6f2";
46 |
47 | ///
48 | /// Initializes a new instance of the class.
49 | ///
50 | public MainToolWindowPackage()
51 | {
52 | // Inside this method you can place any initialization code that does not require
53 | // any Visual Studio service because at this point the package object is created but
54 | // not sited yet inside Visual Studio environment. The place to do all the other
55 | // initialization is the Initialize method.
56 | }
57 |
58 | #region Package Members
59 |
60 | ///
61 | /// Initialization of the package; this method is called right after the package is sited, so this is the place
62 | /// where you can put all the initialization code that rely on services provided by VisualStudio.
63 | ///
64 | /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.
65 | /// A provider for progress updates.
66 | /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.
67 | protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
68 | {
69 | // When initialized asynchronously, the current thread may be a background thread at this point.
70 | // Do any initialization that requires the UI thread after switching to the UI thread.
71 | await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
72 | await MainToolWindowCommand.InitializeAsync(this);
73 | }
74 |
75 | #endregion
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/ToolWindow/MainToolWindowPackage.vsct:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
33 |
34 |
35 |
37 |
38 |
45 |
46 |
47 |
48 |
49 | SQL Scripts Explorer
50 |
51 |
52 |
53 |
54 |
55 |
56 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/Toolbar/MainToolbarCommand.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.Shell;
2 | using Microsoft.VisualStudio.Shell.Interop;
3 | using System;
4 | using System.ComponentModel.Design;
5 | using SQLScriptsExplorer.Addin.Commands.ToolWindow;
6 | using Task = System.Threading.Tasks.Task;
7 |
8 | namespace SQLScriptsExplorer.Addin.Commands.Toolbar
9 | {
10 | ///
11 | /// Command handler
12 | ///
13 | internal sealed class MainToolbarCommand
14 | {
15 | ///
16 | /// Command ID.
17 | ///
18 | public const int CommandId = 0x0100;
19 |
20 | ///
21 | /// Command menu group (command set GUID).
22 | ///
23 | public static readonly Guid CommandSet = new Guid("fa05b6ea-8d21-4380-83d2-208a6ab3deb9");
24 |
25 | ///
26 | /// VS Package that provides this command, not null.
27 | ///
28 | private readonly AsyncPackage package;
29 |
30 | ///
31 | /// Initializes a new instance of the class.
32 | /// Adds our command handlers for menu (commands must exist in the command table file)
33 | ///
34 | /// Owner package, not null.
35 | /// Command service to add command to, not null.
36 | private MainToolbarCommand(AsyncPackage package, OleMenuCommandService commandService)
37 | {
38 | this.package = package ?? throw new ArgumentNullException(nameof(package));
39 | commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
40 |
41 | var menuCommandID = new CommandID(CommandSet, CommandId);
42 | var menuItem = new MenuCommand(this.Execute, menuCommandID);
43 | commandService.AddCommand(menuItem);
44 | }
45 |
46 | ///
47 | /// Gets the instance of the command.
48 | ///
49 | public static MainToolbarCommand Instance
50 | {
51 | get;
52 | private set;
53 | }
54 |
55 | ///
56 | /// Gets the service provider from the owner package.
57 | ///
58 | private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
59 | {
60 | get
61 | {
62 | return this.package;
63 | }
64 | }
65 |
66 | ///
67 | /// Initializes the singleton instance of the command.
68 | ///
69 | /// Owner package, not null.
70 | public static async Task InitializeAsync(AsyncPackage package)
71 | {
72 | // Switch to the main thread - the call to AddCommand in ToolbarCommand's constructor requires
73 | // the UI thread.
74 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
75 |
76 | OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
77 | Instance = new MainToolbarCommand(package, commandService);
78 | }
79 |
80 | ///
81 | /// This function is the callback used to execute the command when the menu item is clicked.
82 | /// See the constructor to see how the menu item is associated with this function using
83 | /// OleMenuCommandService service and MenuCommand class.
84 | ///
85 | /// Event sender.
86 | /// Event args.
87 | private void Execute(object sender, EventArgs e)
88 | {
89 | ThreadHelper.ThrowIfNotOnUIThread();
90 |
91 | IVsUIShell vsUIShell = (IVsUIShell)Package.GetGlobalService(typeof(SVsUIShell));
92 | Guid guid = typeof(MainToolWindow).GUID;
93 | IVsWindowFrame windowFrame;
94 | int result = vsUIShell.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fFindFirst, ref guid, out windowFrame); // Find MainToolWindow
95 |
96 | if (result != Microsoft.VisualStudio.VSConstants.S_OK)
97 | result = vsUIShell.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fForceCreate, ref guid, out windowFrame); // Crate MainToolWindow if not found
98 |
99 | if (result == Microsoft.VisualStudio.VSConstants.S_OK) // Show MainToolWindow
100 | Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/Toolbar/MainToolbarCommandPackage.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio;
2 | using Microsoft.VisualStudio.OLE.Interop;
3 | using Microsoft.VisualStudio.Shell;
4 | using Microsoft.VisualStudio.Shell.Interop;
5 | using Microsoft.Win32;
6 | using System;
7 | using System.ComponentModel.Design;
8 | using System.Diagnostics;
9 | using System.Diagnostics.CodeAnalysis;
10 | using System.Globalization;
11 | using System.Runtime.InteropServices;
12 | using System.Threading;
13 | using System.Threading.Tasks;
14 | using Task = System.Threading.Tasks.Task;
15 |
16 | namespace SQLScriptsExplorer.Addin.Commands.Toolbar
17 | {
18 | ///
19 | /// This is the class that implements the package exposed by this assembly.
20 | ///
21 | ///
22 | ///
23 | /// The minimum requirement for a class to be considered a valid package for Visual Studio
24 | /// is to implement the IVsPackage interface and register itself with the shell.
25 | /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
26 | /// to do it: it derives from the Package class that provides the implementation of the
27 | /// IVsPackage interface and uses the registration attributes defined in the framework to
28 | /// register itself and its components with the shell. These attributes tell the pkgdef creation
29 | /// utility what data to put into .pkgdef file.
30 | ///
31 | ///
32 | /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
33 | ///
34 | ///
35 | [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
36 | [ProvideMenuResource("Menus1.ctmenu", 1)]
37 | [Guid(MainToolbarCommandPackage.PackageGuidString)]
38 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")]
39 | public sealed class MainToolbarCommandPackage : AsyncPackage
40 | {
41 | ///
42 | /// ToolbarCommandPackage GUID string.
43 | ///
44 | public const string PackageGuidString = "697f3f0b-6e13-4080-82e6-2733db1bbf35";
45 |
46 | ///
47 | /// Initializes a new instance of the class.
48 | ///
49 | public MainToolbarCommandPackage()
50 | {
51 | // Inside this method you can place any initialization code that does not require
52 | // any Visual Studio service because at this point the package object is created but
53 | // not sited yet inside Visual Studio environment. The place to do all the other
54 | // initialization is the Initialize method.
55 | }
56 |
57 | #region Package Members
58 |
59 | ///
60 | /// Initialization of the package; this method is called right after the package is sited, so this is the place
61 | /// where you can put all the initialization code that rely on services provided by VisualStudio.
62 | ///
63 | /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.
64 | /// A provider for progress updates.
65 | /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.
66 | protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
67 | {
68 | // When initialized asynchronously, the current thread may be a background thread at this point.
69 | // Do any initialization that requires the UI thread after switching to the UI thread.
70 | await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
71 | await MainToolbarCommand.InitializeAsync(this);
72 | }
73 |
74 | #endregion
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Commands/Toolbar/MainToolbarCommandPackage.vsct:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
29 | DefaultDocked
30 |
31 | SQL Scripts Explorer
32 | SQL Scripts Explorer
33 |
34 |
35 |
36 |
43 |
44 |
48 |
49 |
52 |
54 |
55 |
56 |
57 |
58 |
59 |
61 |
62 |
69 |
70 |
71 |
72 | IconAndText
73 |
74 | SQL Scripts Explorer
75 |
76 |
77 |
78 |
79 |
80 |
81 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Controls/FileExplorerTreeView.xaml:
--------------------------------------------------------------------------------
1 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
117 |
118 |
119 |
120 |
141 |
142 |
157 |
158 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Controls/FileExplorerTreeView.xaml.cs:
--------------------------------------------------------------------------------
1 | using SQLScriptsExplorer.Addin.Infrastructure;
2 | using SQLScriptsExplorer.Addin.Infrastructure.Extensions;
3 | using SQLScriptsExplorer.Addin.Infrastructure.Helpers;
4 | using SQLScriptsExplorer.Addin.Models;
5 | using SQLScriptsExplorer.Addin.Models.Enums;
6 | using SQLScriptsExplorer.Addin.Repository;
7 | using SQLScriptsExplorer.Addin.Repository.Interfaces;
8 | using System;
9 | using System.Collections.Generic;
10 | using System.IO;
11 | using System.Linq;
12 | using System.Windows;
13 | using System.Windows.Controls;
14 | using System.Windows.Input;
15 | using System.Windows.Media;
16 |
17 | namespace SQLScriptsExplorer.Addin.Controls
18 | {
19 | ///
20 | /// Interaction logic for FileExplorerTreeView.xaml
21 | ///
22 | public partial class FileExplorerTreeView : UserControl
23 | {
24 | public List DataSourceList = new List();
25 | public Dictionary DataSourceDictionary = new Dictionary();
26 |
27 | public event EventHandler TreeNodeAdded;
28 | public event EventHandler TreeNodeDeleted;
29 | public event EventHandler TreeNodeRenamed;
30 |
31 | private bool isEditMode = false;
32 | private string renamingNodeId;
33 | private string renamingNodeFileName;
34 | private TextBlock lblRename;
35 | private TextBox txtRename;
36 |
37 | private TreeNode currentTreeNode;
38 | private TreeViewItem currentTreeViewItem;
39 |
40 | private TreeNode potentialCurrentTreeNode;
41 | private TreeViewItem potentialCurrentTreeViewItem;
42 |
43 | public string Filter { get; set; }
44 |
45 | public FileExplorerTreeView()
46 | {
47 | InitializeComponent();
48 | }
49 |
50 | private void TreeViewMain_MouseDoubleClick(object sender, MouseButtonEventArgs e)
51 | {
52 | if (e.ChangedButton == MouseButton.Left)
53 | {
54 | var doubleClickedTreeViewItem = VisualUpwardSearchTreeViewItem(e.OriginalSource as DependencyObject);
55 | var doubleClickedTreeNode = doubleClickedTreeViewItem.DataContext as TreeNode;
56 |
57 | if (doubleClickedTreeNode.Type == TreeNodeType.File && currentTreeNode.Id.Equals(doubleClickedTreeNode.Id))
58 | {
59 | ISettingsRepository settingsRepository = new SettingsRepository();
60 |
61 | if (settingsRepository.ScriptFileDoubleClickBehaviour == ScriptFileDoubleClickBehaviour.OpenNewInstance)
62 | mnuOpenNewInstance_Click(sender, null);
63 | else
64 | mnuEditFile_Click(sender, null);
65 | }
66 | }
67 |
68 | e.Handled = true;
69 | }
70 |
71 | public void RefreshTreeView()
72 | {
73 | TreeViewMain.ItemsSource = null;
74 | TreeViewMain.ItemsSource = DataSourceList;
75 | }
76 |
77 | private void TreeViewMain_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e)
78 | {
79 | var treeView = sender as System.Windows.Controls.TreeView;
80 | var selectedTreeNode = treeView.SelectedItem as TreeNode;
81 |
82 | if (selectedTreeNode != null)
83 | {
84 | if (potentialCurrentTreeNode != null && selectedTreeNode.Id.Equals(potentialCurrentTreeNode.Id))
85 | {
86 | currentTreeNode = potentialCurrentTreeNode;
87 | currentTreeViewItem = potentialCurrentTreeViewItem;
88 |
89 | potentialCurrentTreeNode = null;
90 | potentialCurrentTreeViewItem = null;
91 | }
92 |
93 | switch (selectedTreeNode.Type)
94 | {
95 | case TreeNodeType.File:
96 | treeView.ContextMenu = treeView.Resources["FileContext"] as System.Windows.Controls.ContextMenu;
97 | break;
98 | case TreeNodeType.Folder:
99 | treeView.ContextMenu = treeView.Resources["FolderContext"] as System.Windows.Controls.ContextMenu;
100 | break;
101 | case TreeNodeType.RootFolder:
102 | treeView.ContextMenu = treeView.Resources["RootFolderContext"] as System.Windows.Controls.ContextMenu;
103 | break;
104 | }
105 | }
106 | }
107 |
108 | private void TreeViewMain_ContextMenuOpening(object sender, ContextMenuEventArgs e)
109 | {
110 | if (currentTreeNode.Type == TreeNodeType.File)
111 | {
112 | ISettingsRepository settingsRepository = new SettingsRepository();
113 | var fileContextMenu = TreeViewMain.Resources["FileContext"] as System.Windows.Controls.ContextMenu;
114 |
115 | if (fileContextMenu != null)
116 | {
117 | var executeMenuItem = fileContextMenu.Items[2] as MenuItem;
118 |
119 | if (executeMenuItem != null)
120 | {
121 | if (settingsRepository.ShowExecuteFileButton)
122 | executeMenuItem.Visibility = Visibility.Visible;
123 | else
124 | executeMenuItem.Visibility = Visibility.Collapsed;
125 | }
126 | }
127 | }
128 | }
129 |
130 | private void TreeViewMain_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
131 | {
132 | potentialCurrentTreeViewItem = VisualUpwardSearchTreeViewItem(e.OriginalSource as DependencyObject);
133 |
134 | potentialCurrentTreeNode = potentialCurrentTreeViewItem != null ?
135 | potentialCurrentTreeViewItem.DataContext as TreeNode : null;
136 |
137 | // In case changing focus to a different node while renaming file
138 | if (currentTreeNode != null && isEditMode && currentTreeNode.Id != renamingNodeId)
139 | {
140 | txtRename_LostFocus(null, null);
141 | }
142 | }
143 |
144 | private void TreeViewMain_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
145 | {
146 | currentTreeViewItem = VisualUpwardSearchTreeViewItem(e.OriginalSource as DependencyObject);
147 | currentTreeNode = currentTreeViewItem != null ?
148 | currentTreeViewItem.DataContext as TreeNode : null;
149 |
150 | if (currentTreeViewItem != null)
151 | {
152 | currentTreeViewItem.Focus();
153 | e.Handled = true;
154 | }
155 | }
156 |
157 | private static TreeViewItem VisualUpwardSearchTreeViewItem(DependencyObject source)
158 | {
159 | while (source != null && !(source is TreeViewItem))
160 | source = VisualTreeHelper.GetParent(source);
161 |
162 | return source as TreeViewItem;
163 | }
164 |
165 | private void mnuOpenNewInstance_Click(object sender, RoutedEventArgs e)
166 | {
167 | var treeNode = TreeViewMain.SelectedItem as TreeNode;
168 |
169 | if (treeNode != null && treeNode.Type == TreeNodeType.File && !isEditMode)
170 | {
171 | try
172 | {
173 | DocumentManager.OpenTemplate(treeNode.FileName, treeNode.FileFullPath);
174 | }
175 | catch (Exception ex)
176 | {
177 | MessageBox.Show(ex.Message);
178 | }
179 | }
180 | }
181 |
182 | private void mnuOpenFolder_Click(object sender, RoutedEventArgs e)
183 | {
184 | var treeNode = TreeViewMain.SelectedItem as TreeNode;
185 |
186 | if (treeNode != null)
187 | {
188 | if (treeNode.Type == TreeNodeType.Folder || treeNode.Type == TreeNodeType.RootFolder)
189 | {
190 | System.Diagnostics.Process.Start("explorer.exe", treeNode.FileFullPath);
191 | }
192 | else if (treeNode.Type == TreeNodeType.File)
193 | {
194 | var directoryPath = Path.GetDirectoryName(treeNode.FileFullPath);
195 |
196 | System.Diagnostics.Process.Start("explorer.exe", directoryPath);
197 | }
198 | }
199 | }
200 |
201 | private void mnuEditFile_Click(object sender, RoutedEventArgs e)
202 | {
203 | var treeNode = TreeViewMain.SelectedItem as TreeNode;
204 |
205 | if (treeNode != null && treeNode.Type == TreeNodeType.File)
206 | {
207 | try
208 | {
209 | DocumentManager.EditTemplate(treeNode.FileName, treeNode.FileFullPath);
210 | }
211 | catch (Exception ex)
212 | {
213 | MessageBox.Show(ex.Message);
214 | }
215 | }
216 | }
217 |
218 | private void mnuExecuteFile_Click(object sender, RoutedEventArgs e)
219 | {
220 | var treeNode = TreeViewMain.SelectedItem as TreeNode;
221 |
222 | if (treeNode != null && treeNode.Type == TreeNodeType.File && !isEditMode)
223 | {
224 | try
225 | {
226 | ISettingsRepository settingsRepository = new SettingsRepository();
227 |
228 | DocumentManager.OpenTemplate(treeNode.FileName, treeNode.FileFullPath);
229 | var messageBoxResult = MessageBoxResult.Yes;
230 |
231 | if (settingsRepository.ConfirmScriptExecution)
232 | {
233 | messageBoxResult = MessageBox.Show($"Are sure you want to execute the script '{treeNode.FileName}'?", "Confirmation",
234 | MessageBoxButton.YesNo,
235 | MessageBoxImage.None,
236 | MessageBoxResult.No);
237 | }
238 |
239 | if (messageBoxResult == MessageBoxResult.Yes)
240 | {
241 | DocumentManager.ExecuteTemplate(treeNode.FileName, treeNode.FileFullPath, settingsRepository.ConfirmScriptExecution);
242 | }
243 | }
244 | catch (Exception ex)
245 | {
246 | MessageBox.Show(ex.Message);
247 | }
248 | }
249 | }
250 |
251 | private void mnuRename_Click(object sender, RoutedEventArgs e)
252 | {
253 | // Get the TextBox control as defined in TreeView.ItemTemplate
254 | lblRename = TreeViewItemExtensions.FindVisualChild(currentTreeViewItem as DependencyObject);
255 | txtRename = TreeViewItemExtensions.FindVisualChild(currentTreeViewItem as DependencyObject);
256 |
257 | // Set the Visible property of the TextBox Visibility
258 | lblRename.Visibility = Visibility.Collapsed;
259 | txtRename.Visibility = Visibility.Visible;
260 |
261 | txtRename.Focus();
262 |
263 | isEditMode = true;
264 |
265 | renamingNodeId = currentTreeNode.Id;
266 | renamingNodeFileName = currentTreeNode.FileName;
267 | }
268 |
269 | private void mnuDelete_Click(object sender, RoutedEventArgs e)
270 | {
271 | var treeViewMainTreeNode = TreeViewMain.SelectedItem as TreeNode;
272 | var treeNode = DataSourceDictionary[treeViewMainTreeNode.Id];
273 |
274 | if (treeNode != null)
275 | {
276 | var confirmationMessage = $"Are you sure you want to delete this {treeNode.Type.ToString().ToLowerInvariant()}?";
277 | var messageBoxImage = MessageBoxImage.Question;
278 |
279 | if (PathHelper.IsNetworkPath(treeNode.FileFullPath))
280 | {
281 | confirmationMessage = $"WARNING: The {treeNode.Type.ToString().ToLowerInvariant()} you are attemping to delete belongs to a shared folder in the network. " +
282 | $"This file might be deleted permanently and other users won't be able to access it.\n\n" +
283 | $"{confirmationMessage}";
284 |
285 | messageBoxImage = MessageBoxImage.Warning;
286 | }
287 |
288 | if (MessageBox.Show(confirmationMessage, "Confirmation",
289 | MessageBoxButton.YesNo, messageBoxImage, MessageBoxResult.No) == MessageBoxResult.Yes)
290 | {
291 | try
292 | {
293 | // Remove folder or file
294 | if (treeNode.Type == TreeNodeType.Folder && Directory.Exists(treeNode.FileFullPath))
295 | {
296 | Directory.Delete(treeNode.FileFullPath, true);
297 | }
298 |
299 | if (treeNode.Type == TreeNodeType.File && File.Exists(treeNode.FileFullPath))
300 | {
301 | File.Delete(treeNode.FileFullPath);
302 | }
303 |
304 | // Remove from DataSource
305 | var parentTreeNode = treeNode.Parent;
306 |
307 | if (parentTreeNode != null)
308 | {
309 | parentTreeNode.Children.Remove(treeNode);
310 | }
311 |
312 | DataSourceDictionary.Remove(treeNode.Id);
313 |
314 | RefreshTreeView();
315 |
316 | if (TreeNodeDeleted != null)
317 | {
318 | TreeNodeDeleted(treeNode, EventArgs.Empty);
319 | }
320 | }
321 | catch (Exception ex)
322 | {
323 | MessageBox.Show($"Couldn't delete {treeNode.Type.ToString().ToLowerInvariant()}. Error message: {ex.Message}");
324 | }
325 | }
326 | }
327 | }
328 |
329 | private void mnuNewFile_Click(object sender, RoutedEventArgs e)
330 | {
331 | var newFileName = PathHelper.GetNextNewFileNameAvailable(currentTreeNode.FileFullPath);
332 | var newFilePath = Path.Combine(currentTreeNode.FileFullPath, newFileName);
333 |
334 | if (!File.Exists(newFilePath))
335 | {
336 | File.Create(newFilePath);
337 |
338 | var newTreeNode = new TreeNode(newFileName, newFilePath, TreeNodeType.File);
339 | newTreeNode.Parent = currentTreeNode;
340 | newTreeNode.IsSelected = true;
341 |
342 | currentTreeNode.Children.Add(newTreeNode);
343 | currentTreeNode.Children = currentTreeNode.Children.OrderBy(p => p.Type).ThenBy(p => p.FileName).ToList();
344 | currentTreeNode.IsExpanded = true;
345 |
346 | DataSourceDictionary.Add(newTreeNode.Id, newTreeNode);
347 |
348 | RefreshTreeView();
349 |
350 | if (TreeNodeAdded != null)
351 | {
352 | TreeNodeAdded(newTreeNode, EventArgs.Empty);
353 | }
354 | }
355 | }
356 |
357 | private void mnuNewFolder_Click(object sender, RoutedEventArgs e)
358 | {
359 | var newFolderName = PathHelper.GetNextNewFolderNameAvailable(currentTreeNode.FileFullPath);
360 | var newFolderPath = Path.Combine(currentTreeNode.FileFullPath, newFolderName);
361 |
362 | if (!Directory.Exists(newFolderPath))
363 | {
364 | Directory.CreateDirectory(newFolderPath);
365 |
366 | var newTreeNode = new TreeNode(newFolderName, newFolderPath, TreeNodeType.Folder);
367 | newTreeNode.Parent = currentTreeNode;
368 | newTreeNode.IsSelected = true;
369 |
370 | currentTreeNode.Children.Add(newTreeNode);
371 | currentTreeNode.Children = currentTreeNode.Children.OrderBy(p => p.Type).ThenBy(p => p.FileName).ToList();
372 | currentTreeNode.IsExpanded = true;
373 |
374 | DataSourceDictionary.Add(newTreeNode.Id, newTreeNode);
375 |
376 | RefreshTreeView();
377 |
378 | if (TreeNodeAdded != null)
379 | {
380 | TreeNodeAdded(newTreeNode, EventArgs.Empty);
381 | }
382 | }
383 | }
384 |
385 | private void TreeViewMain_KeyDown(object sender, KeyEventArgs e)
386 | {
387 | if (e.Key == Key.F2)
388 | mnuRename_Click(e, null);
389 | else if (e.Key == Key.Delete)
390 | mnuDelete_Click(e, null);
391 | }
392 |
393 | private void txtRename_KeyDown(object sender, KeyEventArgs e)
394 | {
395 | if (e.Key == Key.Enter)
396 | txtRename_LostFocus(sender, null);
397 | else if (e.Key == Key.Escape)
398 | {
399 | txtRename.Text = lblRename.Text = renamingNodeFileName;
400 | txtRename_LostFocus(sender, null);
401 | }
402 | }
403 |
404 | private void txtRename_LostFocus(object sender, RoutedEventArgs e)
405 | {
406 | try
407 | {
408 | bool hasRenamed = false;
409 |
410 | if (lblRename != null && txtRename != null)
411 | {
412 | txtRename.Text = txtRename.Text.Trim();
413 |
414 | if (isEditMode)
415 | {
416 | if (string.IsNullOrWhiteSpace(txtRename.Text))
417 | {
418 | // TODO: Workaround for when clicking a button outside TreeView
419 | if (currentTreeViewItem != null && !currentTreeViewItem.DataContext.ToString().Equals("{DisconnectedItem}"))
420 | {
421 | MessageBox.Show("Please enter a file name.");
422 | txtRename.Text = lblRename.Text = renamingNodeFileName;
423 | return;
424 | }
425 | }
426 | else if (currentTreeViewItem != null && renamingNodeFileName != txtRename.Text)
427 | {
428 | var renamingTreeNode = DataSourceDictionary[renamingNodeId];
429 |
430 | var basePath = Path.GetDirectoryName(renamingTreeNode.FileFullPath);
431 | var previousPath = Path.Combine(basePath, renamingNodeFileName);
432 | var newPath = Path.Combine(basePath, txtRename.Text);
433 |
434 | if (renamingTreeNode.Type == TreeNodeType.File && File.Exists(previousPath))
435 | {
436 | File.Move(previousPath, newPath);
437 |
438 | hasRenamed = true;
439 | }
440 | else if (renamingTreeNode.Type == TreeNodeType.Folder && Directory.Exists(previousPath))
441 | {
442 | // Necessary to move to another temporary path before moving to the new path, as directory renaming is not case-sensitive
443 | // i.e. Renaming a folder from "Service" to "ServicE" would throw an exception using Directory.Move
444 | var directory = new DirectoryInfo(previousPath);
445 | directory.MoveTo(PathHelper.GetDirectoryTemporaryPath(previousPath));
446 | directory.MoveTo(newPath);
447 |
448 | hasRenamed = true;
449 | }
450 |
451 | if (hasRenamed)
452 | {
453 | renamingTreeNode.FileName = lblRename.Text = txtRename.Text;
454 | renamingTreeNode.FileFullPath = newPath;
455 |
456 | renamingTreeNode.Parent.Children = renamingTreeNode.Parent.Children.OrderBy(p => p.Type).ThenBy(p => p.FileName).ToList();
457 |
458 | if (renamingNodeId == currentTreeNode.Id)
459 | {
460 | currentTreeViewItem.IsSelected = true;
461 | }
462 |
463 | if (TreeNodeRenamed != null)
464 | {
465 | TreeNodeRenamed(renamingTreeNode, EventArgs.Empty);
466 | }
467 | }
468 | }
469 | }
470 |
471 | isEditMode = false;
472 |
473 | if (hasRenamed)
474 | {
475 | RefreshTreeView();
476 | }
477 | else
478 | {
479 | txtRename.Text = lblRename.Text = renamingNodeFileName;
480 | }
481 |
482 | lblRename.Visibility = Visibility.Visible;
483 | txtRename.Visibility = Visibility.Collapsed;
484 | }
485 | }
486 | catch (Exception ex)
487 | {
488 | MessageBox.Show(ex.Message);
489 | }
490 | }
491 | }
492 | }
493 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Controls/HighlightTextBlock.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using System.Windows.Documents;
5 | using System.Windows.Media;
6 |
7 | namespace SQLScriptsExplorer.Addin.Controls
8 | {
9 | public class HighlightTextBlock : TextBlock
10 | {
11 | #region Properties
12 |
13 | public new string Text
14 | {
15 | get { return (string)GetValue(TextProperty); }
16 | set { SetValue(TextProperty, value); }
17 | }
18 |
19 | public new static readonly DependencyProperty TextProperty =
20 | DependencyProperty.Register("Text", typeof(string),
21 | typeof(HighlightTextBlock), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender,
22 | new PropertyChangedCallback(UpdateHighlighting)));
23 |
24 | public string HighlightPhrase
25 | {
26 | get { return (string)GetValue(HighlightPhraseProperty); }
27 | set { SetValue(HighlightPhraseProperty, value); }
28 | }
29 |
30 | public static readonly DependencyProperty HighlightPhraseProperty =
31 | DependencyProperty.Register("HighlightPhrase", typeof(string),
32 | typeof(HighlightTextBlock), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender,
33 | new PropertyChangedCallback(UpdateHighlighting)));
34 |
35 | public Brush HighlightBrush
36 | {
37 | get { return (Brush)GetValue(HighlightBrushProperty); }
38 | set { SetValue(HighlightBrushProperty, value); }
39 | }
40 |
41 | public static readonly DependencyProperty HighlightBrushProperty =
42 | DependencyProperty.Register("HighlightBrush", typeof(Brush),
43 | typeof(HighlightTextBlock), new FrameworkPropertyMetadata(Brushes.Yellow, FrameworkPropertyMetadataOptions.AffectsRender,
44 | new PropertyChangedCallback(UpdateHighlighting)));
45 |
46 | public bool IsCaseSensitive
47 | {
48 | get { return (bool)GetValue(IsCaseSensitiveProperty); }
49 | set { SetValue(IsCaseSensitiveProperty, value); }
50 | }
51 |
52 | public static readonly DependencyProperty IsCaseSensitiveProperty =
53 | DependencyProperty.Register("IsCaseSensitive", typeof(bool),
54 | typeof(HighlightTextBlock), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender,
55 | new PropertyChangedCallback(UpdateHighlighting)));
56 |
57 | private static void UpdateHighlighting(DependencyObject d, DependencyPropertyChangedEventArgs e)
58 | {
59 | ApplyHighlight(d as HighlightTextBlock);
60 | }
61 |
62 | #endregion
63 |
64 | #region Members
65 |
66 | private static void ApplyHighlight(HighlightTextBlock tb)
67 | {
68 | string highlightPhrase = tb.HighlightPhrase;
69 | string text = tb.Text;
70 |
71 | if (String.IsNullOrEmpty(highlightPhrase))
72 | {
73 | tb.Inlines.Clear();
74 |
75 | tb.Inlines.Add(text);
76 | }
77 |
78 | else
79 | {
80 | int index = text.IndexOf(highlightPhrase, (tb.IsCaseSensitive) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
81 |
82 | tb.Inlines.Clear();
83 |
84 | if (index < 0) //if highlightPhrase doesn't exist in text
85 | tb.Inlines.Add(text); //add text, with no background highlighting, to tb.Inlines
86 |
87 | else
88 | {
89 | if (index > 0) //if highlightPhrase occurs after start of text
90 | tb.Inlines.Add(text.Substring(0, index)); //add the text that exists before highlightPhrase, with no background highlighting, to tb.Inlines
91 |
92 | //add the highlightPhrase, using substring to get the casing as it appears in text, with a background, to tb.Inlines
93 | tb.Inlines.Add(new Run(text.Substring(index, highlightPhrase.Length))
94 | {
95 | Background = tb.HighlightBrush,
96 | Foreground = Brushes.Black
97 | });
98 |
99 | index += highlightPhrase.Length; //move index to the end of the matched highlightPhrase
100 |
101 | if (index < text.Length) //if the end of the matched highlightPhrase occurs before the end of text
102 | tb.Inlines.Add(text.Substring(index)); //add the text that exists after highlightPhrase, with no background highlighting, to tb.Inlines
103 | }
104 | }
105 | }
106 |
107 | #endregion
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/DocumentManager.cs:
--------------------------------------------------------------------------------
1 | using EnvDTE;
2 | using Microsoft.SqlServer.TransactSql.ScriptDom;
3 | using Microsoft.VisualStudio.Shell;
4 | using SQLScriptsExplorer.Addin.Repository;
5 | using SQLScriptsExplorer.Addin.Repository.Interfaces;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.IO;
9 | using System.Linq;
10 |
11 | namespace SQLScriptsExplorer.Addin.Infrastructure
12 | {
13 | public static class DocumentManager
14 | {
15 | public static void OpenTemplate(string fileName, string fileFullPath)
16 | {
17 | try
18 | {
19 | ThreadHelper.ThrowIfNotOnUIThread();
20 |
21 | if (File.Exists(fileFullPath))
22 | {
23 | string fileContent = File.ReadAllText(fileFullPath);
24 |
25 | DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
26 | var fileDocument = dte.ItemOperations.NewFile(@"General\Text File", fileName).Document;
27 |
28 | TextSelection textSelection = fileDocument.Selection as TextSelection;
29 | textSelection.SelectAll();
30 | textSelection.Text = string.Empty;
31 | textSelection.Insert(fileContent);
32 | textSelection.StartOfDocument();
33 |
34 | fileDocument.Save();
35 | }
36 | else
37 | {
38 | throw new Exception($"File {fileFullPath} doesn't exist!");
39 | }
40 | }
41 | catch (Exception ex)
42 | {
43 | throw ex;
44 | }
45 | }
46 |
47 | public static void EditTemplate(string fileName, string fileFullPath)
48 | {
49 | try
50 | {
51 | ThreadHelper.ThrowIfNotOnUIThread();
52 |
53 | if (File.Exists(fileFullPath))
54 | {
55 | DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
56 | dte.ItemOperations.OpenFile(fileFullPath);
57 | }
58 | else
59 | {
60 | throw new Exception($"File {fileFullPath} doesn't exist!");
61 | }
62 | }
63 | catch (Exception ex)
64 | {
65 | throw ex;
66 | }
67 | }
68 |
69 | public static void ExecuteTemplate(string fileName, string fileFullPath, bool confirmScriptExecution)
70 | {
71 | string CMD_QUERY_EXECUTE = "Query.Execute";
72 |
73 | try
74 | {
75 | ThreadHelper.ThrowIfNotOnUIThread();
76 |
77 | DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
78 |
79 | // Ensure the document we are executing is the document we have opened by checking its name
80 | if (dte.ActiveDocument != null && dte.ActiveDocument.ProjectItem.Name.Equals(fileName))
81 | {
82 | dte.ExecuteCommand(CMD_QUERY_EXECUTE);
83 | }
84 | }
85 | catch (Exception ex)
86 | {
87 | throw ex;
88 | }
89 | }
90 |
91 | public static void FormatSelection()
92 | {
93 | try
94 | {
95 | ThreadHelper.ThrowIfNotOnUIThread();
96 |
97 | DTE dte = Package.GetGlobalService(typeof(DTE)) as DTE;
98 |
99 | if (dte.ActiveDocument != null)
100 | {
101 | TextSelection selection = (TextSelection)dte.ActiveDocument.Selection;
102 |
103 | // Format whole text: selection.SelectAll();
104 | string selectedText = selection.Text;
105 |
106 | // Nothing is selected
107 | if (string.IsNullOrEmpty(selectedText))
108 | return;
109 |
110 | string formattedText = FormatSelectionUsingSQLServer(selectedText);
111 |
112 | selection.Delete();
113 | selection.Insert(formattedText);
114 | }
115 | }
116 | catch (Exception ex)
117 | {
118 | throw ex;
119 | }
120 | }
121 |
122 | private static string FormatSelectionUsingSQLServer(string code)
123 | {
124 | ISettingsRepository settingsRepository = new SettingsRepository();
125 |
126 | var tupleSQLParser = GetSQLParser(settingsRepository.SQLParserVersion);
127 |
128 | TSqlParser sqlParser = tupleSQLParser.Item1;
129 | SqlScriptGenerator sqlScriptGeneration = tupleSQLParser.Item2;
130 |
131 | // Parse selected code and look for errors
132 | IList lstParseErrors = new List();
133 | var result = sqlParser.Parse(new StringReader(code), out lstParseErrors);
134 |
135 | if (lstParseErrors.Count > 0)
136 | {
137 | string error = lstParseErrors.Select(p => p.Message).Aggregate((a, b) => $"{a}{Environment.NewLine}{b}");
138 |
139 | throw new Exception($"SQL Parser unable format selected text due to a syntax error.{Environment.NewLine}{Environment.NewLine}{error}");
140 | }
141 |
142 | // Generate formatted code
143 | string resultCode = string.Empty;
144 | sqlScriptGeneration.Options.IncludeSemicolons = false;
145 | sqlScriptGeneration.Options.AlignClauseBodies = false;
146 | sqlScriptGeneration.GenerateScript(result, out resultCode);
147 |
148 | return resultCode;
149 | }
150 |
151 | private static Tuple GetSQLParser(string targetVersion)
152 | {
153 | if (targetVersion == "SQL Server 2019")
154 | {
155 | return new Tuple(new TSql150Parser(false), new Sql150ScriptGenerator());
156 | }
157 | else if (targetVersion == "SQL Server 2017")
158 | {
159 | return new Tuple(new TSql140Parser(false), new Sql140ScriptGenerator());
160 | }
161 | else if (targetVersion == "SQL Server 2016")
162 | {
163 | return new Tuple(new TSql130Parser(false), new Sql130ScriptGenerator());
164 | }
165 |
166 | throw new ArgumentOutOfRangeException($"Couldn't find the SQL Parser for {targetVersion}.");
167 | }
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/Extensions/CollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using SQLScriptsExplorer.Addin.Models;
4 |
5 | namespace SQLScriptsExplorer.Addin.Infrastructure.Extensions
6 | {
7 | public static class CollectionExtensions
8 | {
9 | public static List Clone(this List listToClone) where T : ITreeNode
10 | {
11 | return listToClone.Select(item => ((T)item).Clone(default(T))).ToList();
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/Extensions/TreeViewItemExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | namespace SQLScriptsExplorer.Addin.Infrastructure.Extensions
6 | {
7 | public static class TreeViewItemExtensions
8 | {
9 | public static int GetDepth(this TreeViewItem item)
10 | {
11 | TreeViewItem parent;
12 |
13 | while ((parent = GetParent(item)) != null)
14 | {
15 | return GetDepth(parent) + 1;
16 | }
17 |
18 | return 0;
19 | }
20 |
21 | private static TreeViewItem GetParent(TreeViewItem item)
22 | {
23 | var parent = VisualTreeHelper.GetParent(item);
24 |
25 | while (!(parent is TreeViewItem || parent is TreeView))
26 | {
27 | parent = VisualTreeHelper.GetParent(parent);
28 | }
29 |
30 | return parent as TreeViewItem;
31 | }
32 |
33 | ///
34 | /// Get the various controls inside the ItemTemplate
35 | ///
36 | public static ChildItem FindVisualChild(DependencyObject obj) where ChildItem : DependencyObject
37 | {
38 | for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
39 | {
40 | DependencyObject child = VisualTreeHelper.GetChild(obj, i);
41 | if (child != null && child is ChildItem)
42 | return (ChildItem)child;
43 | else
44 | {
45 | ChildItem childOfChild = FindVisualChild(child);
46 | if (childOfChild != null)
47 | return childOfChild;
48 | }
49 | }
50 |
51 | return null;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/Helpers/PathHelper.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace SQLScriptsExplorer.Addin.Infrastructure.Helpers
4 | {
5 | public static class PathHelper
6 | {
7 | public static string GetDirectoryTemporaryPath(string path)
8 | {
9 | do
10 | {
11 | path = $"{path}_{Utils.GenerateID(7)}";
12 |
13 | } while (Directory.Exists(path));
14 |
15 | return path;
16 | }
17 |
18 | public static bool IsNetworkPath(string path)
19 | {
20 | if (!path.StartsWith(@"/") && !path.StartsWith(@"\"))
21 | {
22 | string rootPath = Path.GetPathRoot(path);
23 | DriveInfo driveInfo = new DriveInfo(rootPath);
24 |
25 | return driveInfo.DriveType == DriveType.Network;
26 | }
27 |
28 | return true;
29 | }
30 |
31 | public static string GetNextNewFileNameAvailable(string path)
32 | {
33 | var fileCount = 1;
34 | var fileName = string.Empty;
35 | var fileFullPath = string.Empty;
36 |
37 | do
38 | {
39 | fileName = $"New File {fileCount++}.sql";
40 | fileFullPath = Path.Combine(path, fileName);
41 | } while (File.Exists(fileFullPath));
42 |
43 | return fileName;
44 | }
45 |
46 | public static string GetNextNewFolderNameAvailable(string path)
47 | {
48 | var directoryCount = 1;
49 | var directoryName = string.Empty;
50 | var directoryFullPath = string.Empty;
51 |
52 | do
53 | {
54 | directoryName = $"New Folder {directoryCount++}";
55 | directoryFullPath = Path.Combine(path, directoryName);
56 | } while (Directory.Exists(directoryFullPath));
57 |
58 | return directoryName;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/Helpers/TreeViewHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using SQLScriptsExplorer.Addin.Models;
3 |
4 | namespace SQLScriptsExplorer.Addin.Infrastructure.Helpers
5 | {
6 | public static class TreeViewHelper
7 | {
8 | public static void ExpandTreeView(List lstTreeViewItems)
9 | {
10 | ExpandCollapseTreeView(lstTreeViewItems, true);
11 | }
12 |
13 | public static void CollapseTreeView(List lstTreeViewItems)
14 | {
15 | ExpandCollapseTreeView(lstTreeViewItems, false);
16 | }
17 |
18 | private static void ExpandCollapseTreeView(List lstTreeViewItems, bool isExpanded)
19 | {
20 | foreach (TreeNode item in lstTreeViewItems)
21 | {
22 | item.IsExpanded = isExpanded;
23 |
24 | if (item.Children.Count > 0)
25 | ExpandCollapseTreeView(item.Children, isExpanded);
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/RegistryManager.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 |
4 | namespace SQLScriptsExplorer.Addin.Infrastructure
5 | {
6 | public static class RegistryManager
7 | {
8 | private static RegistryKey RootRegistry
9 | {
10 | get
11 | {
12 | var settingKeyRoot = Registry.CurrentUser.CreateSubKey("SQLScriptsExplorer.Addin");
13 | var settings = settingKeyRoot.CreateSubKey("Settings");
14 |
15 | return settings;
16 | }
17 | }
18 |
19 | public static string GetRegisterValue(string name)
20 | {
21 | string value = string.Empty;
22 |
23 | try
24 | {
25 | var registryValue = RootRegistry.GetValue(name);
26 |
27 | if (registryValue == null)
28 | return string.Empty;
29 |
30 | value = registryValue.ToString();
31 | }
32 | catch { }
33 |
34 | return value;
35 | }
36 |
37 | public static void SaveRegisterValue(string name, string value)
38 | {
39 | try
40 | {
41 | RootRegistry.SetValue(name, value);
42 | RootRegistry.Close();
43 | }
44 | catch (Exception ex)
45 | {
46 | throw ex;
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Infrastructure/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Drawing.Imaging;
4 | using System.IO;
5 | using System.Windows.Media.Imaging;
6 |
7 | namespace SQLScriptsExplorer.Addin.Infrastructure
8 | {
9 | public static class Utils
10 | {
11 | private static readonly Random random = new Random();
12 | private static readonly object syncLock = new object();
13 |
14 | public static string GenerateID(int length)
15 | {
16 | lock (syncLock)
17 | {
18 | var characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
19 | var result = new char[length];
20 |
21 | for (int i = 0; i < length; i++)
22 | {
23 | var randomCharacter = random.Next(characters.Length);
24 |
25 | result[i] = characters[randomCharacter];
26 | }
27 |
28 | return new string(result);
29 | }
30 | }
31 |
32 | public static BitmapImage GetResourceImage(string name)
33 | {
34 | try
35 | {
36 | using (var memory = new MemoryStream())
37 | {
38 |
39 | var bitmap = (Bitmap)Properties.Resources.ResourceManager.GetObject(name);
40 | bitmap.Save(memory, ImageFormat.Png);
41 |
42 | memory.Position = 0L;
43 | var bitmapImage = new BitmapImage();
44 | bitmapImage.BeginInit();
45 | bitmapImage.StreamSource = memory;
46 | bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
47 | bitmapImage.EndInit();
48 |
49 | return bitmapImage;
50 | }
51 | }
52 | catch (Exception ex)
53 | {
54 | }
55 |
56 | return default;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Key.snk
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Models/Enums/ScriptFileDoubleClickBehaviour.cs:
--------------------------------------------------------------------------------
1 | namespace SQLScriptsExplorer.Addin.Models.Enums
2 | {
3 | public enum ScriptFileDoubleClickBehaviour
4 | {
5 | OpenNewInstance = 0,
6 | Edit = 1
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Models/Enums/TreeNodeType.cs:
--------------------------------------------------------------------------------
1 | namespace SQLScriptsExplorer.Addin.Models.Enums
2 | {
3 | public enum TreeNodeType
4 | {
5 | RootFolder = 0,
6 | Folder = 1,
7 | File = 2
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Models/FolderMapping.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.IO;
3 |
4 | namespace SQLScriptsExplorer.Addin.Models
5 | {
6 | public class FolderMapping
7 | {
8 | public string Alias { get; set; }
9 | public string FolderPath { get; set; }
10 | public Image IsValid
11 | {
12 | get
13 | {
14 |
15 | Bitmap imageError = (Bitmap)Properties.Resources.ResourceManager.GetObject("Error");
16 |
17 | if (string.IsNullOrWhiteSpace(Alias))
18 | return imageError;
19 |
20 | if (string.IsNullOrWhiteSpace(FolderPath) || !Directory.Exists(FolderPath))
21 | return imageError;
22 |
23 | return (Bitmap)Properties.Resources.ResourceManager.GetObject("Success");
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Models/ITreeNode.cs:
--------------------------------------------------------------------------------
1 | namespace SQLScriptsExplorer.Addin.Models
2 | {
3 | public interface ITreeNode
4 | {
5 | T Clone(T parentNode);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Models/TreeNode.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Windows.Media.Imaging;
3 | using SQLScriptsExplorer.Addin.Infrastructure;
4 | using SQLScriptsExplorer.Addin.Models.Enums;
5 |
6 | namespace SQLScriptsExplorer.Addin.Models
7 | {
8 | public class TreeNode : ITreeNode
9 | {
10 | public string Id { get; internal set; }
11 | public string FileName { get; set; }
12 | public string FileFullPath { get; set; }
13 | public TreeNodeType Type { get; set; }
14 |
15 | public TreeNode Parent { get; set; }
16 | public List Children { get; set; }
17 |
18 | #region UI
19 |
20 | public BitmapImage Icon { get { return Utils.GetResourceImage(Type.ToString()); } }
21 | public bool IsSelected { get; set; }
22 | public bool IsExpanded { get; set; }
23 | public string HighlightPhrase { get; set; }
24 |
25 | #endregion
26 |
27 | public TreeNode()
28 | {
29 | Id = Utils.GenerateID(8);
30 | Children = new List();
31 | }
32 |
33 | public TreeNode(string fileName, string fileFullPath, TreeNodeType type) : this()
34 | {
35 | FileName = fileName;
36 | FileFullPath = fileFullPath;
37 | Type = type;
38 | }
39 |
40 | public TreeNode Clone(TreeNode parentNode)
41 | {
42 | if (this == null)
43 | return null;
44 |
45 | var clone = new TreeNode(FileName, FileFullPath, Type)
46 | {
47 | Id = Id,
48 | Parent = parentNode
49 | };
50 |
51 | clone.Children = new List();
52 |
53 | if (Children.Count > 0)
54 | Children.ForEach(p => clone.Children.Add(p.Clone(clone)));
55 |
56 | return clone;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SQLScriptsExplorer.Addin")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SQLScriptsExplorer.Addin")]
13 | [assembly: AssemblyCopyright("")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // Version information for an assembly consists of the following four values:
23 | //
24 | // Major Version
25 | // Minor Version
26 | // Build Number
27 | // Revision
28 | //
29 | // You can specify all the values or you can default the Build and Revision Numbers
30 | // by using the '*' as shown below:
31 | // [assembly: AssemblyVersion("1.0.*")]
32 | [assembly: AssemblyVersion("1.0.0.0")]
33 | [assembly: AssemblyFileVersion("1.0.0.0")]
34 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SQLScriptsExplorer.Addin.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SQLScriptsExplorer.Addin.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap CollapseAll {
67 | get {
68 | object obj = ResourceManager.GetObject("CollapseAll", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Bitmap.
75 | ///
76 | internal static System.Drawing.Bitmap Delete {
77 | get {
78 | object obj = ResourceManager.GetObject("Delete", resourceCulture);
79 | return ((System.Drawing.Bitmap)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Bitmap.
85 | ///
86 | internal static System.Drawing.Bitmap Error {
87 | get {
88 | object obj = ResourceManager.GetObject("Error", resourceCulture);
89 | return ((System.Drawing.Bitmap)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | internal static System.Drawing.Bitmap ExpandAll {
97 | get {
98 | object obj = ResourceManager.GetObject("ExpandAll", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized resource of type System.Drawing.Bitmap.
105 | ///
106 | internal static System.Drawing.Bitmap File {
107 | get {
108 | object obj = ResourceManager.GetObject("File", resourceCulture);
109 | return ((System.Drawing.Bitmap)(obj));
110 | }
111 | }
112 |
113 | ///
114 | /// Looks up a localized resource of type System.Drawing.Bitmap.
115 | ///
116 | internal static System.Drawing.Bitmap Folder {
117 | get {
118 | object obj = ResourceManager.GetObject("Folder", resourceCulture);
119 | return ((System.Drawing.Bitmap)(obj));
120 | }
121 | }
122 |
123 | ///
124 | /// Looks up a localized resource of type System.Drawing.Bitmap.
125 | ///
126 | internal static System.Drawing.Bitmap FormatScript {
127 | get {
128 | object obj = ResourceManager.GetObject("FormatScript", resourceCulture);
129 | return ((System.Drawing.Bitmap)(obj));
130 | }
131 | }
132 |
133 | ///
134 | /// Looks up a localized resource of type System.Drawing.Bitmap.
135 | ///
136 | internal static System.Drawing.Bitmap NewFile {
137 | get {
138 | object obj = ResourceManager.GetObject("NewFile", resourceCulture);
139 | return ((System.Drawing.Bitmap)(obj));
140 | }
141 | }
142 |
143 | ///
144 | /// Looks up a localized resource of type System.Drawing.Bitmap.
145 | ///
146 | internal static System.Drawing.Bitmap NewFolder {
147 | get {
148 | object obj = ResourceManager.GetObject("NewFolder", resourceCulture);
149 | return ((System.Drawing.Bitmap)(obj));
150 | }
151 | }
152 |
153 | ///
154 | /// Looks up a localized resource of type System.Drawing.Bitmap.
155 | ///
156 | internal static System.Drawing.Bitmap NewSQLFile {
157 | get {
158 | object obj = ResourceManager.GetObject("NewSQLFile", resourceCulture);
159 | return ((System.Drawing.Bitmap)(obj));
160 | }
161 | }
162 |
163 | ///
164 | /// Looks up a localized resource of type System.Drawing.Bitmap.
165 | ///
166 | internal static System.Drawing.Bitmap OpenFile {
167 | get {
168 | object obj = ResourceManager.GetObject("OpenFile", resourceCulture);
169 | return ((System.Drawing.Bitmap)(obj));
170 | }
171 | }
172 |
173 | ///
174 | /// Looks up a localized resource of type System.Drawing.Bitmap.
175 | ///
176 | internal static System.Drawing.Bitmap OpenFolder {
177 | get {
178 | object obj = ResourceManager.GetObject("OpenFolder", resourceCulture);
179 | return ((System.Drawing.Bitmap)(obj));
180 | }
181 | }
182 |
183 | ///
184 | /// Looks up a localized resource of type System.Drawing.Bitmap.
185 | ///
186 | internal static System.Drawing.Bitmap Refresh {
187 | get {
188 | object obj = ResourceManager.GetObject("Refresh", resourceCulture);
189 | return ((System.Drawing.Bitmap)(obj));
190 | }
191 | }
192 |
193 | ///
194 | /// Looks up a localized resource of type System.Drawing.Bitmap.
195 | ///
196 | internal static System.Drawing.Bitmap Rename {
197 | get {
198 | object obj = ResourceManager.GetObject("Rename", resourceCulture);
199 | return ((System.Drawing.Bitmap)(obj));
200 | }
201 | }
202 |
203 | ///
204 | /// Looks up a localized resource of type System.Drawing.Bitmap.
205 | ///
206 | internal static System.Drawing.Bitmap RootFolder {
207 | get {
208 | object obj = ResourceManager.GetObject("RootFolder", resourceCulture);
209 | return ((System.Drawing.Bitmap)(obj));
210 | }
211 | }
212 |
213 | ///
214 | /// Looks up a localized resource of type System.Drawing.Bitmap.
215 | ///
216 | internal static System.Drawing.Bitmap Settings {
217 | get {
218 | object obj = ResourceManager.GetObject("Settings", resourceCulture);
219 | return ((System.Drawing.Bitmap)(obj));
220 | }
221 | }
222 |
223 | ///
224 | /// Looks up a localized resource of type System.Drawing.Bitmap.
225 | ///
226 | internal static System.Drawing.Bitmap SQLScriptsManager {
227 | get {
228 | object obj = ResourceManager.GetObject("SQLScriptsManager", resourceCulture);
229 | return ((System.Drawing.Bitmap)(obj));
230 | }
231 | }
232 |
233 | ///
234 | /// Looks up a localized resource of type System.Drawing.Bitmap.
235 | ///
236 | internal static System.Drawing.Bitmap Success {
237 | get {
238 | object obj = ResourceManager.GetObject("Success", resourceCulture);
239 | return ((System.Drawing.Bitmap)(obj));
240 | }
241 | }
242 |
243 | ///
244 | /// Looks up a localized resource of type System.Drawing.Bitmap.
245 | ///
246 | internal static System.Drawing.Bitmap TextFile {
247 | get {
248 | object obj = ResourceManager.GetObject("TextFile", resourceCulture);
249 | return ((System.Drawing.Bitmap)(obj));
250 | }
251 | }
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\resources\images\collapseall.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
125 | ..\resources\images\delete.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
126 |
127 |
128 | ..\resources\images\error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
129 |
130 |
131 | ..\resources\images\expandall.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
132 |
133 |
134 | ..\resources\images\file.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
135 |
136 |
137 | ..\resources\images\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
138 |
139 |
140 | ..\resources\images\formatscript.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
141 |
142 |
143 | ..\resources\images\newfile.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
144 |
145 |
146 | ..\resources\images\newfolder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
147 |
148 |
149 | ..\resources\images\newsqlfile.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
150 |
151 |
152 | ..\resources\images\openfile.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
153 |
154 |
155 | ..\resources\images\openfolder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
156 |
157 |
158 | ..\resources\images\refresh.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
159 |
160 |
161 | ..\resources\images\rename.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
162 |
163 |
164 | ..\resources\images\rootfolder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
165 |
166 |
167 | ..\resources\images\settings.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
168 |
169 |
170 | ..\resources\images\sqlscriptsmanager.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
171 |
172 |
173 | ..\resources\images\success.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
174 |
175 |
176 | ..\resources\images\textfile.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
177 |
178 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Repository/Interfaces/ISettingsRepository.cs:
--------------------------------------------------------------------------------
1 | using SQLScriptsExplorer.Addin.Models;
2 | using SQLScriptsExplorer.Addin.Models.Enums;
3 | using System.Collections.Generic;
4 |
5 | namespace SQLScriptsExplorer.Addin.Repository.Interfaces
6 | {
7 | public interface ISettingsRepository
8 | {
9 | List FolderMapping { get; set; }
10 | string SQLParserVersion { get; set; }
11 | string AllowedFileTypes { get; set; }
12 | bool ExpandMappedFoldersOnLoad { get; set; }
13 | bool ShowExecuteFileButton { get; set; }
14 | bool ConfirmScriptExecution { get; set; }
15 |
16 | ScriptFileDoubleClickBehaviour ScriptFileDoubleClickBehaviour { get; set; }
17 |
18 | void Refresh();
19 | void Save();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Repository/Interfaces/ITreeNodeRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using SQLScriptsExplorer.Addin.Models;
3 |
4 | namespace SQLScriptsExplorer.Addin.Repository.Interfaces
5 | {
6 | public interface ITreeNodeRepository
7 | {
8 | List Tree { get; }
9 | List TreeSearchResult { get; }
10 | Dictionary TreeDictionary { get; }
11 | Dictionary TreeSearchResultsDictionary { get; }
12 | void Load(List lstFolderMapping, bool expandMappedFolderOnLoad, string allowedFileTypes);
13 | List Search(string keyword);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Repository/SettingsRepository.cs:
--------------------------------------------------------------------------------
1 | using SQLScriptsExplorer.Addin.Infrastructure;
2 | using SQLScriptsExplorer.Addin.Models;
3 | using SQLScriptsExplorer.Addin.Models.Enums;
4 | using SQLScriptsExplorer.Addin.Repository.Interfaces;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 |
9 | namespace SQLScriptsExplorer.Addin.Repository
10 | {
11 | public class SettingsRepository : ISettingsRepository
12 | {
13 | private const string FOLDER_MAPPING = "FolderMapping";
14 | private const string SQL_PARSER = "SQLParser";
15 | private const string EXPAND_MAPPEDFOLDERS_ONLOAD = "ExpandMappedFoldersOnLoad";
16 | private const string ALLOWED_FILE_TYPES = "AllowedFileTypes";
17 | private const string SHOW_EXECUTEFILE_BUTTON = "ShowExecuteFileButton";
18 | private const string CONFIRM_SCRIPT_EXECUTION = "ConfirmScriptExecution";
19 | private const string SCRIPT_FILE_DOUBLE_CLICK_BEHAVIOUR = "ScriptFileDoubleClickBehaviour";
20 |
21 | public List FolderMapping { get; set; }
22 |
23 | public string SQLParserVersion { get; set; }
24 |
25 | public bool ExpandMappedFoldersOnLoad { get; set; }
26 |
27 | public string AllowedFileTypes { get; set; }
28 |
29 | public bool ShowExecuteFileButton { get; set; }
30 |
31 | public bool ConfirmScriptExecution { get; set; }
32 |
33 | public ScriptFileDoubleClickBehaviour ScriptFileDoubleClickBehaviour { get; set; }
34 |
35 | public SettingsRepository()
36 | {
37 | Refresh();
38 | }
39 |
40 | public void Refresh()
41 | {
42 | LoadFolderMapping();
43 | LoadFileExplorerSettings();
44 | LoadGenericSettings();
45 | }
46 |
47 | public void Save()
48 | {
49 | var jsonFolderMapping = Newtonsoft.Json.JsonConvert.SerializeObject(FolderMapping);
50 |
51 | RegistryManager.SaveRegisterValue(FOLDER_MAPPING, jsonFolderMapping);
52 | RegistryManager.SaveRegisterValue(SQL_PARSER, SQLParserVersion);
53 | RegistryManager.SaveRegisterValue(EXPAND_MAPPEDFOLDERS_ONLOAD, ExpandMappedFoldersOnLoad.ToString());
54 | RegistryManager.SaveRegisterValue(ALLOWED_FILE_TYPES, AllowedFileTypes);
55 | RegistryManager.SaveRegisterValue(SHOW_EXECUTEFILE_BUTTON, ShowExecuteFileButton.ToString());
56 | RegistryManager.SaveRegisterValue(CONFIRM_SCRIPT_EXECUTION, ConfirmScriptExecution.ToString());
57 | RegistryManager.SaveRegisterValue(SCRIPT_FILE_DOUBLE_CLICK_BEHAVIOUR, $"{(int)ScriptFileDoubleClickBehaviour}");
58 | }
59 |
60 | private void LoadFolderMapping()
61 | {
62 | FolderMapping = null;
63 |
64 | string folderMappingRegister = RegistryManager.GetRegisterValue(FOLDER_MAPPING);
65 |
66 | try
67 | {
68 | FolderMapping = Newtonsoft.Json.JsonConvert.DeserializeObject>(folderMappingRegister);
69 | }
70 | catch
71 | {
72 | throw new Exception("Could not load your folders mapping configuration, it has now been reset.");
73 | }
74 |
75 | if (FolderMapping == null || FolderMapping.Count == 0)
76 | {
77 | FolderMapping = new List();
78 |
79 | var folderMapping = new FolderMapping()
80 | {
81 | Alias = "Personal",
82 | FolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "SQLScriptsExplorer"),
83 | };
84 |
85 | FolderMapping.Add(folderMapping);
86 | }
87 | }
88 |
89 | private void LoadFileExplorerSettings()
90 | {
91 | // Show Execute File Button and
92 | var showExecuteFileButton = RegistryManager.GetRegisterValue(SHOW_EXECUTEFILE_BUTTON);
93 | if (string.IsNullOrEmpty(showExecuteFileButton))
94 | ShowExecuteFileButton = true;
95 | else
96 | ShowExecuteFileButton = bool.Parse(showExecuteFileButton);
97 |
98 | // Confirm Script Execution
99 | var confirmScriptExecution = RegistryManager.GetRegisterValue(CONFIRM_SCRIPT_EXECUTION);
100 | if (string.IsNullOrEmpty(confirmScriptExecution))
101 | ConfirmScriptExecution = true;
102 | else
103 | ConfirmScriptExecution = bool.Parse(confirmScriptExecution);
104 |
105 | // Script File Double Click Behaviour
106 | var scriptFileDoubleClickBehaviour = RegistryManager.GetRegisterValue(SCRIPT_FILE_DOUBLE_CLICK_BEHAVIOUR);
107 | if (string.IsNullOrEmpty(scriptFileDoubleClickBehaviour))
108 | ScriptFileDoubleClickBehaviour = ScriptFileDoubleClickBehaviour.OpenNewInstance;
109 | else
110 | ScriptFileDoubleClickBehaviour = (ScriptFileDoubleClickBehaviour)int.Parse(scriptFileDoubleClickBehaviour);
111 | }
112 |
113 | private void LoadGenericSettings()
114 | {
115 | // SQL Parser Version
116 | SQLParserVersion = RegistryManager.GetRegisterValue(SQL_PARSER);
117 | if (string.IsNullOrEmpty(SQLParserVersion))
118 | {
119 | SQLParserVersion = "SQL Server 2019";
120 | }
121 |
122 | // Expand Mapped Folders OnLoad
123 | var expandMappedFoldersOnLoad = RegistryManager.GetRegisterValue(EXPAND_MAPPEDFOLDERS_ONLOAD);
124 | if (string.IsNullOrEmpty(expandMappedFoldersOnLoad))
125 | ExpandMappedFoldersOnLoad = true;
126 | else
127 | ExpandMappedFoldersOnLoad = bool.Parse(expandMappedFoldersOnLoad);
128 |
129 | // Allowed File Types
130 | AllowedFileTypes = RegistryManager.GetRegisterValue(ALLOWED_FILE_TYPES);
131 | if (string.IsNullOrEmpty(AllowedFileTypes))
132 | {
133 | AllowedFileTypes = "*.sql";
134 | }
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Repository/TreeNodeRepository.cs:
--------------------------------------------------------------------------------
1 | using SQLScriptsExplorer.Addin.Infrastructure.Extensions;
2 | using SQLScriptsExplorer.Addin.Models;
3 | using SQLScriptsExplorer.Addin.Models.Enums;
4 | using SQLScriptsExplorer.Addin.Repository.Interfaces;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 |
9 | namespace SQLScriptsExplorer.Addin.Repository
10 | {
11 | public class TreeNodeRepository : ITreeNodeRepository
12 | {
13 | public List Tree { get; internal set; } = new List();
14 | public List TreeSearchResult { get; internal set; } = new List();
15 | public Dictionary TreeDictionary { get; internal set; } = new Dictionary();
16 | public Dictionary TreeSearchResultsDictionary { get; internal set; } = new Dictionary();
17 |
18 | private string previousSearchKeyword = string.Empty;
19 |
20 | #region Load
21 |
22 | public void Load(List lstFolderMapping, bool expandMappedFolderOnLoad, string allowedFileTypes)
23 | {
24 | Tree.Clear();
25 | TreeDictionary.Clear();
26 |
27 | foreach (var folderMapping in lstFolderMapping)
28 | {
29 | if (!string.IsNullOrEmpty(folderMapping.Alias) && !string.IsNullOrEmpty(folderMapping.FolderPath) && Directory.Exists(folderMapping.FolderPath))
30 | {
31 | var treeNodeAlias = new TreeNode(folderMapping.Alias, folderMapping.FolderPath, TreeNodeType.RootFolder);
32 | treeNodeAlias.IsExpanded = expandMappedFolderOnLoad;
33 |
34 | Tree.Add(treeNodeAlias);
35 | TreeDictionary.Add(treeNodeAlias.Id, treeNodeAlias);
36 |
37 | CreateTree(Tree, TreeDictionary, folderMapping.FolderPath, treeNodeAlias, allowedFileTypes);
38 | }
39 | }
40 | }
41 |
42 | private List CreateTree(List lstTreeNode, Dictionary dicTreeNode, string folder, TreeNode parentTreeNode, string allowedFileTypes)
43 | {
44 | var lstDirectories = Directory.GetDirectories(folder);
45 |
46 | foreach (var directory in lstDirectories)
47 | {
48 | try
49 | {
50 | var directoryInfo = new DirectoryInfo(directory);
51 | var treeNodeFolder = new TreeNode(directoryInfo.Name, directoryInfo.FullName, TreeNodeType.Folder);
52 |
53 | if (parentTreeNode is null)
54 | {
55 | lstTreeNode.Add(treeNodeFolder);
56 | }
57 | else
58 | {
59 | treeNodeFolder.Parent = parentTreeNode;
60 |
61 | parentTreeNode.Children.Add(treeNodeFolder);
62 | }
63 |
64 | dicTreeNode.Add(treeNodeFolder.Id, treeNodeFolder);
65 |
66 | CreateTree(lstTreeNode, dicTreeNode, Path.Combine(folder, directory), treeNodeFolder, allowedFileTypes);
67 | }
68 | catch (Exception ex)
69 | {
70 | throw ex;
71 | }
72 | }
73 |
74 | var lstFiles = Directory.GetFiles(folder, allowedFileTypes);
75 |
76 | foreach (var file in lstFiles)
77 | {
78 | try
79 | {
80 | var fileInfo = new FileInfo(file);
81 | var treeNodeFile = new TreeNode(fileInfo.Name, fileInfo.FullName, TreeNodeType.File);
82 |
83 | if (parentTreeNode is null)
84 | {
85 | lstTreeNode.Add(treeNodeFile);
86 | }
87 | else
88 | {
89 | treeNodeFile.Parent = parentTreeNode;
90 |
91 | parentTreeNode.Children.Add(treeNodeFile);
92 | }
93 |
94 | dicTreeNode.Add(treeNodeFile.Id, treeNodeFile);
95 | }
96 | catch (Exception ex)
97 | {
98 | throw ex;
99 | }
100 | }
101 |
102 | return lstTreeNode;
103 | }
104 |
105 | #endregion
106 |
107 | #region Search
108 |
109 | public List Search(string keyword)
110 | {
111 | // Use current search Tree to perform further searches
112 | if (!string.IsNullOrWhiteSpace(keyword) && !string.IsNullOrWhiteSpace(previousSearchKeyword) &&
113 | keyword.StartsWith(previousSearchKeyword))
114 | {
115 | TreeSearchResult = TreeSearchResult.Clone();
116 | }
117 | // Branch new search
118 | else
119 | {
120 | TreeSearchResult = Tree.Clone();
121 | }
122 |
123 | Search(TreeSearchResult, TreeSearchResultsDictionary, keyword);
124 |
125 | TreeSearchResultsDictionary.Clear();
126 | BuildDictionary(TreeSearchResult, TreeSearchResultsDictionary, keyword);
127 |
128 | previousSearchKeyword = keyword;
129 |
130 | return TreeSearchResult;
131 | }
132 |
133 | private void Search(List lstTreeNodeSearchResults, Dictionary dicTreeNodeSearchResults, string keyword)
134 | {
135 | SearchNodes(lstTreeNodeSearchResults, dicTreeNodeSearchResults, keyword);
136 | }
137 |
138 | private void SearchNodes(List lstTreeNodeSearchResults, Dictionary dicTreeNodeSearchResults, string keyword)
139 | {
140 | if (lstTreeNodeSearchResults.Count == 0)
141 | return;
142 |
143 | for (int i = lstTreeNodeSearchResults.Count - 1; i >= 0; i--)
144 | {
145 | var treeNode = lstTreeNodeSearchResults[i];
146 | SearchNodes(treeNode.Children, dicTreeNodeSearchResults, keyword);
147 |
148 | var isNoMatchFile = treeNode.Type == TreeNodeType.File && treeNode.FileName.ToUpperInvariant().IndexOf(keyword.ToUpperInvariant()) == -1;
149 | var isNoMatchFolder = (treeNode.Type == TreeNodeType.Folder || treeNode.Type == TreeNodeType.RootFolder) &&
150 | lstTreeNodeSearchResults.Contains(treeNode) && treeNode.Children.Count == 0 &&
151 | treeNode.FileName.ToUpperInvariant().IndexOf(keyword.ToUpperInvariant()) == -1;
152 |
153 | if (isNoMatchFile || isNoMatchFolder)
154 | {
155 | if (treeNode.Parent != null)
156 | {
157 | treeNode.Parent.Children.Remove(treeNode);
158 | }
159 |
160 | lstTreeNodeSearchResults.Remove(treeNode);
161 | dicTreeNodeSearchResults.Remove(treeNode.Id);
162 | }
163 | }
164 | }
165 |
166 | private void BuildDictionary(List lstTreeNode, Dictionary dicTreeNode, string keyword)
167 | {
168 | foreach (var treeNode in lstTreeNode)
169 | {
170 | treeNode.HighlightPhrase = keyword;
171 |
172 | dicTreeNode.Add(treeNode.Id, treeNode);
173 |
174 | BuildDictionary(treeNode.Children, dicTreeNode, keyword);
175 | }
176 | }
177 |
178 | #endregion
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/CollapseAll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/CollapseAll.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Delete.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Error.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/ExpandAll.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/ExpandAll.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/File.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/File.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Folder.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/FormatScript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/FormatScript.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/NewFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/NewFile.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/NewFolder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/NewFolder.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/NewSQLFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/NewSQLFile.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/OpenFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/OpenFile.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/OpenFolder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/OpenFolder.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Refresh.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Rename.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Rename.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/RootFolder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/RootFolder.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Run.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/SQLScriptsManager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/SQLScriptsManager.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Settings.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/Success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/Success.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/TextFile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/TextFile.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/ToolWindow1Package.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/ToolWindow1Package.ico
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/ToolbarCommand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/ToolbarCommand.png
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Resources/Images/ToolbarCommandPackage.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joaoribe/SQLScriptsExplorer/74fe77c280434d3687b46d9140c60ce703434871/src/SQLScriptsExplorer.Addin/Resources/Images/ToolbarCommandPackage.ico
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/SQLScriptsExplorer.Addin.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16.0
5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
6 |
7 |
8 |
9 | true
10 |
11 |
12 | Key.snk
13 |
14 |
15 |
16 | Debug
17 | AnyCPU
18 | 2.0
19 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | {194CCEE9-F9B5-4681-A1BE-94B31C112D19}
21 | Library
22 | Properties
23 | SQLScriptsExplorer.Addin
24 | SQLScriptsExplorer.Addin
25 | v4.8.1
26 | true
27 | true
28 | true
29 | false
30 | false
31 | true
32 | true
33 | Program
34 | $(DevEnvDir)devenv.exe
35 | /rootsuffix Exp
36 |
37 |
38 | true
39 | full
40 | false
41 | bin\Debug\
42 | DEBUG;TRACE
43 | prompt
44 | 4
45 | True
46 | C:\Program Files %28x86%29\Microsoft SQL Server Management Studio 20\Common7\IDE\Extensions\SQLScriptsExplorer
47 |
48 |
49 | pdbonly
50 | true
51 | bin\Release\
52 | TRACE
53 | prompt
54 | 4
55 | True
56 | C:\Program Files %28x86%29\Microsoft SQL Server Management Studio 18\Common7\IDE\Extensions\SQLScriptsExplorer
57 |
58 |
59 |
60 |
61 | FileExplorerTreeView.xaml
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | True
75 | True
76 | Resources.resx
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Form
89 |
90 |
91 | frmSettings.cs
92 |
93 |
94 |
95 |
96 |
97 | MainToolWindowControl.xaml
98 |
99 |
100 |
101 |
102 |
103 | True
104 | True
105 | VSPackage.resx
106 |
107 |
108 |
109 |
110 |
111 | Designer
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
131 |
132 |
133 | 150.4897.1
134 |
135 |
136 | 15.0.26606
137 |
138 |
139 | 15.0.26228
140 |
141 |
142 | 14.3.25408
143 |
144 |
145 | 7.10.6071
146 |
147 |
148 |
149 | 15.8.33
150 |
151 |
152 | 15.0.10
153 |
154 |
155 | 15.0.26228
156 |
157 |
158 | 15.0.26228
159 |
160 |
161 | 7.10.6071
162 |
163 |
164 | 10.0.30319
165 |
166 |
167 | 11.0.61030
168 |
169 |
170 | 12.0.30110
171 |
172 |
173 | 14.3.25407
174 |
175 |
176 | 8.0.50727
177 |
178 |
179 | 9.0.30729
180 |
181 |
182 | 15.0.26228
183 |
184 |
185 | 15.0.26228
186 |
187 |
188 | 15.0.26228
189 |
190 |
191 | 15.0.26228
192 |
193 |
194 | 7.10.6070
195 |
196 |
197 | 8.0.50727
198 |
199 |
200 | 15.0.240
201 |
202 |
203 | 15.8.122
204 |
205 |
206 | 15.0.26228
207 |
208 |
209 | 15.0.82
210 |
211 |
212 | runtime; build; native; contentfiles; analyzers; buildtransitive
213 | all
214 |
215 |
216 |
217 |
218 | Designer
219 | MSBuild:Compile
220 |
221 |
222 | Designer
223 | MSBuild:Compile
224 |
225 |
226 |
227 |
228 | Menus1.ctmenu
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | Menus.ctmenu
255 |
256 |
257 |
258 |
259 | ResXFileCodeGenerator
260 | Resources.Designer.cs
261 |
262 |
263 | frmSettings.cs
264 |
265 |
266 | true
267 | VSPackage
268 | ResXFileCodeGenerator
269 | VSPackage.Designer.cs
270 |
271 |
272 |
273 |
274 |
275 |
282 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/SQLScriptsExplorer.AddinPackage.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.Shell;
2 | using System;
3 | using System.Runtime.InteropServices;
4 | using System.Threading;
5 | using Task = System.Threading.Tasks.Task;
6 |
7 | namespace SQLScriptsExplorer.Addin
8 | {
9 | ///
10 | /// This is the class that implements the package exposed by this assembly.
11 | ///
12 | ///
13 | ///
14 | /// The minimum requirement for a class to be considered a valid package for Visual Studio
15 | /// is to implement the IVsPackage interface and register itself with the shell.
16 | /// This package uses the helper classes defined inside the Managed Package Framework (MPF)
17 | /// to do it: it derives from the Package class that provides the implementation of the
18 | /// IVsPackage interface and uses the registration attributes defined in the framework to
19 | /// register itself and its components with the shell. These attributes tell the pkgdef creation
20 | /// utility what data to put into .pkgdef file.
21 | ///
22 | ///
23 | /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file.
24 | ///
25 | ///
26 | [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
27 | [Guid(SQLScriptsExplorerAddinPackage.PackageGuidString)]
28 | public sealed class SQLScriptsExplorerAddinPackage : AsyncPackage
29 | {
30 | ///
31 | /// SQLScriptsExplorerAddinPackage GUID string.
32 | ///
33 | public const string PackageGuidString = "5594f41e-ee45-4238-9032-ec95ae0d97c8";
34 |
35 | #region Package Members
36 |
37 | ///
38 | /// Initialization of the package; this method is called right after the package is sited, so this is the place
39 | /// where you can put all the initialization code that rely on services provided by VisualStudio.
40 | ///
41 | /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.
42 | /// A provider for progress updates.
43 | /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.
44 | protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
45 | {
46 | // When initialized asynchronously, the current thread may be a background thread at this point.
47 | // Do any initialization that requires the UI thread after switching to the UI thread.
48 | await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
49 | }
50 |
51 | #endregion
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Styling/Converter/LeftMarginMultiplierConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 | using System.Windows.Data;
6 | using SQLScriptsExplorer.Addin.Infrastructure.Extensions;
7 |
8 | namespace SQLScriptsExplorer.Addin.Styling.Converter
9 | {
10 | public class LeftMarginMultiplierConverter : IValueConverter
11 | {
12 | public double Length { get; set; }
13 |
14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
15 | {
16 | var item = value as TreeViewItem;
17 | if (item == null)
18 | return new Thickness(0);
19 |
20 | return new Thickness(Length * item.GetDepth(), 0, 0, 0);
21 | }
22 |
23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
24 | {
25 | throw new System.NotImplementedException();
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/Styling/Converter/SortableConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Globalization;
4 | using System.Windows.Data;
5 |
6 | namespace SQLScriptsExplorer.Addin.Styling.Converter
7 | {
8 | public class SortableConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | System.Collections.IList collection = value as System.Collections.IList;
13 | ListCollectionView view = new ListCollectionView(collection);
14 | SortDescription sort = new SortDescription(parameter.ToString(), ListSortDirection.Ascending);
15 | view.SortDescriptions.Add(sort);
16 |
17 | return view;
18 | }
19 |
20 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
21 | {
22 | return null;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/VSPackage.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SQLScriptsExplorer.Addin {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class VSPackage {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal VSPackage() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SQLScriptsExplorer.Addin.VSPackage", typeof(VSPackage).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to ToolWindow1 Extension.
65 | ///
66 | internal static string _110 {
67 | get {
68 | return ResourceManager.GetString("110", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to ToolbarCommand Extension.
74 | ///
75 | internal static string _1110 {
76 | get {
77 | return ResourceManager.GetString("1110", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Looks up a localized string similar to ToolbarCommand Visual Stuido Extension Detailed Info.
83 | ///
84 | internal static string _1112 {
85 | get {
86 | return ResourceManager.GetString("1112", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// Looks up a localized string similar to ToolWindow1 Visual Studio Extension Detailed Info.
92 | ///
93 | internal static string _112 {
94 | get {
95 | return ResourceManager.GetString("112", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
101 | ///
102 | internal static System.Drawing.Icon _1400 {
103 | get {
104 | object obj = ResourceManager.GetObject("1400", resourceCulture);
105 | return ((System.Drawing.Icon)(obj));
106 | }
107 | }
108 |
109 | ///
110 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
111 | ///
112 | internal static System.Drawing.Icon _400 {
113 | get {
114 | object obj = ResourceManager.GetObject("400", resourceCulture);
115 | return ((System.Drawing.Icon)(obj));
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/VSPackage.resx:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | text/microsoft-resx
120 |
121 |
122 | 2.0
123 |
124 |
125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
126 |
127 |
128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
129 |
130 |
131 |
132 | ToolWindow1 Extension
133 |
134 |
135 | ToolWindow1 Visual Studio Extension Detailed Info
136 |
137 |
138 | Resources\Images\ToolWindow1Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
139 |
140 |
141 | ToolbarCommand Extension
142 |
143 |
144 | ToolbarCommand Visual Stuido Extension Detailed Info
145 |
146 |
147 | Resources\Images\ToolbarCommandPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
148 |
149 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/frmSettings.cs:
--------------------------------------------------------------------------------
1 | using SQLScriptsExplorer.Addin.Models;
2 | using SQLScriptsExplorer.Addin.Models.Enums;
3 | using SQLScriptsExplorer.Addin.Repository;
4 | using SQLScriptsExplorer.Addin.Repository.Interfaces;
5 | using System.ComponentModel;
6 | using System.Drawing;
7 | using System.Linq;
8 | using System.Windows.Forms;
9 |
10 | namespace SQLScriptsExplorer.Addin
11 | {
12 | public partial class frmSettings : Form
13 | {
14 | private ISettingsRepository settingsRepository = null;
15 | private BindingList folderMappingBindingList = null;
16 | private string jsonFolderMappingPrevious = null;
17 |
18 | public frmSettings()
19 | {
20 | InitializeComponent();
21 |
22 | settingsRepository = new SettingsRepository();
23 |
24 | // Folder Mapping
25 | jsonFolderMappingPrevious = Newtonsoft.Json.JsonConvert.SerializeObject(settingsRepository.FolderMapping);
26 | folderMappingBindingList = new BindingList(settingsRepository.FolderMapping);
27 |
28 | gdvFolderMapping.AutoGenerateColumns = false;
29 | gdvFolderMapping.DataSource = folderMappingBindingList;
30 |
31 | chkExpandOnLoad.Checked = settingsRepository.ExpandMappedFoldersOnLoad;
32 |
33 | // File Explorer
34 | chkShowExecuteFileButton.Checked = settingsRepository.ShowExecuteFileButton;
35 | chkConfirmScriptExecution.Checked = settingsRepository.ConfirmScriptExecution;
36 |
37 | chkShowExecuteFileButton_CheckedChanged(null, System.EventArgs.Empty);
38 |
39 | cboFileDoubleClick.SelectedIndex = (int)settingsRepository.ScriptFileDoubleClickBehaviour;
40 |
41 | // General
42 | cboParserVersion.SelectedItem = settingsRepository.SQLParserVersion;
43 | txtAllowedFileTypes.Text = settingsRepository.AllowedFileTypes;
44 | }
45 |
46 | private void btnSave_Click(object sender, System.EventArgs e)
47 | {
48 | var jsonFolderMappingCurrent = Newtonsoft.Json.JsonConvert.SerializeObject(folderMappingBindingList.ToList());
49 |
50 | // Folder Mapping
51 | settingsRepository.FolderMapping = folderMappingBindingList.ToList();
52 | settingsRepository.ExpandMappedFoldersOnLoad = chkExpandOnLoad.Checked;
53 |
54 | // File Explorer
55 | settingsRepository.ShowExecuteFileButton = chkShowExecuteFileButton.Checked;
56 | settingsRepository.ConfirmScriptExecution = chkConfirmScriptExecution.Checked;
57 |
58 | settingsRepository.ScriptFileDoubleClickBehaviour = (ScriptFileDoubleClickBehaviour)cboFileDoubleClick.SelectedIndex;
59 |
60 | // General
61 | settingsRepository.SQLParserVersion = cboParserVersion.SelectedItem.ToString();
62 | settingsRepository.AllowedFileTypes = txtAllowedFileTypes.Text;
63 |
64 | settingsRepository.Save();
65 |
66 | // Refresh Explorer if mapping has changed
67 | if (jsonFolderMappingPrevious != jsonFolderMappingCurrent)
68 | DialogResult = DialogResult.OK;
69 |
70 | Close();
71 | }
72 |
73 | private void chkShowExecuteFileButton_CheckedChanged(object sender, System.EventArgs e)
74 | {
75 | chkConfirmScriptExecution.Enabled = chkShowExecuteFileButton.Checked;
76 | }
77 |
78 | private void btnCancel_Click(object sender, System.EventArgs e)
79 | {
80 | DialogResult = DialogResult.Cancel;
81 |
82 | Close();
83 | }
84 |
85 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
86 | {
87 | if (keyData == Keys.Escape)
88 | {
89 | btnCancel_Click(null, null);
90 | return true;
91 | }
92 |
93 | return base.ProcessCmdKey(ref msg, keyData);
94 | }
95 |
96 | #region UI Behaviour
97 |
98 | private Rectangle dragBoxFromMouseDown;
99 | private int rowIndexFromMouseDown;
100 | private int rowIndexOfItemUnderMouseToDrop;
101 | private void gdvFolderMapping_MouseMove(object sender, MouseEventArgs e)
102 | {
103 | if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
104 | {
105 | // If the mouse moves outside the rectangle, start the drag.
106 | if (dragBoxFromMouseDown != Rectangle.Empty &&
107 | !dragBoxFromMouseDown.Contains(e.X, e.Y))
108 | {
109 |
110 | // Proceed with the drag and drop, passing in the list item.
111 | DragDropEffects dropEffect = gdvFolderMapping.DoDragDrop(
112 | gdvFolderMapping.Rows[rowIndexFromMouseDown],
113 | DragDropEffects.Move);
114 | }
115 | }
116 | }
117 |
118 | private void gdvFolderMapping_MouseDown(object sender, MouseEventArgs e)
119 | {
120 | // Get the index of the item the mouse is below.
121 | rowIndexFromMouseDown = gdvFolderMapping.HitTest(e.X, e.Y).RowIndex;
122 | if (rowIndexFromMouseDown != -1 && rowIndexFromMouseDown != gdvFolderMapping.RowCount - 1)
123 | {
124 | // Remember the point where the mouse down occurred.
125 | // The DragSize indicates the size that the mouse can move
126 | // before a drag event should be started.
127 | Size dragSize = SystemInformation.DragSize;
128 |
129 | // Create a rectangle using the DragSize, with the mouse position being
130 | // at the center of the rectangle.
131 | dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2),
132 | e.Y - (dragSize.Height / 2)),
133 | dragSize);
134 | }
135 | else
136 | // Reset the rectangle if the mouse is not over an item in the ListBox.
137 | dragBoxFromMouseDown = Rectangle.Empty;
138 | }
139 |
140 | private void gdvFolderMapping_DragOver(object sender, DragEventArgs e)
141 | {
142 | e.Effect = DragDropEffects.Move;
143 | }
144 |
145 | private void gdvFolderMapping_DragDrop(object sender, DragEventArgs e)
146 | {
147 | // The mouse locations are relative to the screen, so they must be
148 | // converted to client coordinates.
149 | Point clientPoint = gdvFolderMapping.PointToClient(new Point(e.X, e.Y));
150 |
151 | // Get the row index of the item the mouse is below.
152 | rowIndexOfItemUnderMouseToDrop =
153 | gdvFolderMapping.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
154 |
155 | // If the drag operation was a move then remove and insert the row.
156 | if (e.Effect == DragDropEffects.Move)
157 | {
158 | DataGridViewRow rowToMove = e.Data.GetData(
159 | typeof(DataGridViewRow)) as DataGridViewRow;
160 |
161 | if (rowIndexOfItemUnderMouseToDrop == gdvFolderMapping.RowCount - 1)
162 | rowIndexOfItemUnderMouseToDrop--;
163 |
164 | if (rowIndexOfItemUnderMouseToDrop == -1)
165 | rowIndexOfItemUnderMouseToDrop++;
166 |
167 | FolderMapping item = folderMappingBindingList[rowIndexFromMouseDown];
168 | folderMappingBindingList.RemoveAt(rowIndexFromMouseDown);
169 | folderMappingBindingList.Insert(rowIndexOfItemUnderMouseToDrop, item);
170 | }
171 | }
172 |
173 | private void gdvFolderMapping_CellEndEdit(object sender, DataGridViewCellEventArgs e)
174 | {
175 | // Force Valid icon to be refreshed
176 | gdvFolderMapping.Refresh();
177 | }
178 |
179 | private void gdvFolderMapping_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
180 | {
181 | // Prevent Empty Cell from having a red X box
182 | if (gdvFolderMapping.Rows[e.RowIndex].IsNewRow && e.ColumnIndex == 2)
183 | {
184 | e.Value = new Bitmap(1, 1);
185 | }
186 | }
187 |
188 | #endregion
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/frmSettings.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | True
122 |
123 |
124 | True
125 |
126 |
127 | True
128 |
129 |
130 | True
131 |
132 |
133 | True
134 |
135 |
136 | True
137 |
138 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.Addin/source.extension.vsixmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SQL Scripts Explorer Addin.
6 | Collaborate SQL Scripts between teams.
7 |
8 |
9 |
10 | amd64
11 |
12 |
13 | amd64
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/SQLScriptsExplorer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31903.59
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLScriptsExplorer.Addin", "SQLScriptsExplorer.Addin\SQLScriptsExplorer.Addin.csproj", "{194CCEE9-F9B5-4681-A1BE-94B31C112D19}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {194CCEE9-F9B5-4681-A1BE-94B31C112D19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {194CCEE9-F9B5-4681-A1BE-94B31C112D19}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {194CCEE9-F9B5-4681-A1BE-94B31C112D19}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {194CCEE9-F9B5-4681-A1BE-94B31C112D19}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {E1092DDA-C068-4EF0-A77E-F015CB24CCF1}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------