18 |
19 | true
20 | true
21 | false
22 | false
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tablefilter/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) Luis M. Pena All rights reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/test/kotlin/com/github/gitofleonardo/simplesqlitebrowser/MyPluginTest.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser
2 |
3 | import com.intellij.ide.highlighter.XmlFileType
4 | import com.intellij.psi.xml.XmlFile
5 | import com.intellij.testFramework.TestDataPath
6 | import com.intellij.testFramework.fixtures.BasePlatformTestCase
7 | import com.intellij.util.PsiErrorElementUtil
8 |
9 | @TestDataPath("\$CONTENT_ROOT/src/test/testData")
10 | class MyPluginTest : BasePlatformTestCase() {
11 |
12 | fun testXMLFile() {
13 | val psiFile = myFixture.configureByText(XmlFileType.INSTANCE, "bar")
14 | val xmlFile = assertInstanceOf(psiFile, XmlFile::class.java)
15 |
16 | assertFalse(PsiErrorElementUtil.hasErrors(project, xmlFile.virtualFile))
17 |
18 | assertNotNull(xmlFile.rootTag)
19 |
20 | xmlFile.rootTag?.let {
21 | assertEquals("foo", it.name)
22 | assertEquals("bar", it.value.text)
23 | }
24 | }
25 |
26 | override fun getTestDataPath() = "src/test/testData/rename"
27 |
28 | fun testRename() {
29 | myFixture.testRename("foo.xml", "foo_after.xml", "a2")
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/ui/viewmodel/MetadataViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.ui.viewmodel
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.SqliteMetadata
4 | import com.github.gitofleonardo.simplesqlitebrowser.model.SqliteModel
5 | import com.github.gitofleonardo.simplesqlitebrowser.mvvm.LiveData
6 | import com.github.gitofleonardo.simplesqlitebrowser.mvvm.ViewModel
7 | import com.intellij.openapi.vfs.VirtualFile
8 | import io.reactivex.rxjava3.core.Observable
9 | import io.reactivex.rxjava3.schedulers.Schedulers
10 | import javax.swing.SwingUtilities
11 |
12 | class MetadataViewModel : ViewModel {
13 | private val model = SqliteModel
14 |
15 | val metadata: LiveData = LiveData()
16 |
17 | fun loadMetaData(file: VirtualFile) {
18 | Observable
19 | .create { emitter ->
20 | emitter.onNext(model.loadMetaData(file))
21 | }
22 | .subscribeOn(Schedulers.io())
23 | .subscribe {
24 | SwingUtilities.invokeLater {
25 | metadata.value = it
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.run/Run Qodana.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/provider/SqliteEditorProvider.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.provider
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.EXTENSION
4 | import com.github.gitofleonardo.simplesqlitebrowser.SQLITE_LANGUAGE
5 | import com.intellij.openapi.fileEditor.FileEditor
6 | import com.intellij.openapi.fileEditor.FileEditorPolicy
7 | import com.intellij.openapi.fileEditor.FileEditorProvider
8 | import com.intellij.openapi.project.DumbAware
9 | import com.intellij.openapi.project.Project
10 | import com.intellij.openapi.util.Disposer
11 | import com.intellij.openapi.vfs.VirtualFile
12 |
13 | class SqliteEditorProvider : FileEditorProvider, DumbAware {
14 | override fun accept(project: Project, file: VirtualFile): Boolean {
15 | return file.extension == EXTENSION
16 | }
17 |
18 | override fun createEditor(project: Project, file: VirtualFile): FileEditor {
19 | return SqliteEditor(project, file)
20 | }
21 |
22 | override fun getEditorTypeId(): String = SQLITE_LANGUAGE
23 |
24 | override fun getPolicy(): FileEditorPolicy = FileEditorPolicy.HIDE_DEFAULT_EDITOR
25 |
26 | override fun disposeEditor(editor: FileEditor) {
27 | super.disposeEditor(editor)
28 | Disposer.dispose(editor)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/tools/DatabaseTableCellRenderer.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.tools
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.DbRow
4 | import com.github.gitofleonardo.simplesqlitebrowser.model.SqliteModel
5 | import com.github.gitofleonardo.simplesqlitebrowser.toStringOr
6 | import java.awt.Component
7 | import java.sql.Types
8 | import javax.swing.JTable
9 | import javax.swing.table.DefaultTableCellRenderer
10 |
11 | class DatabaseTableCellRenderer : DefaultTableCellRenderer() {
12 | override fun getTableCellRendererComponent(
13 | table: JTable,
14 | value: Any?,
15 | isSelected: Boolean,
16 | hasFocus: Boolean,
17 | row: Int,
18 | column: Int
19 | ): Component {
20 | val newValue: String = when (value) {
21 | null -> {
22 | SqliteModel.NULL
23 | }
24 | is DbRow.RowData -> {
25 | when (value.type) {
26 | Types.BLOB -> {
27 | if (value.data == null) {
28 | SqliteModel.NULL
29 | } else {
30 | SqliteModel.BLOB
31 | }
32 | }
33 | else -> value.data.toStringOr(SqliteModel.NULL)
34 | }
35 | }
36 | else -> {
37 | value.toString()
38 | }
39 | }
40 | return super.getTableCellRendererComponent(table, newValue, isSelected, hasFocus, row, column)
41 | }
42 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # IntelliJ Platform Artifacts Repositories -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
2 |
3 | pluginGroup = com.github.gitofleonardo
4 | pluginName = SimpleSqliteBrowser
5 | # SemVer format -> https://semver.org
6 | pluginVersion = 1.0.8
7 |
8 | # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
9 | pluginSinceBuild = 201
10 | pluginUntilBuild =
11 |
12 | # IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#intellij-extension
13 | platformType = AI
14 | platformVersion = 2023.2.1.1
15 |
16 | # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
17 | # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
18 | platformPlugins =
19 |
20 | # Gradle Releases -> https://github.com/gradle/gradle/releases
21 | gradleVersion = 8.3
22 |
23 | # Opt-out flag for bundling Kotlin standard library -> https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library
24 | # suppress inspection "UnusedProperty"
25 | kotlin.stdlib.default.dependency = false
26 |
27 | # Enable Gradle Configuration Cache -> https://docs.gradle.org/current/userguide/configuration_cache.html
28 | org.gradle.configuration-cache = true
29 |
30 | # Enable Gradle Build Cache -> https://docs.gradle.org/current/userguide/build_cache.html
31 | org.gradle.caching = true
32 |
33 | # Enable Gradle Kotlin DSL Lazy Property Assignment -> https://docs.gradle.org/current/userguide/kotlin_dsl.html#kotdsl:assignment
34 | systemProp.org.gradle.unsafe.kotlin.assignment = true
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/provider/SqliteEditor.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.provider
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.ui.window.SqliteBrowserMainWindow
4 | import com.intellij.openapi.fileEditor.FileEditor
5 | import com.intellij.openapi.fileEditor.FileEditorLocation
6 | import com.intellij.openapi.fileEditor.FileEditorState
7 | import com.intellij.openapi.project.Project
8 | import com.intellij.openapi.util.UserDataHolderBase
9 | import com.intellij.openapi.vfs.VirtualFile
10 | import java.beans.PropertyChangeListener
11 | import javax.swing.JComponent
12 |
13 | private const val NAME = "SqliteEditor"
14 |
15 | class SqliteEditor(private val proj: Project, private val dbFile: VirtualFile) : UserDataHolderBase(), FileEditor {
16 | private val mainWindow by lazy { SqliteBrowserMainWindow(dbFile) }
17 |
18 | override fun dispose() {
19 | }
20 |
21 | override fun getComponent(): JComponent {
22 | return mainWindow
23 | }
24 |
25 | override fun getPreferredFocusedComponent(): JComponent? {
26 | return null
27 | }
28 |
29 | override fun getName(): String = NAME
30 |
31 | override fun setState(state: FileEditorState) {
32 | }
33 |
34 | override fun isModified(): Boolean {
35 | return false
36 | }
37 |
38 | override fun isValid(): Boolean {
39 | return true
40 | }
41 |
42 | override fun addPropertyChangeListener(listener: PropertyChangeListener) {
43 | }
44 |
45 | override fun removePropertyChangeListener(listener: PropertyChangeListener) {
46 | }
47 |
48 | override fun getCurrentLocation(): FileEditorLocation? {
49 | return null
50 | }
51 |
52 | override fun getFile(): VirtualFile {
53 | return dbFile
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/IFilterObserver.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 |
29 | /**
30 | *
A IFilterObserver instance receives notifications when the associated
31 | * {@link IFilter} instance updates the held filter.
32 | *
33 | * @author Luis M Pena - lu@coderazzi.net
34 | */
35 | public interface IFilterObserver {
36 |
37 | /**
38 | *
Notification made by the observer when the associated {@link
39 | * IFilter} instance updates the held filter.
40 | */
41 | void filterUpdated(IFilter obs);
42 | }
43 |
--------------------------------------------------------------------------------
/.github/workflows/run-ui-tests.yml:
--------------------------------------------------------------------------------
1 | # GitHub Actions Workflow for launching UI tests on Linux, Windows, and Mac in the following steps:
2 | # - prepare and launch IDE with your plugin and robot-server plugin, which is needed to interact with UI
3 | # - wait for IDE to start
4 | # - run UI tests with separate Gradle task
5 | #
6 | # Please check https://github.com/JetBrains/intellij-ui-test-robot for information about UI tests with IntelliJ Platform
7 | #
8 | # Workflow is triggered manually.
9 |
10 | name: Run UI Tests
11 | on:
12 | workflow_dispatch
13 |
14 | jobs:
15 |
16 | testUI:
17 | runs-on: ${{ matrix.os }}
18 | strategy:
19 | fail-fast: false
20 | matrix:
21 | include:
22 | - os: ubuntu-latest
23 | runIde: |
24 | export DISPLAY=:99.0
25 | Xvfb -ac :99 -screen 0 1920x1080x16 &
26 | gradle runIdeForUiTests &
27 | - os: windows-latest
28 | runIde: start gradlew.bat runIdeForUiTests
29 | - os: macos-latest
30 | runIde: ./gradlew runIdeForUiTests &
31 |
32 | steps:
33 |
34 | # Check out current repository
35 | - name: Fetch Sources
36 | uses: actions/checkout@v3
37 |
38 | # Setup Java 11 environment for the next steps
39 | - name: Setup Java
40 | uses: actions/setup-java@v3
41 | with:
42 | distribution: zulu
43 | java-version: 11
44 |
45 | # Run IDEA prepared for UI testing
46 | - name: Run IDE
47 | run: ${{ matrix.runIde }}
48 |
49 | # Wait for IDEA to be started
50 | - name: Health Check
51 | uses: jtalk/url-health-check-action@v2
52 | with:
53 | url: http://127.0.0.1:8082
54 | max-attempts: 15
55 | retry-delay: 30s
56 |
57 | # Run tests
58 | - name: Tests
59 | run: ./gradlew test
60 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/AutoChoices.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | /**
29 | * Enumeration to define the available auto choices modes on a table filter or
30 | * on each separated filter editor.
31 | */
32 | public enum AutoChoices {
33 |
34 | /** No auto choices, any choices must be explicitly inserted. */
35 | DISABLED,
36 |
37 | /** Enumerations and booleans automatically handled. */
38 | ENUMS,
39 |
40 | /**
41 | * Choices extracted from the model, it is guaranteed that the choices
42 | * include all the model's values, and only those.
43 | */
44 | ENABLED
45 | }
46 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/TableFilterHeaderBeanInfo.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.beans.BeanDescriptor;
29 | import java.beans.SimpleBeanInfo;
30 |
31 |
32 | public class TableFilterHeaderBeanInfo extends SimpleBeanInfo {
33 |
34 | @Override public BeanDescriptor getBeanDescriptor() {
35 | BeanDescriptor desc = new BeanDescriptor(TableFilterHeader.class);
36 | desc.setValue("isContainer", Boolean.FALSE);
37 |
38 | return desc;
39 | }
40 |
41 | @Override public java.awt.Image getIcon(int iconKind) {
42 | return loadImage(
43 | "/net/coderazzi/filters/resources/tableFilterHeader.png");
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/ChoiceRenderer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.awt.Component;
29 |
30 |
31 | /**
32 | * Interface to customize the rendering of choices in the {@link IFilterEditor}.
33 | */
34 | public interface ChoiceRenderer {
35 |
36 | /**
37 | * Returns the component used to represent the choice (normally, an element
38 | * from the associated table).
39 | * The value can be as well {@link CustomChoice} instances; to use the
40 | * default rendering in this case, the method should return null.
41 | */
42 | Component getRendererComponent(IFilterEditor editor,
43 | Object value,
44 | boolean isSelected);
45 | }
46 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/editor/IChoicesParser.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui.editor;
27 |
28 | /**
29 | * Interface to escape properly choices, so that the IParser handles them
30 | * properly. In special, HTML content must be always removed from the choices.
31 | *
32 | * Starting on version 4.3, the parser is also able to handle html content;
33 | * in this case, the parser accepts simple text, but the created filter can
34 | * be applied to Html content
35 | *
36 | * @author Luis M Pena - lu@coderazzi.net
37 | */
38 | interface IChoicesParser {
39 |
40 | /**
41 | * Escapes a given expression, such that, when parsed, the parser will make
42 | * no character/operator substitutions.
43 | */
44 | String escapeChoice(String s);
45 | }
46 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/HtmlChoiceRenderer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.awt.Component;
29 |
30 | import javax.swing.JLabel;
31 |
32 | /**
33 | * Class to render properly columns having html content.
34 | */
35 | public class HtmlChoiceRenderer extends JLabel implements ChoiceRenderer {
36 |
37 | private static final long serialVersionUID = -825539410560961416L;
38 |
39 | public HtmlChoiceRenderer() {
40 | setOpaque(true);
41 | }
42 |
43 | @Override
44 | public Component getRendererComponent(IFilterEditor editor, Object value,
45 | boolean isSelected) {
46 | setText(value==null? "" : value.toString());
47 | editor.getLook().setupComponent(this, isSelected,
48 | editor.getFilter().isEnabled());
49 | return this;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/NotFilter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import javax.swing.RowFilter;
29 |
30 |
31 | /**
32 | * Composed set of filters, added via logical AND, and then NOT-ed the result.
33 | *
34 | * @author Luis M Pena - lu@coderazzi.net
35 | */
36 | public class NotFilter extends AndFilter {
37 |
38 | /** Default constructor. */
39 | public NotFilter() {
40 | super();
41 | }
42 |
43 | /**
44 | * Constructor built up out of one or more {@link
45 | * IFilter} instances.
46 | */
47 | public NotFilter(IFilter... observables) {
48 | super(observables);
49 | }
50 |
51 | /** @see IFilter#include(Entry) */
52 | @Override public boolean include(Entry rowEntry) {
53 | return !isEnabled() || !super.include(rowEntry);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SimpleSqliteBrowser
2 |
3 | 
4 | [](https://plugins.jetbrains.com/plugin/19797-simplesqlitebrowser)
5 | [](https://plugins.jetbrains.com/plugin/19797-simplesqlitebrowser)
6 |
7 |
8 | A simple plugin that helps you to view your sqlite databases in `Intellij Platform`. It's also good to directly double-click
9 | the database file to open it in your `Android Studio`-`Device File Explorer` without any extra actions.
10 |
11 |
12 | ---
13 |
14 | ## Installation
15 |
16 | - Using IDE built-in plugin system:
17 |
18 | Settings/Preferences > Plugins > Marketplace > Search for "SimpleSqliteBrowser" >
19 | Install Plugin
20 |
21 | - Manually:
22 |
23 | Download the [latest release](https://github.com/gitofleonardo/SimpleSqliteBrowser/releases/latest) and install it manually using
24 | Settings/Preferences > Plugins > ⚙️ > Install plugin from disk...
25 |
26 |
27 | ---
28 |
29 | ## Examples
30 |
31 | |  |  |
32 | |--|--|
33 |
34 | ---
35 |
36 | ## Credits
37 |
38 | + [tablefilter-swing](https://github.com/coderazzi/tablefilter-swing) of [coderazzi](https://github.com/coderazzi), for filtering table column results.
39 |
40 | ## License
41 |
42 | ```
43 | Licensed under the Apache License, Version 2.0 (the "License");
44 | you may not use this file except in compliance with the License.
45 | You may obtain a copy of the License at
46 |
47 | http://www.apache.org/licenses/LICENSE-2.0
48 |
49 | Unless required by applicable law or agreed to in writing, software
50 | distributed under the License is distributed on an "AS IS" BASIS,
51 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52 | See the License for the specific language governing permissions and
53 | limitations under the License.
54 | ```
55 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/AndFilter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import javax.swing.RowFilter;
29 |
30 |
31 | /**
32 | * Composed set of filters, added via logical AND.
33 | *
34 | * @author Luis M Pena - lu@coderazzi.net
35 | */
36 | public class AndFilter extends ComposedFilter {
37 |
38 | /** Default constructor. */
39 | public AndFilter() {
40 | super();
41 | }
42 |
43 | /**
44 | * Constructor built up out of one or more {@link
45 | * IFilter} instances.
46 | */
47 | public AndFilter(IFilter... observables) {
48 | super(observables);
49 | }
50 |
51 | /** @see IFilter#include(Entry) */
52 | @Override public boolean include(Entry rowEntry) {
53 | for (IFilter filter : filters) {
54 | if (filter.isEnabled() && !filter.include(rowEntry)) {
55 | return false;
56 | }
57 | }
58 |
59 | return true;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/IFilter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import javax.swing.RowFilter;
29 |
30 |
31 | /**
32 | *
Interface to be implemented by any instance holding a filter than can be
33 | * updated dynamically.
34 | *
35 | *
Any change on the filter is propagated to the observers, in no given
36 | * order.
37 | *
38 | * @author Luis M Pena - lu@coderazzi.net
39 | */
40 | public interface IFilter {
41 |
42 | /** {@link RowFilter} interface. */
43 | boolean include(RowFilter.Entry rowEntry);
44 |
45 | /** Returns true if the filter is enabled. */
46 | boolean isEnabled();
47 |
48 | /** Enables/Disables the filter. */
49 | void setEnabled(boolean enable);
50 |
51 | /** Adds an observer to receive filter change notifications. */
52 | void addFilterObserver(IFilterObserver observer);
53 |
54 | /**
55 | * Unregisters an observer, that will not receive any further filter update
56 | * notifications.
57 | */
58 | void removeFilterObserver(IFilterObserver observer);
59 | }
60 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/OrFilter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import javax.swing.RowFilter;
29 |
30 |
31 | /**
32 | * Composed set of filters, added via logical OR.
33 | *
34 | * @author Luis M Pena - lu@coderazzi.net
35 | */
36 | public class OrFilter extends ComposedFilter {
37 |
38 | /** Default constructor. */
39 | public OrFilter() {
40 | super();
41 | }
42 |
43 | /**
44 | * Constructor built up out of one or more {@link
45 | * IFilter} instances.
46 | */
47 | public OrFilter(IFilter... observables) {
48 | super(observables);
49 | }
50 |
51 | /** @see IFilter#include(Entry) */
52 | @Override public boolean include(Entry rowEntry) {
53 | boolean ret = true;
54 | for (IFilter filter : filters) {
55 | if (filter.isEnabled()) {
56 | if (filter.include(rowEntry)) {
57 | return true;
58 | }
59 |
60 | ret = false;
61 | }
62 | }
63 |
64 | return ret;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/Extensions.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser
2 |
3 | import com.intellij.openapi.ui.ComboBox
4 | import java.awt.event.*
5 | import javax.swing.JComponent
6 | import javax.swing.text.JTextComponent
7 |
8 | inline fun ComboBox.addOnItemChangeListener(crossinline listener: (T) -> Unit) {
9 | addItemListener {
10 | if (it.stateChange == ItemEvent.SELECTED) {
11 | val item = it.item
12 | if (item is T) {
13 | listener.invoke(item)
14 | }
15 | }
16 | }
17 | }
18 |
19 | fun JTextComponent.addOnKeyEventListener(listener: (KeyEvent) -> Unit) {
20 | addKeyListener(object : KeyListener {
21 | override fun keyTyped(e: KeyEvent?) {
22 | e?.let(listener)
23 | }
24 |
25 | override fun keyPressed(e: KeyEvent?) {
26 | }
27 |
28 | override fun keyReleased(e: KeyEvent?) {
29 | }
30 | })
31 | }
32 |
33 | fun JComponent.addOnClickListener(listener:(MouseEvent) -> Unit) {
34 | addMouseListener(object : MouseListener {
35 | override fun mouseClicked(e: MouseEvent?) {
36 | e?.let(listener)
37 | }
38 |
39 | override fun mousePressed(e: MouseEvent?) {}
40 |
41 | override fun mouseReleased(e: MouseEvent?) {}
42 |
43 | override fun mouseEntered(e: MouseEvent?) {}
44 |
45 | override fun mouseExited(e: MouseEvent?) {}
46 | })
47 | }
48 |
49 | fun JComponent.addOnTouchListener(listener: (MouseEvent) -> Unit) {
50 | addMouseListener(object : MouseListener {
51 | override fun mouseClicked(e: MouseEvent?) {}
52 |
53 | override fun mousePressed(e: MouseEvent?) {
54 | e?.let(listener)
55 | }
56 |
57 | override fun mouseReleased(e: MouseEvent?) {}
58 |
59 | override fun mouseEntered(e: MouseEvent?) {}
60 |
61 | override fun mouseExited(e: MouseEvent?) {}
62 | })
63 | }
64 |
65 | fun Any?.toStringOr(placeHolder: String = ""): String {
66 | return this?.toString() ?: placeHolder
67 | }
68 |
69 | private const val BYTE_SIZE = 1024
70 | private const val K_BYTE_SIZE = 1024 * 1024
71 |
72 | fun ByteArray.toSizeString(): String {
73 | val siz = size
74 | return if (siz <= BYTE_SIZE) {
75 | "$siz Bytes"
76 | } else if (siz <= K_BYTE_SIZE) {
77 | String.format("%.2f KB", siz / BYTE_SIZE.toFloat())
78 | } else{
79 | String.format("%.2f MB", siz / K_BYTE_SIZE.toFloat())
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/ui/window/SqliteMetaDataWindow.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.ui.window
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.SqliteMetadata
4 | import com.github.gitofleonardo.simplesqlitebrowser.tools.DatabaseTreeCellRenderer
5 | import com.github.gitofleonardo.simplesqlitebrowser.tools.DatabaseTreeModel
6 | import com.github.gitofleonardo.simplesqlitebrowser.ui.TabbedChildView
7 | import com.github.gitofleonardo.simplesqlitebrowser.ui.viewmodel.MetadataViewModel
8 | import com.intellij.openapi.vfs.VirtualFile
9 | import com.intellij.ui.components.JBScrollPane
10 | import com.intellij.ui.components.JBTreeTable
11 | import com.intellij.ui.treeStructure.Tree
12 | import java.awt.BorderLayout
13 | import javax.swing.Icon
14 | import javax.swing.JPanel
15 | import javax.swing.JTree
16 | import javax.swing.ScrollPaneConstants
17 |
18 | private const val TITLE = "Database Metadata"
19 |
20 | class SqliteMetaDataWindow(private val file: VirtualFile) : TabbedChildView() {
21 | override val title: String = TITLE
22 | override val icon: Icon? = null
23 |
24 | private val viewModel = MetadataViewModel()
25 | private val emptyMetadata = SqliteMetadata()
26 | private var treeModel: DatabaseTreeModel = DatabaseTreeModel(emptyMetadata)
27 |
28 | // Auto-generated components {@
29 | private lateinit var rootTree: Tree
30 | private lateinit var rootContainer: JPanel
31 | private lateinit var treeScrollContainer: JBScrollPane
32 | // @}
33 |
34 | init {
35 | setupUI()
36 | initObserve()
37 | viewModel.loadMetaData(file)
38 | }
39 |
40 | private fun initObserve() {
41 | viewModel.metadata.observe {
42 | if (!it.isValidSqliteDatabase) {
43 | return@observe
44 | }
45 | treeModel = DatabaseTreeModel(it)
46 | rootTree.model = treeModel
47 | }
48 | }
49 |
50 | // UI Setup {@
51 | private fun setupUI() {
52 | rootContainer = JPanel()
53 | rootContainer.layout = BorderLayout(0, 0)
54 | rootTree = Tree()
55 | rootTree.cellRenderer = DatabaseTreeCellRenderer()
56 | treeScrollContainer = JBScrollPane()
57 | treeScrollContainer.horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
58 | treeScrollContainer.setViewportView(rootTree)
59 | rootContainer.add(treeScrollContainer, BorderLayout.CENTER)
60 |
61 | layout = BorderLayout()
62 | add(rootContainer)
63 | }
64 | // @}
65 | }
66 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/editor/ChoiceMatch.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui.editor;
27 |
28 | import java.util.Comparator;
29 |
30 |
31 | /** Class to find matches in the lists (history / choices). */
32 | class ChoiceMatch {
33 | // exact is true if the given index corresponds to an string that fully
34 | // matches the passed string
35 | boolean exact;
36 | // the matched content
37 | Object content;
38 | // index in the list. Will be -1 if the content is empty or a fullMatch
39 | // is required and cannot be found
40 | int index = -1;
41 | // length of the string that is matched, if exact is false.
42 | int len;
43 |
44 | /** Returns the number of matching characters between two strings. */
45 | public static int getMatchingLength(String a,
46 | String b,
47 | Comparator stringComparator) {
48 | int max = Math.min(a.length(), b.length());
49 | for (int i = 0; i < max; i++) {
50 | char f = a.charAt(i);
51 | char s = b.charAt(i);
52 | if ((f != s)
53 | && (stringComparator.compare(String.valueOf(f),
54 | String.valueOf(s)) != 0)) {
55 | return i;
56 | }
57 | }
58 |
59 | return max;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/tools/DatabaseTreeModel.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.tools
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.DbColumn
4 | import com.github.gitofleonardo.simplesqlitebrowser.data.DbTable
5 | import com.github.gitofleonardo.simplesqlitebrowser.data.SqliteMetadata
6 | import javax.swing.event.TreeModelListener
7 | import javax.swing.tree.DefaultMutableTreeNode
8 | import javax.swing.tree.MutableTreeNode
9 | import javax.swing.tree.TreeModel
10 | import javax.swing.tree.TreeNode
11 | import javax.swing.tree.TreePath
12 |
13 | class DatabaseTreeModel(private val metadata: SqliteMetadata) : TreeModel {
14 | private val root = DefaultMutableTreeNode("Tables")
15 |
16 | init {
17 | for (table in metadata.tables) {
18 | root.add(buildTableNode(table))
19 | }
20 | }
21 |
22 | private fun buildTableNode(table: DbTable): MutableTreeNode {
23 | val tableNode = DefaultMutableTreeNode(table, true)
24 | for (col in table.columns) {
25 | tableNode.add(buildColumnNode(col))
26 | }
27 | return tableNode
28 | }
29 |
30 | private fun buildColumnNode(col: DbColumn): MutableTreeNode {
31 | return DefaultMutableTreeNode(col, false)
32 | }
33 |
34 | override fun getRoot(): Any {
35 | return root
36 | }
37 |
38 | override fun getChild(parent: Any?, index: Int): Any? {
39 | if (parent == null) {
40 | return null
41 | }
42 | if (parent !is MutableTreeNode) {
43 | return null
44 | }
45 | if (index >= parent.childCount) {
46 | return null
47 | }
48 | return parent.getChildAt(index)
49 | }
50 |
51 | override fun getChildCount(parent: Any?): Int {
52 | if (parent == null) {
53 | return 0
54 | }
55 | if (parent !is MutableTreeNode) {
56 | return 0
57 | }
58 | return parent.childCount
59 | }
60 |
61 | override fun isLeaf(node: Any?): Boolean {
62 | if (node == null || node !is DefaultMutableTreeNode) {
63 | return false
64 | }
65 | return node.isLeaf
66 | }
67 |
68 | override fun valueForPathChanged(path: TreePath?, newValue: Any?) {
69 | }
70 |
71 | override fun getIndexOfChild(parent: Any?, child: Any?): Int {
72 | if (parent == null || child == null) {
73 | return -1
74 | }
75 | if (parent !is TreeNode || child !is TreeNode) {
76 | return -1
77 | }
78 | return parent.getIndex(child)
79 | }
80 |
81 | override fun addTreeModelListener(l: TreeModelListener?) {
82 | }
83 |
84 | override fun removeTreeModelListener(l: TreeModelListener?) {
85 | }
86 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/LooseParserModel.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import net.coderazzi.filters.IParser;
29 | import net.coderazzi.filters.parser.DateComparator;
30 | import net.coderazzi.filters.parser.Parser;
31 |
32 | import java.beans.PropertyChangeListener;
33 | import java.beans.PropertyChangeSupport;
34 | import java.text.DateFormat;
35 | import java.text.FieldPosition;
36 | import java.text.Format;
37 | import java.text.ParseException;
38 | import java.text.ParsePosition;
39 | import java.text.SimpleDateFormat;
40 | import java.util.Comparator;
41 | import java.util.Date;
42 | import java.util.HashMap;
43 | import java.util.Map;
44 |
45 |
46 | /**
47 | * Default {@link Format} instances, supporting all the basic java types
48 | * It also includes support for {@link Comparator} of {@link Date} instances.
49 | *
50 | * The default {@link IParser} is automatically configured to use these {@link
51 | * Format} instances, when created by the {@link TableFilterHeader}.
52 | * Users can add any {@link Format} or {@link Comparator} definitions, as the
53 | * class is used as a singleton.
54 | *
55 | * @author Luis M Pena - lu@coderazzi.net
56 | */
57 | public class LooseParserModel extends ParserModel {
58 |
59 | /** Creates the parser as required with the given parameters */
60 | protected IParser createParser(Format fmt, Comparator cmp,
61 | Comparator stringCmp, boolean ignoreCase,
62 | int modelIndex) {
63 | return new Parser(fmt, cmp, stringCmp, ignoreCase, modelIndex){
64 | @Override
65 | protected String getInstantAppliedExpression(String expression) {
66 | return expression;
67 | }
68 |
69 | @Override
70 | public IOperand getDefaultOperator(boolean instantMode) {
71 | return super.getDefaultOperator(true);
72 | }
73 | };
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/IFilterHeaderObserver.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import javax.swing.table.TableColumn;
29 |
30 |
31 | /**
32 | *
A ITableFilterHeaderObserver instance receives notifications when the
33 | * associated {@link IFilterEditor} instances are
34 | * created, destroyed, or update the held filter.
35 | *
36 | * @author Luis M Pena - lu@coderazzi.net
37 | */
38 | public interface IFilterHeaderObserver {
39 |
40 | /**
41 | *
Informs the observer than a new filter editor is created
Notification made by the {@link
65 | * IFilterEditor} when the filter's content is
66 | * updated
67 | *
68 | * @param header the associated table filter header
69 | * @param editor the observable instance
70 | * @param tableColumn the associated {@link TableColumn}
71 | */
72 | void tableFilterUpdated(TableFilterHeader header,
73 | IFilterEditor editor,
74 | TableColumn tableColumn);
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/tools/DatabaseTreeCellRenderer.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.tools
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.DbColumn
4 | import com.github.gitofleonardo.simplesqlitebrowser.data.DbTable
5 | import com.intellij.uiDesigner.core.GridConstraints
6 | import com.intellij.uiDesigner.core.GridLayoutManager
7 | import java.awt.Component
8 | import java.awt.Dimension
9 | import java.awt.Insets
10 | import javax.swing.JLabel
11 | import javax.swing.JPanel
12 | import javax.swing.JTree
13 | import javax.swing.tree.DefaultMutableTreeNode
14 | import javax.swing.tree.TreeCellRenderer
15 |
16 | class DatabaseTreeCellRenderer : TreeCellRenderer {
17 | override fun getTreeCellRendererComponent(
18 | tree: JTree,
19 | value: Any?,
20 | selected: Boolean,
21 | expanded: Boolean,
22 | leaf: Boolean,
23 | row: Int,
24 | hasFocus: Boolean
25 | ): Component {
26 | if (value == null || value !is DefaultMutableTreeNode) {
27 | return JPanel()
28 | }
29 | return when (val data = value.userObject) {
30 | null -> {
31 | JPanel()
32 | }
33 | is DbTable -> {
34 | buildTreeNodeComponent( data.tableName, "", "")
35 | }
36 | is DbColumn -> {
37 | buildTreeNodeComponent(data.name, data.typeName, "\"${data.name}\" ${data.typeName} ${data.schema}")
38 | }
39 | else -> {
40 | buildTreeNodeComponent(data.toString(), "", "")
41 | }
42 | }
43 | }
44 |
45 | // Auto-generated code {@
46 | private fun buildTreeNodeComponent(name: String, type: String, schema: String): Component {
47 | val rootPanel = JPanel()
48 | rootPanel.layout = GridLayoutManager(1, 3, Insets(0, 0, 0, 0), -1, -1, true, false)
49 | rootPanel.minimumSize = Dimension(28, 26)
50 | rootPanel.preferredSize = Dimension(28, 26)
51 | val nameLabel = JLabel()
52 | nameLabel.text = name
53 | rootPanel.add(nameLabel, GridConstraints(0, 0, 1, 1,
54 | GridConstraints.ANCHOR_WEST, GridConstraints.FILL_VERTICAL,
55 | GridConstraints.SIZEPOLICY_CAN_SHRINK or GridConstraints.SIZEPOLICY_CAN_GROW,
56 | GridConstraints.SIZEPOLICY_CAN_SHRINK or GridConstraints.SIZEPOLICY_CAN_GROW,
57 | null, null, null, 0, false))
58 | val typeLabel = JLabel()
59 | typeLabel.text = type
60 | rootPanel.add(typeLabel, GridConstraints(0, 1, 1, 1,
61 | GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
62 | GridConstraints.SIZEPOLICY_CAN_SHRINK or GridConstraints.SIZEPOLICY_WANT_GROW,
63 | GridConstraints.SIZEPOLICY_CAN_SHRINK or GridConstraints.SIZEPOLICY_CAN_GROW,
64 | null, null, null, 0, false))
65 | val schemaLabel = JLabel()
66 | schemaLabel.text = schema
67 | rootPanel.add(schemaLabel, GridConstraints(0, 2, 1, 1,
68 | GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED,
69 | GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false))
70 | return rootPanel
71 | }
72 | // @}
73 | }
74 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/Filter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import java.util.ArrayList;
29 | import java.util.HashSet;
30 | import java.util.Set;
31 |
32 | import javax.swing.RowFilter;
33 |
34 |
35 | /**
36 | * Commodity class implementing the interface {@link
37 | * IFilter} on a {@link RowFilter}.
38 | *
39 | * @author Luis M Pena - lu@coderazzi.net
40 | */
41 | abstract public class Filter extends RowFilter implements IFilter {
42 |
43 | /** The set of currently subscribed observers. */
44 | private Set observers = new HashSet();
45 |
46 | /** The enabled state. */
47 | private boolean enabled = true;
48 |
49 | /** @see IFilter#isEnabled() */
50 | @Override public boolean isEnabled() {
51 | return enabled;
52 | }
53 |
54 | /** @see IFilter#setEnabled(boolean) */
55 | @Override public void setEnabled(boolean enable) {
56 | if (enable != this.enabled) {
57 | this.enabled = enable;
58 | reportFilterUpdatedToObservers();
59 | }
60 | }
61 |
62 | /** @see IFilter#addFilterObserver(IFilterObserver) */
63 | @Override public void addFilterObserver(IFilterObserver observer) {
64 | observers.add(observer);
65 | }
66 |
67 | /** @see IFilter#removeFilterObserver(IFilterObserver) */
68 | @Override public void removeFilterObserver(IFilterObserver observer) {
69 | observers.remove(observer);
70 | }
71 |
72 | /** Returns all the registered {@link IFilterObserver} instances. */
73 | public Set getFilterObservers() {
74 | return new HashSet(observers);
75 | }
76 |
77 | /**
78 | * Method to be called by subclasses to report to the observers that the
79 | * filter has changed.
80 | */
81 | public void reportFilterUpdatedToObservers() {
82 | for (IFilterObserver obs : new ArrayList(observers)) {
83 | obs.filterUpdated(this);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # GitHub Actions Workflow created for handling the release process based on the draft release prepared
2 | # with the Build workflow. Running the publishPlugin task requires the PUBLISH_TOKEN secret provided.
3 |
4 | name: Release
5 | on:
6 | release:
7 | types: [prereleased, released]
8 |
9 | jobs:
10 |
11 | # Prepare and publish the plugin to the Marketplace repository
12 | release:
13 | name: Publish Plugin
14 | runs-on: ubuntu-latest
15 | permissions:
16 | contents: write
17 | pull-requests: write
18 | steps:
19 |
20 | # Check out current repository
21 | - name: Fetch Sources
22 | uses: actions/checkout@v3
23 | with:
24 | ref: ${{ github.event.release.tag_name }}
25 |
26 | # Setup Java 11 environment for the next steps
27 | - name: Setup Java
28 | uses: actions/setup-java@v3
29 | with:
30 | distribution: zulu
31 | java-version: 11
32 |
33 | # Set environment variables
34 | - name: Export Properties
35 | id: properties
36 | shell: bash
37 | run: |
38 | CHANGELOG="$(cat << 'EOM' | sed -e 's/^[[:space:]]*$//g' -e '/./,$!d'
39 | ${{ github.event.release.body }}
40 | EOM
41 | )"
42 |
43 | CHANGELOG="${CHANGELOG//'%'/'%25'}"
44 | CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
45 | CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
46 |
47 | echo "::set-output name=changelog::$CHANGELOG"
48 |
49 | # Update Unreleased section with the current release note
50 | - name: Patch Changelog
51 | if: ${{ steps.properties.outputs.changelog != '' }}
52 | env:
53 | CHANGELOG: ${{ steps.properties.outputs.changelog }}
54 | run: |
55 | ./gradlew patchChangelog --release-note="$CHANGELOG"
56 |
57 | # Publish the plugin to the Marketplace
58 | - name: Publish Plugin
59 | env:
60 | PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
61 | CERTIFICATE_CHAIN: ${{ secrets.CERTIFICATE_CHAIN }}
62 | PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
63 | PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}
64 | run: ./gradlew publishPlugin
65 |
66 | # Upload artifact as a release asset
67 | - name: Upload Release Asset
68 | env:
69 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
70 | run: gh release upload ${{ github.event.release.tag_name }} ./build/distributions/*
71 |
72 | # Create pull request
73 | - name: Create Pull Request
74 | if: ${{ steps.properties.outputs.changelog != '' }}
75 | env:
76 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77 | run: |
78 | VERSION="${{ github.event.release.tag_name }}"
79 | BRANCH="changelog-update-$VERSION"
80 |
81 | git config user.email "action@github.com"
82 | git config user.name "GitHub Action"
83 |
84 | git checkout -b $BRANCH
85 | git commit -am "Changelog update - $VERSION"
86 | git push --set-upstream origin $BRANCH
87 |
88 | gh pr create \
89 | --title "Changelog update - \`$VERSION\`" \
90 | --body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$VERSION\` version." \
91 | --base main \
92 | --head $BRANCH
93 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/ui/viewmodel/TableViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.ui.viewmodel
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.DbTableInstance
4 | import com.github.gitofleonardo.simplesqlitebrowser.model.SqliteModel
5 | import com.github.gitofleonardo.simplesqlitebrowser.mvvm.LiveData
6 | import com.github.gitofleonardo.simplesqlitebrowser.mvvm.ViewModel
7 | import com.intellij.openapi.vfs.VirtualFile
8 | import io.reactivex.rxjava3.core.Observable
9 | import io.reactivex.rxjava3.schedulers.Schedulers
10 | import javax.swing.SwingUtilities
11 | import kotlin.math.ceil
12 |
13 | private const val DEFAULT_PGE_COUNT = 50
14 |
15 | class TableViewModel(private val dbFile: VirtualFile) : ViewModel {
16 | private val model = SqliteModel
17 | var currentPage: Int = 1
18 | var pageCount: Int = DEFAULT_PGE_COUNT
19 | var currentTableName: String? = null
20 | var totalPages: Int = 1
21 | var totalCount: Int = 0
22 |
23 | val tables = LiveData>()
24 | val tableData = LiveData()
25 |
26 | fun resetTableData() {
27 | currentTableName?.let { resetTableData(it) }
28 | }
29 |
30 | fun resetTableData(tableName: String) {
31 | currentPage = 1
32 | currentTableName = tableName
33 | loadTableData(dbFile, tableName, pageCount, currentPage)
34 | }
35 |
36 | fun loadNextPage() {
37 | currentTableName?.let {
38 | if (currentPage < totalPages) {
39 | ++currentPage
40 | loadTableData(dbFile, it, pageCount, currentPage)
41 | }
42 | }
43 | }
44 |
45 | fun loadPreviousPage() {
46 | currentTableName?.let {
47 | if (currentPage > 1) {
48 | --currentPage
49 | loadTableData(dbFile, it, pageCount, currentPage)
50 | }
51 | }
52 | }
53 |
54 | fun loadPage(page: Int) {
55 | if (page < 1 || page > totalPages) {
56 | return
57 | }
58 | currentTableName?.let {
59 | currentPage = page
60 | loadTableData(dbFile, it, pageCount, currentPage)
61 | }
62 | }
63 |
64 | fun loadFirstPage() {
65 | loadPage(1)
66 | }
67 |
68 | fun loadLastPage() {
69 | loadPage(totalPages)
70 | }
71 |
72 | private fun loadTableData(file: VirtualFile, tableName: String, pageCount: Int, page: Int) {
73 | Observable
74 | .create { emitter ->
75 | emitter.onNext(model.loadTableData(file, tableName, pageCount, page))
76 | }
77 | .subscribeOn(Schedulers.io())
78 | .subscribe { result ->
79 | SwingUtilities.invokeLater {
80 | totalCount = result.totalCount
81 | totalPages = ceil(totalCount.toFloat() / pageCount).toInt()
82 | tableData.value = result
83 | }
84 | }
85 |
86 | }
87 |
88 | fun loadTables() {
89 | Observable
90 | .create { emitter->
91 | emitter.onNext(model.loadTables(dbFile))
92 | }
93 | .subscribeOn(Schedulers.io())
94 | .subscribe { tbls ->
95 | SwingUtilities.invokeLater {
96 | tables.value = tbls
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/IParserModel.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.beans.PropertyChangeListener;
29 |
30 | import java.text.Format;
31 |
32 | import java.util.Comparator;
33 |
34 | import net.coderazzi.filters.IParser;
35 |
36 |
37 | /**
38 | * Interface defining the model required to use and create {@link IParser}
39 | * instances.
40 | *
41 | * @author Luis M Pena - lu@coderazzi.net
42 | */
43 | public interface IParserModel {
44 |
45 | /** Property fired when the ignore case value changes. */
46 | String IGNORE_CASE_PROPERTY = "ignoreCase";
47 |
48 | /** Property fired when any class' comparator changes. */
49 | String COMPARATOR_PROPERTY = "comparator";
50 |
51 | /** Property fired when any class' format changes. */
52 | String FORMAT_PROPERTY = "format";
53 |
54 | /** Creates a text parser for the given editor. */
55 | IParser createParser(IFilterEditor editor);
56 |
57 | /** Returns the {@link Format} for the given class. */
58 | Format getFormat(Class c);
59 |
60 | /** Defines the {@link Format} for the given class. */
61 | void setFormat(Class c, Format format);
62 |
63 | /**
64 | * Returns the {@link Comparator} for the given class.
65 | * It never returns null.
66 | */
67 | Comparator getComparator(Class c);
68 |
69 | /** Defines the {@link Comparator} for the given class. */
70 | void setComparator(Class c, Comparator format);
71 |
72 | /** Returns the {@link Comparator} used for String comparisons. */
73 | Comparator getStringComparator(boolean ignoreCase);
74 |
75 | /** Sets a String comparator that is case sensitive/insensitive. */
76 | void setIgnoreCase(boolean set);
77 |
78 | /**
79 | * Returns true if the String comparator ignores case
80 | * Note that this is redundant information, which can be retrieved from the
81 | * {@link #getComparator(Class)} method with a String.class parameter.
82 | */
83 | boolean isIgnoreCase();
84 |
85 | /**
86 | * Adds a {@link PropertyChangeListener}.
87 | * Any property change will be transmitted as an event
88 | */
89 | void addPropertyChangeListener(PropertyChangeListener listener);
90 |
91 | /** Removes an existing {@link PropertyChangeListener}. */
92 | void removePropertyChangeListener(PropertyChangeListener listener);
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/IParser.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import java.text.ParseException;
29 |
30 | import javax.swing.RowFilter;
31 |
32 | import net.coderazzi.filters.gui.IFilterEditor;
33 |
34 |
35 | /**
36 | * Interface defining the requirements on text parsing for filter expressions.
37 | *
38 | * Starting on version 4.3, the parser is also able to handle html content;
39 | * in this case, the parser accepts simple text, but the created filter can
40 | * be applied to Html content
41 | *
42 | * @author Luis M Pena - lu@coderazzi.net
43 | */
44 | public interface IParser {
45 |
46 | /**
47 | * Parses the text, returning a filter that can be applied to the table.
48 | *
49 | * @param expression the text to parse
50 | */
51 | RowFilter parseText(String expression) throws ParseException;
52 |
53 | /**
54 | * Parses the text, considered to be a part of the whole text to enter.
55 | *
56 | *
The behaviour of this method is implementation specific; the default
57 | * implementation considers the expression to be the beginning of the
58 | * expected final string
59 | *
60 | *
This method is invoked when the user inputs text on a filter editor,
61 | * if instant parsing is enabled, and if the text entered so far does not
62 | * match any table's row value for the associated column.
63 | *
64 | *
Alternative implementations that would consider matching the provided
65 | * expression to any substring ('contain' meaning), should set the
66 | * autoCompletion flag in the {@link IFilterEditor}to false
67 | *
68 | * @param expression the text to parse
69 | *
70 | * @return the filter plus the real expression used to create the filter
71 | */
72 | InstantFilter parseInstantText(String expression) throws ParseException;
73 |
74 | /**
75 | * Escapes a given expression, such that, when parsed, the parser will make
76 | * no character/operator substitutions.
77 | */
78 | String escape(String s);
79 |
80 | /**
81 | * Removes any Html content from the passed string, converting special
82 | * Html characters to Java characters.
83 | */
84 | String stripHtml(String s);
85 |
86 | /** Helper class used on {@link IParser#parseInstantText(String)}. */
87 | public class InstantFilter {
88 | public RowFilter filter;
89 | public String expression;
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/editor/FilterArrowButton.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui.editor;
27 |
28 | import java.awt.Dimension;
29 | import java.awt.Graphics;
30 | import java.awt.Graphics2D;
31 | import java.awt.RenderingHints;
32 |
33 | import javax.swing.JButton;
34 |
35 | import net.coderazzi.filters.gui.Look;
36 |
37 |
38 | /** Custom implementation of the arrow used to display the popup menu. */
39 | final class FilterArrowButton extends JButton {
40 | private static final long serialVersionUID = -777416843479142582L;
41 | private final static int MIN_X = 6;
42 | private final static int MIN_Y = 6;
43 | private final static int FILL_X[] = { 0, 3, 6 };
44 | private final static int FILL_Y[] = { 0, 5, 0 };
45 |
46 | private boolean focus;
47 | private Look look;
48 |
49 | public void setLook(Look look) {
50 | this.look = look;
51 | repaint();
52 | }
53 |
54 | public Look getLook() {
55 | return look;
56 | }
57 |
58 | public void setFocused(boolean focus) {
59 | this.focus = focus;
60 | repaint();
61 | }
62 |
63 |
64 | @Override public void paint(Graphics g) {
65 | ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
66 | RenderingHints.VALUE_ANTIALIAS_ON);
67 |
68 | int height = getHeight();
69 | int width = getWidth();
70 |
71 | if (isEnabled()) {
72 | g.setColor(focus ? look.getSelectionBackground()
73 | : look.getBackground());
74 | } else {
75 | g.setColor(look.getDisabledBackground());
76 | }
77 |
78 | g.fillRect(0, 0, width, height);
79 |
80 | width = (width - MIN_X) / 2;
81 | height = Math.min(height / 2, height - MIN_Y);
82 | g.translate(width, height);
83 |
84 | if (isEnabled()) {
85 | g.setColor(focus ? look.getSelectionForeground()
86 | : look.getForeground());
87 | } else {
88 | g.setColor(look.getDisabledForeground());
89 | }
90 |
91 | g.fillPolygon(FILL_X, FILL_Y, FILL_X.length);
92 | }
93 |
94 | @Override protected void paintBorder(Graphics g) {
95 | super.paintBorder(g);
96 | }
97 |
98 | @Override public boolean isFocusable() {
99 | return false;
100 | }
101 |
102 | @Override public Dimension getPreferredSize() {
103 | return new Dimension(12, 12);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/parser/HtmlHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.parser;
27 |
28 | /**
29 | * Class to handle HTML content, required to remove HTML tags and to convert
30 | * HTML special characters (like &) to Java characters
31 | */
32 | class HtmlHandler {
33 |
34 | private StringBuffer buffer = new StringBuffer();
35 |
36 | /**
37 | * Converts an String to the corresponding string without HTML
38 | * information.
39 | */
40 | public String stripHtml(String s) {
41 | String inner = getSubstringUnderHtmlTag(s);
42 | return (inner == null ? s : removeHtmlInfo(inner)).trim();
43 | }
44 |
45 | /**
46 | * Removes any tag and converts special HTML characters to Java chars.
47 | */
48 | private String removeHtmlInfo(String inner) {
49 | boolean inTag = false, inQuoteInTag = false;
50 | char quoteChar = '"';
51 | int entityPos = -1;
52 |
53 | buffer.delete(0, buffer.length());
54 | for (char c : inner.toCharArray()) {
55 | if (c == '<') {
56 | inTag = true;
57 | entityPos = -1;
58 | } else if (c == '>') {
59 | // not anymore tag, unless is inside a quote
60 | inTag = inTag && inQuoteInTag;
61 | } else if (inTag) {
62 | // special attention to "' characters
63 | if (c == '"' || c == '\'') {
64 | if (inQuoteInTag) {
65 | inQuoteInTag = (quoteChar != c);
66 | } else {
67 | inQuoteInTag = true;
68 | quoteChar = c;
69 | }
70 | }
71 | } else {
72 | if (c == '&') {
73 | entityPos = buffer.length();
74 | } else if (c == ';' && entityPos != -1) {
75 | int len = buffer.length();
76 | if (len > entityPos + 2) {
77 | int entityValue = getEntityValue(entityPos + 1);
78 | if (entityValue > 0 && entityValue < 65536) {
79 | buffer.delete(entityPos, len);
80 | c = (char) entityValue;
81 | }
82 | }
83 | }
84 | buffer.append(c);
85 | }
86 | }
87 | return buffer.toString();
88 | }
89 |
90 | /**
91 | * Returns the integer associated to the entity stored in the StringBuffer,
92 | * starting at the passed position (until the end of the buffer).
93 | * @return -1 if it is not a valid html entity
94 | */
95 | private int getEntityValue(int start) {
96 | if (buffer.charAt(start) == '#') {
97 | char hex = buffer.charAt(start);
98 | try {
99 | if (hex == 'x' || hex == 'X') {
100 | return Integer.valueOf(buffer.substring(start + 2), 16);
101 | }
102 | return Integer.valueOf(buffer.substring(start + 1));
103 | } catch (NumberFormatException nfe) {
104 | return -1;
105 | }
106 | }
107 | return HtmlEntities.getEntityValue(buffer.substring(start));
108 | }
109 |
110 | /**
111 | * Removes the external tags, if existing.
112 | * It returns the string contained inside the tags, or null if the tags
113 | * are not present
114 | */
115 | private String getSubstringUnderHtmlTag(String s) {
116 | int l = s.length();
117 | if (l >= 6 && (s.charAt(0) == '<') && (s.charAt(5) == '>')
118 | && (s.charAt(1) == 'h' || s.charAt(1) == 'H')
119 | && (s.charAt(2) == 't' || s.charAt(2) == 'T')
120 | && (s.charAt(3) == 'm' || s.charAt(3) == 'M')
121 | && (s.charAt(4) == 'l' || s.charAt(4) == 'L')
122 | && (s.charAt(0) == '<')) {
123 | // it is enough if the string starts with , ending not
124 | // important
125 | if (l >= 13 && (s.charAt(l - 1) == '>') && (s.charAt(l - 7) == '<')
126 | && (s.charAt(l - 6) == '/')
127 | && (s.charAt(l - 5) == 'h' || s.charAt(l - 5) == 'H')
128 | && (s.charAt(l - 4) == 't' || s.charAt(l - 4) == 'T')
129 | && (s.charAt(l - 3) == 'm' || s.charAt(l - 3) == 'M')
130 | && (s.charAt(l - 2) == 'l' || s.charAt(l - 2) == 'L')) {
131 | l -= 7;
132 | }
133 | return s.substring(6, l);
134 | }
135 | return null;
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/CustomChoiceDecorator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.awt.Color;
29 | import java.awt.Font;
30 | import java.awt.Graphics;
31 |
32 | import javax.swing.JComponent;
33 |
34 |
35 | /**
36 | * Interface that allows customizing the appearance of CustomChoices in those
37 | * {@link IFilterEditor}s without associated {@link ChoiceRenderer}.
38 | */
39 | public interface CustomChoiceDecorator {
40 |
41 | /** Returns the background color. */
42 | Color getBackground(CustomChoice choice,
43 | IFilterEditor editor,
44 | boolean isSelected);
45 |
46 | /** Returns the foreground color. */
47 | Color getForeground(CustomChoice choice,
48 | IFilterEditor editor,
49 | boolean isSelected);
50 |
51 | /** Returns the font. */
52 | Font getFont(CustomChoice choice, IFilterEditor editor, boolean isSelected);
53 |
54 | /** Decorates the choice on the given editor. */
55 | void decorateComponent(CustomChoice choice,
56 | IFilterEditor editor,
57 | boolean isSelected,
58 | JComponent c,
59 | Graphics g);
60 |
61 | /**
62 | * Default decorator, delegating always to the associated methods on the
63 | * {@link CustomChoice} instances. The font, by default, will be cursive
64 | */
65 | public class DefaultDecorator implements CustomChoiceDecorator {
66 |
67 | private Font baseFont;
68 | private Font italicFont;
69 |
70 | @Override public void decorateComponent(CustomChoice choice,
71 | IFilterEditor editor,
72 | boolean isSelected,
73 | JComponent c,
74 | Graphics g) {
75 | choice.decorateComponent(editor, isSelected, c, g);
76 | }
77 |
78 | @Override public Font getFont(CustomChoice choice,
79 | IFilterEditor editor,
80 | boolean isSelected) {
81 | Font ret = choice.getFont(editor, isSelected);
82 | if (ret == null) {
83 | ret = editor.getLook().getFont();
84 | if (ret != baseFont) {
85 | baseFont = ret;
86 | italicFont = baseFont.deriveFont(Font.ITALIC);
87 | }
88 |
89 | ret = italicFont;
90 | }
91 |
92 | return ret;
93 | }
94 |
95 | @Override public Color getBackground(CustomChoice choice,
96 | IFilterEditor editor,
97 | boolean isSelected) {
98 | Color color = choice.getBackground(editor, isSelected);
99 | if (color == null) {
100 | Look look = editor.getLook();
101 | color = isSelected ? look.getSelectionBackground()
102 | : look.getBackground();
103 | }
104 | return color;
105 | }
106 |
107 | @Override public Color getForeground(CustomChoice choice,
108 | IFilterEditor editor,
109 | boolean isSelected) {
110 | Color color = choice.getForeground(editor, isSelected);
111 | if (color == null) {
112 | Look look = editor.getLook();
113 | color = isSelected ? look.getSelectionForeground()
114 | : look.getForeground();
115 | }
116 | return color;
117 | }
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/ComposedFilter.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters;
27 |
28 | import java.util.HashSet;
29 | import java.util.Set;
30 |
31 |
32 | /**
33 | *
Abstract parent class to support the composition of multiple filters.
34 | *
35 | *
The exact composition semantics (and / or / not) are not defined.
36 | *
37 | * @author Luis M Pena - lu@coderazzi.net
38 | */
39 | abstract public class ComposedFilter extends Filter implements IFilterObserver {
40 |
41 | /** Set of associated IFilters. */
42 | protected Set filters;
43 |
44 | /** disabled filters. */
45 | private Set disabledFilters = new HashSet();
46 |
47 | /** Default constructor. */
48 | protected ComposedFilter() {
49 | filters = new HashSet();
50 | }
51 |
52 | /**
53 | * Constructor built up out of one or more {@link
54 | * IFilter} instances.
55 | */
56 | protected ComposedFilter(IFilter... observables) {
57 | this();
58 | addFilter(observables);
59 | }
60 |
61 | /**
62 | * Subscribes one or more {@link IFilter} instances to
63 | * receive filter events from this composition filter.
64 | */
65 | public void addFilter(IFilter... filtersToAdd) {
66 | for (IFilter filter : filtersToAdd) {
67 | if (filters.add(filter)) {
68 | filter.addFilterObserver(this);
69 | if (filter.isEnabled()) {
70 | super.setEnabled(true);
71 | } else {
72 | disabledFilters.add(filter);
73 | }
74 | }
75 | }
76 | }
77 |
78 | /**
79 | * Unsubscribes one or more {@link IFilter}s that were
80 | * previously subscribed to receive filter events.
81 | */
82 | public void removeFilter(IFilter... filtersToRemove) {
83 | boolean report = false;
84 | for (IFilter filter : filtersToRemove) {
85 | if (filters.remove(filter)) {
86 | filter.removeFilterObserver(this);
87 | disabledFilters.remove(filter);
88 | report = true;
89 | }
90 | }
91 |
92 | if (report) {
93 | if (isEnabled() && !filters.isEmpty()
94 | && (disabledFilters.size() == filters.size())) {
95 | super.setEnabled(false);
96 | } else {
97 | reportFilterUpdatedToObservers();
98 | }
99 | }
100 | }
101 |
102 | /**
103 | * Returns all {@link IFilter} instances previously
104 | * added.
105 | */
106 | public Set getFilters() {
107 | return new HashSet(filters);
108 | }
109 |
110 | /** @see IFilterObserver#filterUpdated(IFilter) */
111 | @Override public void filterUpdated(IFilter filter) {
112 | boolean enabled = isEnabled();
113 | boolean changeState = false;
114 | if (filter.isEnabled()) {
115 | changeState = disabledFilters.remove(filter) && !enabled;
116 | } else {
117 | changeState = disabledFilters.add(filter)
118 | && (disabledFilters.size() == filters.size());
119 | }
120 |
121 | if (changeState) {
122 | super.setEnabled(!enabled);
123 | } else {
124 | reportFilterUpdatedToObservers();
125 | }
126 | }
127 |
128 | /** @see IFilter#setEnabled(boolean) */
129 | @Override public void setEnabled(boolean enable) {
130 | if (filters.isEmpty()) {
131 | super.setEnabled(enable);
132 | } else {
133 | // perhaps some filter will not honor the request
134 | // super.setEnabled is now only call when the filters report
135 | // its update
136 | for (IFilter filter : filters) {
137 | filter.setEnabled(enable);
138 | }
139 | }
140 | }
141 |
142 | /** Returns true if there is information of this filter as disabled. */
143 | protected boolean isDisabled(IFilter filter) {
144 | return disabledFilters.contains(filter);
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/Look.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.awt.Color;
29 | import java.awt.Component;
30 | import java.awt.Font;
31 |
32 |
33 | /** Class representing the current {@link TableFilterHeader} appearance. */
34 | public class Look {
35 | Color background;
36 | Color disabledBackground;
37 | Color disabledForeground;
38 | Color errorForeground;
39 | Color foreground;
40 | Color gridColor;
41 | Color selectionBackground;
42 | Color selectionForeground;
43 | Color textSelection;
44 | Color warningForeground;
45 | Font font;
46 | int maxVisiblePopupRows = FilterSettings.maxVisiblePopupRows;
47 | CustomChoiceDecorator customChoiceDecorator = FilterSettings
48 | .newCustomChoiceDecorator();
49 |
50 | /** Returns the background color used by the editors. */
51 | public Color getBackground() {
52 | return background;
53 | }
54 |
55 | /** Returns the registered {@link CustomChoiceDecorator}. */
56 | public CustomChoiceDecorator getCustomChoiceDecorator() {
57 | return customChoiceDecorator;
58 | }
59 |
60 | /** Returns the background color used for disabled editors. */
61 | public Color getDisabledBackground() {
62 | return disabledBackground;
63 | }
64 |
65 | /** Returns the foreground color used for disabled editors. */
66 | public Color getDisabledForeground() {
67 | return disabledForeground;
68 | }
69 |
70 | /**
71 | * Returns the color set by default as foreground on each text editor
72 | * when the user commits any error on the filter expression.
73 | */
74 | public Color getErrorForeground() {
75 | return errorForeground;
76 | }
77 |
78 | /** Returns the font used on editors. */
79 | public Font getFont() {
80 | return font;
81 | }
82 |
83 | /** Returns the foreground color used by the editors. */
84 | public Color getForeground() {
85 | return foreground;
86 | }
87 |
88 | /** Returns the color set by default for the header's grid. */
89 | public Color getGridColor() {
90 | return gridColor;
91 | }
92 |
93 | /** Returns the maximum number of visible rows in the popup menu. */
94 | public int getMaxVisiblePopupRows() {
95 | return maxVisiblePopupRows;
96 | }
97 |
98 | /** Returns the background color on focused editors. */
99 | public Color getSelectionBackground() {
100 | return selectionBackground;
101 | }
102 |
103 | /** Returns the foreground color on focused editors. */
104 | public Color getSelectionForeground() {
105 | return selectionForeground;
106 | }
107 |
108 | /** Returns the color set by default as text selection on filters. */
109 | public Color getTextSelection() {
110 | return textSelection;
111 | }
112 |
113 | /**
114 | *
Returns the color set by default as foreground on each text editor
115 | * when the filter would produce no visible rows
116 | */
117 | public Color getWarningForeground() {
118 | return warningForeground;
119 | }
120 |
121 | /**
122 | * Prepares the provided component to have the expected appearance
123 | * Only the background, foreground and font are updated.
124 | */
125 | public void setupComponent(Component c,
126 | boolean isSelected,
127 | boolean isEnabled) {
128 | Color bg;
129 | Color fg;
130 | if (isEnabled) {
131 | if (isSelected) {
132 | bg = getSelectionBackground();
133 | fg = getSelectionForeground();
134 | } else {
135 | bg = getBackground();
136 | fg = getForeground();
137 | }
138 | } else {
139 | bg = getDisabledBackground();
140 | fg = getDisabledForeground();
141 | }
142 |
143 | if (bg != c.getBackground()) {
144 | c.setBackground(bg);
145 | }
146 |
147 | if (fg != c.getForeground()) {
148 | c.setForeground(fg);
149 | }
150 |
151 | if (c.getFont() != getFont()) {
152 | c.setFont(getFont());
153 | }
154 | }
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/src/main/kotlin/com/github/gitofleonardo/simplesqlitebrowser/model/SqliteModel.kt:
--------------------------------------------------------------------------------
1 | package com.github.gitofleonardo.simplesqlitebrowser.model
2 |
3 | import com.github.gitofleonardo.simplesqlitebrowser.data.*
4 | import com.intellij.openapi.vfs.VirtualFile
5 | import java.sql.ResultSet
6 | import java.sql.Types
7 |
8 | object SqliteModel {
9 | const val NULL = "null"
10 | const val BLOB = "BLOB"
11 |
12 | fun loadMetaData(file: VirtualFile) : SqliteMetadata {
13 | val connection = ConnectionManager.createConnection(file)
14 | val metadata = SqliteMetadata()
15 | connection?.let {
16 | val md = it.metaData
17 | metadata.isValidSqliteDatabase = true
18 | metadata.version = md.databaseMajorVersion
19 | metadata.driverVersion = md.driverVersion
20 |
21 | val tables = ArrayList()
22 | val tableResult = md.getTables(null, null, "%", null)
23 | while (tableResult.next()) {
24 | val tb = DbTable()
25 | tb.tableName = tableResult.getString("TABLE_NAME")
26 | val tableType = tableResult.getString("TABLE_TYPE")
27 | if ("TABLE" != tableType) {
28 | continue
29 | }
30 | val columnResult = md.getColumns(null, null, tb.tableName, null)
31 | while (columnResult.next()) {
32 | val columnName = columnResult.getString("COLUMN_NAME")
33 | val type = columnResult.getInt("DATA_TYPE")
34 | val typeName = columnResult.getString("TYPE_NAME")
35 | val schema = getAllSchema(columnResult)
36 | tb.columns.add(DbColumn(columnName, type, typeName, schema))
37 | }
38 | tables.add(tb)
39 | }
40 | metadata.tables.addAll(tables)
41 | }
42 | ConnectionManager.disposeConnection(connection)
43 | return metadata
44 | }
45 |
46 | fun loadTables(file: VirtualFile) : List {
47 | val connection = ConnectionManager.createConnection(file)
48 | val result = mutableListOf()
49 | connection?.let {
50 | val resultSet = it.metaData.getTables(null, null, "%", null)
51 | while (resultSet.next()) {
52 | val table = resultSet.getString("TABLE_NAME")
53 | val type = resultSet.getString("TABLE_TYPE")
54 | if ("TABLE" == type) {
55 | result.add(table)
56 | }
57 | }
58 | }
59 | ConnectionManager.disposeConnection(connection)
60 | return result
61 | }
62 |
63 | fun loadTableData(file: VirtualFile, tableName: String, pageCount: Int, page: Int) : DbTableInstance {
64 | val columns = mutableListOf()
65 | val rows = mutableListOf()
66 | var totalCount = 0
67 | val connection = ConnectionManager.createConnection(file)
68 | connection?.let {
69 | val columnResult = it.metaData.getColumns(null, null, tableName, null)
70 | while (columnResult.next()) {
71 | val columnName = columnResult.getString("COLUMN_NAME")
72 | val type = columnResult.getInt("DATA_TYPE")
73 | val typeName = columnResult.getString("TYPE_NAME")
74 | val schema = getAllSchema(columnResult)
75 | columns.add(DbColumn(columnName, type, typeName, schema))
76 | }
77 |
78 | val statement = it.createStatement()
79 | val rowResult = statement.executeQuery("SELECT * FROM \"$tableName\" LIMIT $pageCount OFFSET ${pageCount * (page - 1)}")
80 | val rowMeta = rowResult.metaData
81 | while (rowResult.next()) {
82 | val dbRows = mutableListOf()
83 | val dbRow = DbRow(dbRows)
84 | for (columnIndex in columns.indices) {
85 | val type = rowMeta.getColumnType(columnIndex + 1)
86 | val typeName = rowMeta.getColumnTypeName(columnIndex + 1)
87 | val rowData = when (type) {
88 | Types.BLOB -> {
89 | DbRow.RowData(type, typeName, rowResult.getBytes(columnIndex + 1))
90 | }
91 | else -> {
92 | DbRow.RowData(type, typeName, rowResult.getObject(columnIndex + 1))
93 | }
94 | }
95 | dbRows.add(rowData)
96 | }
97 | rows.add(dbRow)
98 | }
99 |
100 | val countResult = statement.executeQuery("SELECT COUNT(*) FROM \"$tableName\"")
101 | countResult.next()
102 | totalCount = countResult.getInt(1)
103 | }
104 | ConnectionManager.disposeConnection(connection)
105 | return DbTableInstance(columns, rows, rows.size, page, totalCount)
106 | }
107 |
108 | private fun getAllSchema(resultSet: ResultSet): String {
109 | val nullable = resultSet.getBoolean("NULLABLE")
110 | val nullableString = if (nullable) "" else "NOT NULL"
111 | var def = resultSet.getString("COLUMN_DEF")
112 | def = if (def == null || def.isEmpty()) {
113 | ""
114 | } else {
115 | "DEFAULT $def"
116 | }
117 | val autoIncrement = resultSet.getBoolean("IS_AUTOINCREMENT")
118 | val autoIncString = if (autoIncrement) "AUTO INCREMENT" else ""
119 | return "$nullableString $def $autoIncString"
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | # GitHub Actions Workflow created for testing and preparing the plugin release in following steps:
2 | # - validate Gradle Wrapper,
3 | # - run 'test' and 'verifyPlugin' tasks,
4 | # - run Qodana inspections,
5 | # - run 'buildPlugin' task and prepare artifact for the further tests,
6 | # - run 'runPluginVerifier' task,
7 | # - create a draft release.
8 | #
9 | # Workflow is triggered on push and pull_request events.
10 | #
11 | # GitHub Actions reference: https://help.github.com/en/actions
12 | #
13 | ## JBIJPPTPL
14 |
15 | name: Build
16 | on:
17 | # Trigger the workflow on pushes to only the 'main' branch (this avoids duplicate checks being run e.g. for dependabot pull requests)
18 | push:
19 | branches: [main]
20 | # Trigger the workflow on any pull request
21 | pull_request:
22 |
23 | jobs:
24 |
25 | # Run Gradle Wrapper Validation Action to verify the wrapper's checksum
26 | # Run verifyPlugin, IntelliJ Plugin Verifier, and test Gradle tasks
27 | # Build plugin and provide the artifact for the next workflow jobs
28 | build:
29 | name: Build
30 | runs-on: ubuntu-latest
31 | outputs:
32 | version: ${{ steps.properties.outputs.version }}
33 | changelog: ${{ steps.properties.outputs.changelog }}
34 | steps:
35 |
36 | # Free GitHub Actions Environment Disk Space
37 | - name: Maximize Build Space
38 | run: |
39 | sudo rm -rf /usr/share/dotnet
40 | sudo rm -rf /usr/local/lib/android
41 | sudo rm -rf /opt/ghc
42 |
43 | # Check out current repository
44 | - name: Fetch Sources
45 | uses: actions/checkout@v3
46 |
47 | # Validate wrapper
48 | - name: Gradle Wrapper Validation
49 | uses: gradle/wrapper-validation-action@v1.0.4
50 |
51 | # Setup Java 11 environment for the next steps
52 | - name: Setup Java
53 | uses: actions/setup-java@v3
54 | with:
55 | distribution: zulu
56 | java-version: 11
57 |
58 | # Set environment variables
59 | - name: Export Properties
60 | id: properties
61 | shell: bash
62 | run: |
63 | PROPERTIES="$(./gradlew properties --console=plain -q)"
64 | VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
65 | NAME="$(echo "$PROPERTIES" | grep "^pluginName:" | cut -f2- -d ' ')"
66 | CHANGELOG="$(./gradlew getChangelog --unreleased --no-header --console=plain -q)"
67 | CHANGELOG="${CHANGELOG//'%'/'%25'}"
68 | CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
69 | CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
70 |
71 | echo "::set-output name=version::$VERSION"
72 | echo "::set-output name=name::$NAME"
73 | echo "::set-output name=changelog::$CHANGELOG"
74 | echo "::set-output name=pluginVerifierHomeDir::~/.pluginVerifier"
75 |
76 | ./gradlew listProductsReleases # prepare list of IDEs for Plugin Verifier
77 |
78 | # Run tests
79 | - name: Run Tests
80 | run: ./gradlew test
81 |
82 | # Collect Tests Result of failed tests
83 | - name: Collect Tests Result
84 | if: ${{ failure() }}
85 | uses: actions/upload-artifact@v3
86 | with:
87 | name: tests-result
88 | path: ${{ github.workspace }}/build/reports/tests
89 |
90 | # Cache Plugin Verifier IDEs
91 | - name: Setup Plugin Verifier IDEs Cache
92 | uses: actions/cache@v3
93 | with:
94 | path: ${{ steps.properties.outputs.pluginVerifierHomeDir }}/ides
95 | key: plugin-verifier-${{ hashFiles('build/listProductsReleases.txt') }}
96 |
97 | # Run Verify Plugin task and IntelliJ Plugin Verifier tool
98 | - name: Run Plugin Verification tasks
99 | run: ./gradlew runPluginVerifier -Pplugin.verifier.home.dir=${{ steps.properties.outputs.pluginVerifierHomeDir }}
100 |
101 | # Collect Plugin Verifier Result
102 | - name: Collect Plugin Verifier Result
103 | if: ${{ always() }}
104 | uses: actions/upload-artifact@v3
105 | with:
106 | name: pluginVerifier-result
107 | path: ${{ github.workspace }}/build/reports/pluginVerifier
108 |
109 | # Run Qodana inspections
110 | - name: Qodana - Code Inspection
111 | uses: JetBrains/qodana-action@v2022.2.1
112 |
113 | # Prepare plugin archive content for creating artifact
114 | - name: Prepare Plugin Artifact
115 | id: artifact
116 | shell: bash
117 | run: |
118 | cd ${{ github.workspace }}/build/distributions
119 | FILENAME=`ls *.zip`
120 | unzip "$FILENAME" -d content
121 |
122 | echo "::set-output name=filename::${FILENAME:0:-4}"
123 |
124 | # Store already-built plugin as an artifact for downloading
125 | - name: Upload artifact
126 | uses: actions/upload-artifact@v3
127 | with:
128 | name: ${{ steps.artifact.outputs.filename }}
129 | path: ./build/distributions/content/*/*
130 |
131 | # Prepare a draft release for GitHub Releases page for the manual verification
132 | # If accepted and published, release workflow would be triggered
133 | releaseDraft:
134 | name: Release Draft
135 | if: github.event_name != 'pull_request'
136 | needs: build
137 | runs-on: ubuntu-latest
138 | permissions:
139 | contents: write
140 | steps:
141 |
142 | # Check out current repository
143 | - name: Fetch Sources
144 | uses: actions/checkout@v3
145 |
146 | # Remove old release drafts by using the curl request for the available releases with draft flag
147 | - name: Remove Old Release Drafts
148 | env:
149 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
150 | run: |
151 | gh api repos/{owner}/{repo}/releases \
152 | --jq '.[] | select(.draft == true) | .id' \
153 | | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{}
154 |
155 | # Create new release draft - which is not publicly visible and requires manual acceptance
156 | - name: Create Release Draft
157 | env:
158 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
159 | run: |
160 | gh release create v${{ needs.build.outputs.version }} \
161 | --draft \
162 | --title "v${{ needs.build.outputs.version }}" \
163 | --notes "$(cat << 'EOM'
164 | ${{ needs.build.outputs.changelog }}
165 | EOM
166 | )"
167 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/parser/DateComparator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.parser;
27 |
28 | import java.text.Format;
29 |
30 | import java.util.Calendar;
31 | import java.util.Comparator;
32 | import java.util.Date;
33 |
34 |
35 | /**
36 | * Class to deduce a sensible {@link Comparator} for {@link Date} instances.
37 | */
38 | abstract public class DateComparator implements Comparator {
39 |
40 | /**
41 | * Factory constructor, returning an instance suitable for the given format.
42 | */
43 | public static DateComparator getDateComparator(Format dateFormat) {
44 | // the idea is to build a date instance, change then each field
45 | // (milliseconds / seconds / etc) and check the change on the
46 | // parsed instance. If changing, for example, the seconds, does
47 | // not produce a different formatted string, the comparator will
48 | // not pay attention to the seconds, and so on
49 | Calendar calendar = Calendar.getInstance();
50 | calendar.setTimeInMillis(new Date().getTime());
51 | if (change(calendar, dateFormat, Calendar.MILLISECOND)) {
52 | // Milliseconds affect the output, full comparison
53 | return new DateComparator() {
54 | @Override public long diff(Date o1, Date o2) {
55 | return o1.compareTo(o2);
56 | }
57 | };
58 | }
59 |
60 | int divisor = 0;
61 | if (change(calendar, dateFormat, Calendar.SECOND)) {
62 | divisor = 1000;
63 | } else if (change(calendar, dateFormat, Calendar.MINUTE)) {
64 | divisor = 1000 * 60;
65 | } else if (change(calendar, dateFormat, Calendar.HOUR)) {
66 | divisor = 1000 * 60 * 60;
67 | } else if (change(calendar, dateFormat, Calendar.DAY_OF_YEAR)) {
68 | return new DayMonthYearComparator(calendar);
69 | } else if (change(calendar, dateFormat, Calendar.MONTH)) {
70 | return new MonthYearComparator(calendar);
71 | } else if (change(calendar, dateFormat, Calendar.YEAR)) {
72 | return new YearComparator(calendar);
73 | } else {
74 | // nothing affects the output, great formatter!
75 | return new DateComparator() {
76 | @Override public long diff(Date o1, Date o2) {
77 | return 0;
78 | }
79 | };
80 | }
81 |
82 | return new TimeComparator(divisor);
83 | }
84 |
85 | static private boolean change(Calendar c, Format f, int field) {
86 | c.set(field, 10);
87 |
88 | String sf = f.format(c.getTime());
89 | c.set(field, 11);
90 |
91 | return !sf.equals(f.format(c.getTime()));
92 | }
93 |
94 | @Override public int compare(Date o1, Date o2) {
95 | if (o1 == null) {
96 | return (o2 == null) ? 0 : -1;
97 | }
98 |
99 | if (o2 == null) {
100 | return 1;
101 | }
102 |
103 | long diff = diff(o1, o2);
104 |
105 | return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
106 | }
107 |
108 | public abstract long diff(Date o1, Date o2);
109 |
110 | /**
111 | * DateComparator when the difference relies on time fields (seconds,
112 | * minutes, hours).
113 | * We divide the time to set out the unneeded information, before comparing
114 | */
115 | static class TimeComparator extends DateComparator {
116 | int divisor;
117 |
118 | public TimeComparator(int divisor) {
119 | this.divisor = divisor;
120 | }
121 |
122 | @Override public long diff(Date o1, Date o2) {
123 | return (o1.getTime() / divisor) - (o2.getTime() / divisor);
124 | }
125 | }
126 |
127 | /** DateComparator that simply compares the year's fields. */
128 | static class YearComparator extends DateComparator {
129 | Calendar calendar;
130 |
131 | public YearComparator(Calendar calendar) {
132 | this.calendar = calendar;
133 | }
134 |
135 | @Override public long diff(Date o1, Date o2) {
136 | calendar.setTime(o1);
137 |
138 | long base = time();
139 | calendar.setTime(o2);
140 |
141 | return base - time();
142 | }
143 |
144 | long time() {
145 | return calendar.get(Calendar.YEAR);
146 | }
147 | }
148 |
149 | /** DateComparator that simply compares the year and month's fields. */
150 | static class MonthYearComparator extends YearComparator {
151 | public MonthYearComparator(Calendar calendar) {
152 | super(calendar);
153 | }
154 |
155 | @Override long time() {
156 | return (calendar.get(Calendar.YEAR) * 12)
157 | + calendar.get(Calendar.MONTH);
158 | }
159 | }
160 |
161 | /** DateComparator that simply compares the year/month/day's fields. */
162 | static class DayMonthYearComparator extends YearComparator {
163 | public DayMonthYearComparator(Calendar calendar) {
164 | super(calendar);
165 | }
166 |
167 | @Override long time() {
168 | return (calendar.get(Calendar.YEAR) * 400)
169 | + calendar.get(Calendar.DAY_OF_YEAR);
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/ChoicesHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.text.Format;
29 |
30 | import javax.swing.JTable;
31 | import javax.swing.RowFilter;
32 | import javax.swing.SwingUtilities;
33 | import javax.swing.event.TableModelEvent;
34 | import javax.swing.event.TableModelListener;
35 | import javax.swing.table.TableModel;
36 |
37 | import net.coderazzi.filters.IFilter;
38 | import net.coderazzi.filters.gui.editor.FilterEditor;
39 |
40 |
41 | /**
42 | * Interface implemented by the classes that handle the choices on each {@link
43 | * FilterEditor}.
44 | */
45 | abstract class ChoicesHandler implements TableModelListener, Runnable {
46 |
47 | protected FiltersHandler handler;
48 |
49 | /** The model being listened to handle model changes. */
50 | private TableModel listenedModel;
51 |
52 | /** this variable is true to signal an update to the FiltersHandler. */
53 | private boolean runScheduled;
54 |
55 | protected ChoicesHandler(FiltersHandler handler) {
56 | this.handler = handler;
57 | }
58 |
59 | /** Returns the {@link RowFilter} associated to this handler. */
60 | public abstract RowFilter getRowFilter();
61 |
62 | /**
63 | * Sets/unsets the handler on interrupt mode
64 | * On interrupt mode, the associated {@link FiltersHandler} is likely to
65 | * send many update events, which shouldn't be treated (if possible).
66 | */
67 | public abstract boolean setInterrupted(boolean interrupted);
68 |
69 | /** Reports a {@link FilterEditor} update. */
70 | public abstract void editorUpdated(FilterEditor editor);
71 |
72 | /**
73 | * Reports a {@link IFilter} update.
74 | *
75 | * @param retInfoRequired set to true if the return value is required
76 | *
77 | * @return true if the filter let pass any row
78 | */
79 | public abstract boolean filterUpdated(IFilter filter,
80 | boolean retInfoRequired);
81 |
82 | /**
83 | * Reports the beginning or end of {@link IFilter} add/remove operations.
84 | */
85 | public abstract void filterOperation(boolean start);
86 |
87 | /** Call triggered after a filter becomes enabled. */
88 | public abstract void filterEnabled(IFilter filter);
89 |
90 | /** Call triggered after all filters become disabled. */
91 | public abstract void allFiltersDisabled();
92 |
93 | /** Ensures that instant changes are propagated. */
94 | public abstract void consolidateFilterChanges(int modelIndex);
95 |
96 | /** Reports a table update. */
97 | protected abstract void tableUpdated(TableModel model,
98 | int eventType,
99 | int firstRow,
100 | int lastRow,
101 | int column);
102 |
103 | @Override public void tableChanged(TableModelEvent e) {
104 | int firstRow = e.getFirstRow();
105 | if (firstRow != TableModelEvent.HEADER_ROW) {
106 | int type = e.getType();
107 | TableModel model = (TableModel) e.getSource();
108 | tableUpdated(model, type, firstRow, e.getLastRow(), e.getColumn());
109 | if (!runScheduled) {
110 | runScheduled = true;
111 | // invoke later filtersHandler.tableUpdated, as perhaps the
112 | // row sorter hasn't been updated its status
113 | SwingUtilities.invokeLater(this);
114 | }
115 | }
116 | }
117 |
118 | /** {@link Runnable} interface. */
119 | @Override public void run() {
120 | runScheduled = false;
121 | handler.tableUpdated();
122 | }
123 |
124 | /**
125 | * Sets whether to send table model events to the {@link ChoicesHandler}.
126 | */
127 | protected void setEnableTableModelEvents(boolean set) {
128 | if (set) {
129 | JTable table = handler.getTable();
130 | if (table != null) {
131 | if (listenedModel != null) {
132 | if (listenedModel == table.getModel()) {
133 | return;
134 | }
135 |
136 | setEnableTableModelEvents(false);
137 | }
138 |
139 | listenedModel = table.getModel();
140 | listenedModel.addTableModelListener(this);
141 | }
142 | } else if (listenedModel != null) {
143 | listenedModel.removeTableModelListener(this);
144 | listenedModel = null;
145 | }
146 | }
147 |
148 | /**
149 | * Basic RowFilter.Entry instance, used internally to handle the RowFilter
150 | * default filtering.
151 | */
152 | static protected class RowEntry extends RowFilter.Entry {
153 | private TableModel model;
154 | private int count;
155 | private Format formatters[];
156 | public int row;
157 |
158 | public RowEntry(TableModel model, FilterEditor editors[]) {
159 | this.model = model;
160 | this.count = model.getColumnCount();
161 |
162 | int len = editors.length;
163 | formatters = new Format[len];
164 | while (len-- > 0) {
165 | formatters[len] = editors[len].getFormat();
166 | }
167 | }
168 |
169 | public int getModelRowCount() {
170 | return model.getRowCount();
171 | }
172 |
173 | public Format[] getFormatters() {
174 | return formatters;
175 | }
176 |
177 | @Override public Object getIdentifier() {
178 | return row;
179 | }
180 |
181 | @Override public TableModel getModel() {
182 | return model;
183 | }
184 |
185 | @Override public Object getValue(int index) {
186 | return model.getValueAt(row, index);
187 | }
188 |
189 | @Override public int getValueCount() {
190 | return count;
191 | }
192 |
193 | @Override public String getStringValue(int index) {
194 | Format f = formatters[index];
195 | return f == null ? "" : f.format(getValue(index));
196 | }
197 | }
198 |
199 | }
200 |
--------------------------------------------------------------------------------
/tablefilter/src/main/java/net/coderazzi/filters/gui/IFilterEditor.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Author: Luis M Pena ( lu@coderazzi.net )
3 | * License: MIT License
4 | *
5 | * Copyright (c) 2007 Luis M. Pena - lu@coderazzi.net
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 |
26 | package net.coderazzi.filters.gui;
27 |
28 | import java.text.Format;
29 |
30 | import java.util.Comparator;
31 | import java.util.List;
32 | import java.util.Set;
33 |
34 | import javax.swing.table.TableModel;
35 |
36 | import net.coderazzi.filters.IFilter;
37 |
38 |
39 | /** Public interface of the editors associated to each table's column. */
40 | public interface IFilterEditor {
41 |
42 | /** Returns the model position associated to this editor. */
43 | int getModelIndex();
44 |
45 | /** Returns the class associated to the editor on the model. */
46 | Class> getModelClass();
47 |
48 | /**
49 | * Returns the {@link IFilter} associated to the editor's content
50 | * The returned instance can then be used to enable or disable the filter
51 | * and its GUI component.
52 | */
53 | IFilter getFilter();
54 |
55 | /**
56 | * Resets the filter, which implies set its content to empty and reset its
57 | * history choices.
58 | */
59 | void resetFilter();
60 |
61 | /** Sets the content, adapted to the editors' type. */
62 | void setContent(Object content);
63 |
64 | /** Returns the current editor's content. */
65 | Object getContent();
66 |
67 | /**
68 | * Using autoChoices, the choices displayed on the popup menu are
69 | * automatically extracted from the associated {@link TableModel}.
70 | * For editors associated to boolean or short enumerations, if
71 | * AutoCompletion is not set, setting the AutoChoices automatically changes
72 | * the editable flag to true, unless AutoChoices has the DISABLED value
73 | */
74 | void setAutoChoices(AutoChoices mode);
75 |
76 | /** Returns the autoChoices mode. */
77 | AutoChoices getAutoChoices();
78 |
79 | /** Sets the available choices, shown on the popup menu. */
80 | void setCustomChoices(Set choices);
81 |
82 | /** Returns the current choices. */
83 | Set getCustomChoices();
84 |
85 | /**
86 | * Enables or disables the user's interaction; if disabled, the control
87 | * is disabled but the associated filter remains in place.
88 | */
89 | void setUserInteractionEnabled(boolean enable);
90 |
91 | /** Returns the user interaction mode. */
92 | boolean isUserInteractionEnabled();
93 |
94 | /**
95 | * Defines the editor, if text based -i.e., without associated {@link
96 | * ChoiceRenderer}, as editable: this flag means that the user can enter any
97 | * text, not being limited to the existing choices
98 | */
99 | void setEditable(boolean enable);
100 |
101 | /** Returns the editable flag. */
102 | boolean isEditable();
103 |
104 | /** Sets the ignore case flag. */
105 | void setIgnoreCase(boolean set);
106 |
107 | /** Returns the ignore case flag. */
108 | boolean isIgnoreCase();
109 |
110 | /**
111 | * Sets the {@link Format} required by the editor to handle the user's input
112 | * when the associated class is not a String
113 | * It is initially retrieved from the {@link IParserModel}.
114 | */
115 | void setFormat(Format format);
116 |
117 | /** Returns the associated {@link Format}. */
118 | Format getFormat();
119 |
120 | /**
121 | * Sets the {@link Comparator} required to compare (and sort) instances of
122 | * the associated class in the table model.
123 | * This operation sets also this operator as the choices comparator
124 | * (see {@link #setChoicesComparator(Comparator)})
125 | * @param comparator cannot be null
126 | */
127 | void setComparator(Comparator comparator);
128 |
129 | /** Returns the associated {@link Comparator}, which is never null. */
130 | Comparator getComparator();
131 |
132 | /**
133 | * Sets the {@link Comparator} used to sort out the choices. By default.
134 | * this is the same operator associated to the editor. Note that editors
135 | * associated to enumeration types are sorted by default alphabetically.
136 | * @param comparator can be set to null to use alphabetic sorting
137 | * @see IFilterEditor#setComparator(Comparator)
138 | */
139 | void setChoicesComparator(Comparator comparator);
140 |
141 | /** Returns the associated {@link Comparator} choices comparator. */
142 | Comparator getChoicesComparator();
143 |
144 | /** Sets the auto completion flag. */
145 | void setAutoCompletion(boolean enable);
146 |
147 | /** Returns the auto completion flag. */
148 | boolean isAutoCompletion();
149 |
150 | /** Sets the auto hide-popup flag*/
151 | void setHidePopupOnTableUpdates(boolean set);
152 |
153 | /** Returns the auto hide-popup flag */
154 | boolean isHidePopupOnTableUpdates();
155 |
156 | /** Sets the instant filtering flag. */
157 | void setInstantFiltering(boolean enable);
158 |
159 | /** Returns the instant filtering flag. */
160 | boolean isInstantFiltering();
161 |
162 | /** Sets the allow instant vanishing flag. */
163 | void setAllowedInstantVanishing(boolean enable);
164 |
165 | /** Returns the instant filtering flag. */
166 | boolean isAllowedInstantVanishing();
167 |
168 | /**
169 | * Limits the history size.
170 | * This limit is only used when the popup contains also choices. Otherwise,
171 | * the maximum history size is to the maximum number of visible rows
172 | * The max history cannot be greater than the max visible rows
173 | */
174 | void setMaxHistory(int size);
175 |
176 | /**
177 | * Returns the maximum history size, as defined by the user.
178 | * This is not the real maximum history size, as it depends on the max
179 | * number of visible rows and whether the popup contains only history or
180 | * also choices
181 | */
182 | int getMaxHistory();
183 |
184 | /**
185 | * Sets the history contents.
186 | * @since 4.3.1.0
187 | */
188 | void setHistory(List