RDI 0.1.0.20091020
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +3 -0
- data/ChangeLog +46 -0
- data/Credits +21 -0
- data/LICENSE +31 -0
- data/README +18 -0
- data/TODO +17 -0
- data/lib/rdi/Installer.rb +678 -0
- data/lib/rdi/Model/ContextModifier.rb +20 -0
- data/lib/rdi/Model/DependencyDescription.rb +154 -0
- data/lib/rdi/Model/DependencyUserChoice.rb +202 -0
- data/lib/rdi/Model/Installer.rb +24 -0
- data/lib/rdi/Model/LocationSelector.rb +16 -0
- data/lib/rdi/Model/ProgressView.rb +16 -0
- data/lib/rdi/Model/Tester.rb +20 -0
- data/lib/rdi/Model/View.rb +16 -0
- data/lib/rdi/Plugins/ContextModifiers/GemPath.desc.rb +13 -0
- data/lib/rdi/Plugins/ContextModifiers/GemPath.rb +106 -0
- data/lib/rdi/Plugins/ContextModifiers/LibraryPath.rb +74 -0
- data/lib/rdi/Plugins/ContextModifiers/RubyLoadPath.rb +76 -0
- data/lib/rdi/Plugins/ContextModifiers/SystemPath.rb +74 -0
- data/lib/rdi/Plugins/GemCommon.rb +127 -0
- data/lib/rdi/Plugins/Installers/Download.rb +72 -0
- data/lib/rdi/Plugins/Installers/DownloadAndInstall.desc.rb +11 -0
- data/lib/rdi/Plugins/Installers/DownloadAndInstall.rb +54 -0
- data/lib/rdi/Plugins/Installers/Gem.desc.rb +13 -0
- data/lib/rdi/Plugins/Installers/Gem.rb +67 -0
- data/lib/rdi/Plugins/Installers/Icons/Download.png +0 -0
- data/lib/rdi/Plugins/Installers/Icons/DownloadAndInstall.png +0 -0
- data/lib/rdi/Plugins/Installers/Icons/Gem.png +0 -0
- data/lib/rdi/Plugins/Installers/Yum.rb +52 -0
- data/lib/rdi/Plugins/ProgressViews/SimpleWxGUI.desc.rb +13 -0
- data/lib/rdi/Plugins/ProgressViews/SimpleWxGUI.rb +58 -0
- data/lib/rdi/Plugins/ProgressViews/Text.rb +68 -0
- data/lib/rdi/Plugins/RubyGemsDepDesc.rb +41 -0
- data/lib/rdi/Plugins/Testers/Binaries.rb +56 -0
- data/lib/rdi/Plugins/Testers/DynamicLibraries.rb +56 -0
- data/lib/rdi/Plugins/Testers/RubyRequires.rb +76 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/DependenciesLoaderDialog.rb +147 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/DependencyPanel.rb +301 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/Icons/Dependency.png +0 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/Icons/Ignore.png +0 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/Icons/ValidKO.png +0 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/Icons/ValidOK.png +0 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/LocationSelectors/Directory.desc.rb +13 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI/LocationSelectors/Directory.rb +45 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI.desc.rb +13 -0
- data/lib/rdi/Plugins/Views/SimpleWxGUI.rb +60 -0
- data/lib/rdi/Plugins/Views/Text/LocationSelectors/Directory.rb +44 -0
- data/lib/rdi/Plugins/Views/Text.rb +257 -0
- data/lib/rdi/Plugins/WxCommon.rb +69 -0
- data/lib/rdi/Plugins/WxRubyDepDesc.rb +36 -0
- data/lib/rdi/rdi.rb +8 -0
- data/test/Common.rb +796 -0
- data/test/Flows/BasicFlows.rb +114 -0
- data/test/Flows/UIFlows.rb +460 -0
- data/test/Plugins/ContextModifiers/GemPath.rb +44 -0
- data/test/Plugins/ContextModifiers/LibraryPath.rb +36 -0
- data/test/Plugins/ContextModifiers/RubyLoadPath.rb +36 -0
- data/test/Plugins/ContextModifiers/SystemPath.rb +36 -0
- data/test/Plugins/Installers/Download.rb +65 -0
- data/test/Plugins/Installers/DownloadAndInstall.rb +73 -0
- data/test/Plugins/Installers/Gem.rb +79 -0
- data/test/Plugins/LocationSelectors/Directory.rb +34 -0
- data/test/Plugins/Testers/Binaries.rb +46 -0
- data/test/Plugins/Testers/DynamicLibraries.rb +46 -0
- data/test/Plugins/Testers/RubyRequires.rb +48 -0
- data/test/Plugins/Views/SimpleWxGUI.rb +190 -0
- data/test/Plugins/Views/Text.rb +112 -0
- data/test/Plugins/WxEnv.rb +58 -0
- data/test/Plugins/WxEnvApp.rb +53 -0
- data/test/Repository/Binaries/DummyBinary +1 -0
- data/test/Repository/Libraries/DummyLibrary.so +1 -0
- data/test/Repository/RubyGems/DummyGem-0.0.1.20090828.gem +0 -0
- data/test/Repository/RubyGems/GemsSources/DummyGem/DummyGem.gemspec.rb +23 -0
- data/test/Repository/RubyGems/GemsSources/DummyGem/lib/DummyGemMain.rb +5 -0
- data/test/Repository/RubyLibraries/DummyRubyLib.rb +1 -0
- data/test/run.rb +23 -0
- metadata +145 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module RDI
|
7
|
+
|
8
|
+
# Give the description of the RubyGems dependency
|
9
|
+
# It has been put in this singular file because it is required by many different plugins
|
10
|
+
#
|
11
|
+
# Return:
|
12
|
+
# * <em>map<Symbol,Object></em>: The description
|
13
|
+
def self.getRubyGemsDepDesc
|
14
|
+
return RDI::Model::DependencyDescription.new('RubyGems 1.3.5').addDescription( {
|
15
|
+
:Testers => [
|
16
|
+
{
|
17
|
+
:Type => 'RubyRequires',
|
18
|
+
:Content => [ 'rubygems' ]
|
19
|
+
}
|
20
|
+
],
|
21
|
+
:Installers => [
|
22
|
+
{
|
23
|
+
:Type => 'DownloadAndInstall',
|
24
|
+
:Content => [
|
25
|
+
'http://rubyforge.org/frs/download.php/60719/rubygems-1.3.5.zip',
|
26
|
+
Proc.new do |iInstallLocation|
|
27
|
+
next system("ruby -w setup.rb --destdir #{iInstallLocation}")
|
28
|
+
end
|
29
|
+
],
|
30
|
+
:ContextModifiers => [
|
31
|
+
{
|
32
|
+
:Type => 'RubyLoadPath',
|
33
|
+
:Content => "%INSTALLDIR%/lib/ruby/site_ruby/#{Config::CONFIG['ruby_version']}"
|
34
|
+
}
|
35
|
+
]
|
36
|
+
}
|
37
|
+
]
|
38
|
+
} )
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'rdi/Model/Tester'
|
7
|
+
|
8
|
+
module RDI
|
9
|
+
|
10
|
+
module Testers
|
11
|
+
|
12
|
+
# Test that some Exes are accessible
|
13
|
+
class Binaries < RDI::Model::Tester
|
14
|
+
|
15
|
+
# Give the name of possible ContextModifiers that might change the resolution of this Tester.
|
16
|
+
# This is used to know what context modifiers the user can use to resolve dependencies without having to install.
|
17
|
+
#
|
18
|
+
# Return:
|
19
|
+
# * <em>list<String></em>: The list of ContextModifiers names
|
20
|
+
def getAffectingContextModifiers
|
21
|
+
return [ 'SystemPath' ]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Test if a given content is resolved
|
25
|
+
#
|
26
|
+
# Parameters:
|
27
|
+
# * *iContent* (_Object_): The tester's content
|
28
|
+
# Return:
|
29
|
+
# * _Boolean_: Is the content resolved ?
|
30
|
+
def isContentResolved?(iContent)
|
31
|
+
# * *iContent* (<em>list<String></em>): The list of Exes to resolve (extensions might be guessed)
|
32
|
+
rSuccess = false
|
33
|
+
|
34
|
+
# For each required file, test that it exists among PATH
|
35
|
+
iContent.each do |iExeName|
|
36
|
+
$rUtilAnts_Platform_Info.getSystemExePath.each do |iDir|
|
37
|
+
rSuccess = (!Dir.glob(File.expand_path("#{iDir}/#{iExeName}{,#{$rUtilAnts_Platform_Info.getDiscreteExeExtensions.join(',')}}")).empty?)
|
38
|
+
if (rSuccess)
|
39
|
+
# We found it. Don't try other paths.
|
40
|
+
break
|
41
|
+
end
|
42
|
+
end
|
43
|
+
if (!rSuccess)
|
44
|
+
# We didn't find this exe. Don't try other requires.
|
45
|
+
break
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
return rSuccess
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'rdi/Model/Tester'
|
7
|
+
|
8
|
+
module RDI
|
9
|
+
|
10
|
+
module Testers
|
11
|
+
|
12
|
+
# Test that some DLLs are accessible
|
13
|
+
class DynamicLibraries < RDI::Model::Tester
|
14
|
+
|
15
|
+
# Give the name of possible ContextModifiers that might change the resolution of this Tester.
|
16
|
+
# This is used to know what context modifiers the user can use to resolve dependencies without having to install.
|
17
|
+
#
|
18
|
+
# Return:
|
19
|
+
# * <em>list<String></em>: The list of ContextModifiers names
|
20
|
+
def getAffectingContextModifiers
|
21
|
+
return [ 'LibraryPath' ]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Test if a given content is resolved
|
25
|
+
#
|
26
|
+
# Parameters:
|
27
|
+
# * *iContent* (_Object_): The tester's content
|
28
|
+
# Return:
|
29
|
+
# * _Boolean_: Is the content resolved ?
|
30
|
+
def isContentResolved?(iContent)
|
31
|
+
# * *iContent* (<em>list<String></em>): The list of DLLs to resolve
|
32
|
+
rSuccess = false
|
33
|
+
|
34
|
+
# For each required file, test that it exists among $LOAD_PATH
|
35
|
+
iContent.each do |iDLLName|
|
36
|
+
$rUtilAnts_Platform_Info.getSystemLibsPath.each do |iDir|
|
37
|
+
rSuccess = File.exists?("#{iDir}/#{iDLLName}")
|
38
|
+
if (rSuccess)
|
39
|
+
# We found it. Don't try other paths.
|
40
|
+
break
|
41
|
+
end
|
42
|
+
end
|
43
|
+
if (!rSuccess)
|
44
|
+
# We didn't find this require. Don't try other requires.
|
45
|
+
break
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
return rSuccess
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'rdi/Model/Tester'
|
7
|
+
require 'rdi/Plugins/GemCommon'
|
8
|
+
|
9
|
+
module RDI
|
10
|
+
|
11
|
+
module Testers
|
12
|
+
|
13
|
+
# Test that some Ruby files are accessible
|
14
|
+
class RubyRequires < RDI::Model::Tester
|
15
|
+
|
16
|
+
# Give the name of possible ContextModifiers that might change the resolution of this Tester.
|
17
|
+
# This is used to know what context modifiers the user can use to resolve dependencies without having to install.
|
18
|
+
#
|
19
|
+
# Return:
|
20
|
+
# * <em>list<String></em>: The list of ContextModifiers names
|
21
|
+
def getAffectingContextModifiers
|
22
|
+
return [ 'GemPath', 'RubyLoadPath' ]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Test if a given content is resolved
|
26
|
+
#
|
27
|
+
# Parameters:
|
28
|
+
# * *iContent* (_Object_): The tester's content
|
29
|
+
# Return:
|
30
|
+
# * _Boolean_: Is the content resolved ?
|
31
|
+
def isContentResolved?(iContent)
|
32
|
+
# * *iContent* (<em>list<String></em>): The list of requires to resolve
|
33
|
+
rSuccess = false
|
34
|
+
|
35
|
+
# Handle RubyGems as an option
|
36
|
+
if (defined?(Gem) == nil)
|
37
|
+
# No RubyGem.
|
38
|
+
# For each required file, test that it exists among $LOAD_PATH
|
39
|
+
iContent.each do |iRequireName|
|
40
|
+
lFileFilter = iRequireName
|
41
|
+
if (File.extname(iRequireName).empty?)
|
42
|
+
lFileFilter = "#{iRequireName}.{rb,so,o,sl,dll}"
|
43
|
+
end
|
44
|
+
rSuccess = false
|
45
|
+
$LOAD_PATH.each do |iDir|
|
46
|
+
rSuccess = (!Dir.glob(File.expand_path("#{iDir}/#{lFileFilter}")).empty?)
|
47
|
+
if (rSuccess)
|
48
|
+
# We found it. Don't try other paths.
|
49
|
+
break
|
50
|
+
end
|
51
|
+
end
|
52
|
+
if (!rSuccess)
|
53
|
+
# We didn't find this require. Don't try other requires.
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
# RubyGems is here. Use it.
|
59
|
+
# For each required file, test that it exists among the RubyGems' loaded paths
|
60
|
+
iContent.each do |iRequireName|
|
61
|
+
rSuccess = (!Gem.find_files(iRequireName).empty?)
|
62
|
+
if (!rSuccess)
|
63
|
+
# We did not find this one: don't even try the next ones
|
64
|
+
break
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
return rSuccess
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module RDI
|
7
|
+
|
8
|
+
module Views
|
9
|
+
|
10
|
+
class SimpleWxGUI
|
11
|
+
|
12
|
+
# Dialog that downloads missing dependencies
|
13
|
+
# Apart launchers, only this class has a dependency on RubyGems
|
14
|
+
class DependenciesLoaderDialog < Wx::Dialog
|
15
|
+
|
16
|
+
# Constructor
|
17
|
+
#
|
18
|
+
# Parameters:
|
19
|
+
# * *iParent* (<em>Wx::Window</em>): The parent
|
20
|
+
# * *ioInstaller* (_Installer_): The installer
|
21
|
+
# * *iDepsUserChoices* (<em>list<DependencyUserChoice></em>): The dependency user choices to reflect in this dialog
|
22
|
+
def initialize(iParent, ioInstaller, iDepsUserChoices)
|
23
|
+
super(iParent,
|
24
|
+
:title => 'RDI: Runtime Dependencies Installer',
|
25
|
+
:style => Wx::DEFAULT_DIALOG_STYLE|Wx::RESIZE_BORDER|Wx::MAXIMIZE_BOX
|
26
|
+
)
|
27
|
+
|
28
|
+
# This boolean will prevent undesirable refreshes
|
29
|
+
@DuringInit = true
|
30
|
+
|
31
|
+
@Installer, @DepsUserChoices = ioInstaller, iDepsUserChoices
|
32
|
+
@IconsDir = "#{File.dirname(__FILE__)}/Icons"
|
33
|
+
|
34
|
+
# Create components
|
35
|
+
@BApply = Wx::Button.new(self, Wx::ID_ANY, 'Apply')
|
36
|
+
lSTMessage = Wx::StaticText.new(self, Wx::ID_ANY, "#{@DepsUserChoices.size} dependencies could not be found.\nPlease indicate what action to take for each one of them before continuing.",
|
37
|
+
:style => Wx::ALIGN_CENTRE
|
38
|
+
)
|
39
|
+
lFont = lSTMessage.font
|
40
|
+
lFont.weight = Wx::FONTWEIGHT_BOLD
|
41
|
+
lSTMessage.font = lFont
|
42
|
+
|
43
|
+
# The notebook containing the scroll windows
|
44
|
+
@NBDeps = Wx::Notebook.new(self)
|
45
|
+
# Create the image list for the notebook
|
46
|
+
lNotebookImageList = Wx::ImageList.new(16, 16)
|
47
|
+
@NBDeps.image_list = lNotebookImageList
|
48
|
+
# Make this image list driven by a manager
|
49
|
+
@NBImageListManager = RUtilAnts::GUI::ImageListManager.new(lNotebookImageList, 16, 16)
|
50
|
+
|
51
|
+
# Create the list of Panels displaying each dependency
|
52
|
+
@DependencyPanels = []
|
53
|
+
require 'rdi/Plugins/Views/SimpleWxGUI/DependencyPanel'
|
54
|
+
@DepsUserChoices.each do |iDepUserChoice|
|
55
|
+
@DependencyPanels << DependencyPanel.new(
|
56
|
+
@NBDeps,
|
57
|
+
@Installer,
|
58
|
+
iDepUserChoice,
|
59
|
+
self
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
# The notebook pages, 1 per dependency
|
64
|
+
lIdx = 0
|
65
|
+
@DepsUserChoices.each do |iDepUserChoice|
|
66
|
+
@NBDeps.add_page(
|
67
|
+
@DependencyPanels[lIdx],
|
68
|
+
iDepUserChoice.DepDesc.ID,
|
69
|
+
false,
|
70
|
+
-1
|
71
|
+
)
|
72
|
+
lIdx += 1
|
73
|
+
end
|
74
|
+
|
75
|
+
# Resize some components as they will be used for sizers
|
76
|
+
@NBDeps.fit
|
77
|
+
|
78
|
+
# Put everything in sizers
|
79
|
+
lMainSizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
80
|
+
lMainSizer.add_item(lSTMessage, :border => 8, :flag => Wx::ALIGN_CENTER|Wx::ALL, :proportion => 0)
|
81
|
+
lMainSizer.add_item(@NBDeps, :flag => Wx::GROW, :proportion => 1)
|
82
|
+
lMainSizer.add_item(@BApply, :border => 8, :flag => Wx::ALIGN_RIGHT|Wx::ALL, :proportion => 0)
|
83
|
+
self.sizer = lMainSizer
|
84
|
+
|
85
|
+
self.fit
|
86
|
+
|
87
|
+
# Events
|
88
|
+
evt_button(@BApply) do |iEvent|
|
89
|
+
self.end_modal(Wx::ID_OK)
|
90
|
+
end
|
91
|
+
|
92
|
+
@DuringInit = false
|
93
|
+
|
94
|
+
# Update the tabs
|
95
|
+
@DependencyPanels.each do |iPanel|
|
96
|
+
notifyRefresh(iPanel)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# A panel has been refreshed
|
102
|
+
#
|
103
|
+
# Parameters:
|
104
|
+
# * *iPanel* (<em>Wx::Panel</em>): The panel just refreshed
|
105
|
+
def notifyRefresh(iPanel)
|
106
|
+
if (!@DuringInit)
|
107
|
+
# Find the Tab containing this Panel
|
108
|
+
lIdx = @DependencyPanels.index(iPanel)
|
109
|
+
lDepUserChoice = @DepsUserChoices[lIdx]
|
110
|
+
lIconName = "#{@IconsDir}/Dependency.png"
|
111
|
+
if (lDepUserChoice.Locate)
|
112
|
+
if (lDepUserChoice.ResolvedTesters.size == lDepUserChoice.DepDesc.Testers.size)
|
113
|
+
# Complete
|
114
|
+
lIconName = "#{@IconsDir}/ValidOK.png"
|
115
|
+
else
|
116
|
+
# Incomplete
|
117
|
+
lIconName = "#{@IconsDir}/ValidKO.png"
|
118
|
+
end
|
119
|
+
elsif (lDepUserChoice.Ignore)
|
120
|
+
lIconName = "#{@IconsDir}/Ignore.png"
|
121
|
+
else
|
122
|
+
# Get the icon of the selected Installer
|
123
|
+
lInstallerName = lDepUserChoice.DepDesc.Installers[lDepUserChoice.IdxInstaller][0]
|
124
|
+
# TODO: Accept more data formats
|
125
|
+
lInstallerIconName = "#{@Installer.RDILibDir}/Plugins/Installers/Icons/#{lInstallerName}.png"
|
126
|
+
if (File.exists?(lInstallerIconName))
|
127
|
+
lIconName = lInstallerIconName
|
128
|
+
end
|
129
|
+
end
|
130
|
+
lIdxImage = @NBImageListManager.getImageIndex(lIconName) do
|
131
|
+
lIcon, lError = getBitmapFromURL(lIconName)
|
132
|
+
if (lIcon == nil)
|
133
|
+
lIcon, lError = getBitmapFromURL("#{@IconsDir}/Dependency.png")
|
134
|
+
end
|
135
|
+
next lIcon
|
136
|
+
end
|
137
|
+
@NBDeps.set_page_image(lIdx, lIdxImage)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,301 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Muriel Salvan (murielsalvan@users.sourceforge.net)
|
3
|
+
# Licensed under the terms specified in LICENSE file. No warranty is provided.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module RDI
|
7
|
+
|
8
|
+
module Views
|
9
|
+
|
10
|
+
class SimpleWxGUI
|
11
|
+
|
12
|
+
# Panel that proposes how to resolve a dependency
|
13
|
+
class DependencyPanel < Wx::Panel
|
14
|
+
|
15
|
+
# Constructor
|
16
|
+
# The notifier control window must have a notifyInstallDecisionChanged method implemented
|
17
|
+
#
|
18
|
+
# Parameters:
|
19
|
+
# * *iParent* (<em>Wx::Window</em>): The parent window
|
20
|
+
# * *ioInstaller* (_Installer_): The installer
|
21
|
+
# * *iDepUserChoice* (_DependencyUserChoice_): The dependency's user choice
|
22
|
+
# * *iNotifierControl* (_Object_): The notifier control that will be notified upon changes
|
23
|
+
def initialize(iParent, ioInstaller, iDepUserChoice, iNotifierControl)
|
24
|
+
super(iParent)
|
25
|
+
|
26
|
+
@Installer, @DepUserChoice, @NotifierControl = ioInstaller, iDepUserChoice, iNotifierControl
|
27
|
+
@IconsDir = "#{File.dirname(__FILE__)}/Icons"
|
28
|
+
|
29
|
+
# Create components
|
30
|
+
|
31
|
+
# The locate part
|
32
|
+
@RBLocate = Wx::RadioButton.new(self, Wx::ID_ANY, 'Locate', :style => Wx::RB_GROUP)
|
33
|
+
# The Testers' statuses
|
34
|
+
# The list of [ StaticBitmap, StaticText ] used to represent Testers' state
|
35
|
+
# list< [ Wx::StaticBitmap, Wx::StaticText ] >
|
36
|
+
@TesterComponents = []
|
37
|
+
@DepUserChoice.DepDesc.Testers.each do |iTesterInfo|
|
38
|
+
iTesterName, iTesterContent = iTesterInfo
|
39
|
+
@TesterComponents << [
|
40
|
+
Wx::StaticBitmap.new(self, Wx::ID_ANY, Wx::Bitmap.new),
|
41
|
+
Wx::StaticText.new(self, Wx::ID_ANY, "#{iTesterName}: #{iTesterContent}")
|
42
|
+
]
|
43
|
+
end
|
44
|
+
# The buttons affecting ContextModifiers
|
45
|
+
# The list of Buttons used to affect ContextModifiers
|
46
|
+
# list< Wx::Button >
|
47
|
+
lACMComponents = []
|
48
|
+
@DepUserChoice.AffectingContextModifiers.each do |iCMName|
|
49
|
+
lACMComponents << Wx::Button.new(self, Wx::ID_ANY, "Change #{iCMName}")
|
50
|
+
end
|
51
|
+
|
52
|
+
# The ignore part
|
53
|
+
@RBIgnore = Wx::RadioButton.new(self, Wx::ID_ANY, 'Ignore')
|
54
|
+
|
55
|
+
# The install part
|
56
|
+
@RBInstall = Wx::RadioButton.new(self, Wx::ID_ANY, 'Install')
|
57
|
+
# The list of installers info
|
58
|
+
# list< [ RadioButton, StaticBitmap, list< RadioButton > ] >
|
59
|
+
@InstallerComponents = []
|
60
|
+
# First, create the installers radio buttons before their respective destinations radio buttons.
|
61
|
+
# This is done this way to ensure correct radio buttons grouping
|
62
|
+
@DepUserChoice.DepDesc.Installers.each do |iInstallerInfo|
|
63
|
+
iInstallerName, iInstallerContent, iContextModifiers = iInstallerInfo
|
64
|
+
lRBInstaller = nil
|
65
|
+
if (@InstallerComponents.empty?)
|
66
|
+
# First item of the group
|
67
|
+
lRBInstaller = Wx::RadioButton.new(self, Wx::ID_ANY, "#{iInstallerName} - #{iInstallerContent}", :style => Wx::RB_GROUP)
|
68
|
+
else
|
69
|
+
lRBInstaller = Wx::RadioButton.new(self, Wx::ID_ANY, "#{iInstallerName} - #{iInstallerContent}")
|
70
|
+
end
|
71
|
+
# Icon of the installer
|
72
|
+
lIconName = "#{@IconsDir}/Dependency.png"
|
73
|
+
# TODO: Accept more data formats
|
74
|
+
lInstallerIconName = "#{@Installer.RDILibDir}/Plugins/Installers/Icons/#{iInstallerName}.png"
|
75
|
+
if (File.exists?(lInstallerIconName))
|
76
|
+
lIconName = lInstallerIconName
|
77
|
+
end
|
78
|
+
@InstallerComponents << [
|
79
|
+
lRBInstaller,
|
80
|
+
Wx::StaticBitmap.new(self, Wx::ID_ANY, Wx::Bitmap.new(lIconName)),
|
81
|
+
[]
|
82
|
+
]
|
83
|
+
end
|
84
|
+
lIdxInstaller = 0
|
85
|
+
@DepUserChoice.DepDesc.Installers.each do |iInstallerInfo|
|
86
|
+
iInstallerName, iInstallerContent, iContextModifiers = iInstallerInfo
|
87
|
+
lDestinationComponents = @InstallerComponents[lIdxInstaller][2]
|
88
|
+
@Installer.accessPlugin('Installers', iInstallerName) do |iPlugin|
|
89
|
+
iPlugin.PossibleDestinations.each do |iDestInfo|
|
90
|
+
iFlavour, iLocation = iDestInfo
|
91
|
+
lFlavourText = nil
|
92
|
+
lDestLocation = iLocation
|
93
|
+
case iFlavour
|
94
|
+
when DEST_LOCAL
|
95
|
+
lFlavourText = 'Local'
|
96
|
+
when DEST_SYSTEM
|
97
|
+
lFlavourText = 'System'
|
98
|
+
when DEST_USER
|
99
|
+
lFlavourText = 'User'
|
100
|
+
when DEST_TEMP
|
101
|
+
lFlavourText = 'Temporary'
|
102
|
+
when DEST_OTHER
|
103
|
+
lFlavourText = 'Other'
|
104
|
+
lDestLocation = "Choose #{iLocation}"
|
105
|
+
else
|
106
|
+
logBug "Unknown flavour ID: #{iFlavour}"
|
107
|
+
lFlavourText = 'Unknown'
|
108
|
+
end
|
109
|
+
if (lDestinationComponents.empty?)
|
110
|
+
# First destination radio button
|
111
|
+
lDestinationComponents << Wx::RadioButton.new(self, Wx::ID_ANY, "#{lFlavourText} - #{lDestLocation}", :style => Wx::RB_GROUP)
|
112
|
+
else
|
113
|
+
lDestinationComponents << Wx::RadioButton.new(self, Wx::ID_ANY, "#{lFlavourText} - #{lDestLocation}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
lIdxInstaller += 1
|
118
|
+
end
|
119
|
+
|
120
|
+
# Put them into sizers
|
121
|
+
lMainSizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
122
|
+
lMainSizer.add_item(@RBLocate, :proportion => 0)
|
123
|
+
|
124
|
+
lLocateSizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
125
|
+
lLocateSizer.add_item([16,0], :proportion => 0)
|
126
|
+
|
127
|
+
lLocateChoicesSizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
128
|
+
@TesterComponents.each do |iTesterComponentsList|
|
129
|
+
lSB, lST = iTesterComponentsList
|
130
|
+
lTesterSizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
131
|
+
lTesterSizer.add_item(lSB, :proportion => 0)
|
132
|
+
lTesterSizer.add_item([8,0], :proportion => 0)
|
133
|
+
lTesterSizer.add_item(lST, :proportion => 0)
|
134
|
+
lLocateChoicesSizer.add_item(lTesterSizer, :proportion => 0)
|
135
|
+
end
|
136
|
+
lACMComponents.each do |iACMButton|
|
137
|
+
lLocateChoicesSizer.add_item(iACMButton, :proportion => 0)
|
138
|
+
end
|
139
|
+
|
140
|
+
lLocateSizer.add_item(lLocateChoicesSizer, :proportion => 0)
|
141
|
+
|
142
|
+
lMainSizer.add_item(lLocateSizer, :proportion => 0)
|
143
|
+
lMainSizer.add_item([0,16], :proportion => 0)
|
144
|
+
lMainSizer.add_item(@RBIgnore, :proportion => 0)
|
145
|
+
lMainSizer.add_item([0,16], :proportion => 0)
|
146
|
+
lMainSizer.add_item(@RBInstall, :proportion => 0)
|
147
|
+
|
148
|
+
lInstallSizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
149
|
+
lInstallSizer.add_item([16,0], :proportion => 0)
|
150
|
+
|
151
|
+
lInstallersListSizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
152
|
+
@InstallerComponents.each do |iInstallerComponentsInfo|
|
153
|
+
lRBInstaller, lSBIcon, lRBListDests = iInstallerComponentsInfo
|
154
|
+
|
155
|
+
lInstallerChoiceSizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
156
|
+
lInstallerChoiceSizer.add_item(lRBInstaller, :proportion => 0)
|
157
|
+
lInstallerChoiceSizer.add_item(lSBIcon, :proportion => 0)
|
158
|
+
|
159
|
+
lInstallersListSizer.add_item(lInstallerChoiceSizer, :proportion => 0)
|
160
|
+
|
161
|
+
lDestinationsListWithTabSizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
|
162
|
+
lDestinationsListWithTabSizer.add_item([16,0], :proportion => 0)
|
163
|
+
|
164
|
+
lDestinationsListSizer = Wx::BoxSizer.new(Wx::VERTICAL)
|
165
|
+
lRBListDests.each do |iRBDestination|
|
166
|
+
lDestinationsListSizer.add_item(iRBDestination, :proportion => 0)
|
167
|
+
end
|
168
|
+
|
169
|
+
lDestinationsListWithTabSizer.add_item(lDestinationsListSizer, :proportion => 0)
|
170
|
+
|
171
|
+
lInstallersListSizer.add_item(lDestinationsListWithTabSizer, :proportion => 0)
|
172
|
+
end
|
173
|
+
|
174
|
+
lInstallSizer.add_item(lInstallersListSizer, :proportion => 0)
|
175
|
+
|
176
|
+
lMainSizer.add_item(lInstallSizer, :proportion => 0)
|
177
|
+
|
178
|
+
self.sizer = lMainSizer
|
179
|
+
self.fit
|
180
|
+
|
181
|
+
# Set events
|
182
|
+
# Click on "Locate"
|
183
|
+
evt_radiobutton(@RBLocate) do |iEvent|
|
184
|
+
@DepUserChoice.setLocate
|
185
|
+
refreshComponents
|
186
|
+
end
|
187
|
+
# Click on any of the ACM
|
188
|
+
lACMIdx = 0
|
189
|
+
lACMComponents.each do |iACMButton|
|
190
|
+
# Clone indexes for them to be persistent in the code block
|
191
|
+
lACMIdxCloned = lACMIdx
|
192
|
+
evt_button(iACMButton) do |iEvent|
|
193
|
+
# Call the correct LocationSelector
|
194
|
+
@DepUserChoice.affectContextModifier(@DepUserChoice.AffectingContextModifiers[lACMIdxCloned])
|
195
|
+
refreshComponents
|
196
|
+
end
|
197
|
+
lACMIdx += 1
|
198
|
+
end
|
199
|
+
# Click on "Ignore"
|
200
|
+
evt_radiobutton(@RBIgnore) do |iEvent|
|
201
|
+
@DepUserChoice.setIgnore
|
202
|
+
refreshComponents
|
203
|
+
end
|
204
|
+
# Click on "Install"
|
205
|
+
evt_radiobutton(@RBInstall) do |iEvent|
|
206
|
+
@DepUserChoice.setInstaller(0, 0)
|
207
|
+
refreshComponents
|
208
|
+
end
|
209
|
+
# Click on any of the installers
|
210
|
+
lIdxInstaller = 0
|
211
|
+
@InstallerComponents.each do |iInstallerComponentsInfo|
|
212
|
+
# Clone the indexes to make them persistent in the code block
|
213
|
+
lIdxInstallerCloned = lIdxInstaller
|
214
|
+
lRBInstaller, lSBIcon, lRBListDests = iInstallerComponentsInfo
|
215
|
+
evt_radiobutton(lRBInstaller) do |iEvent|
|
216
|
+
@DepUserChoice.setInstaller(lIdxInstallerCloned, 0)
|
217
|
+
refreshComponents
|
218
|
+
end
|
219
|
+
# Click on any of the destinations
|
220
|
+
lIdxDest = 0
|
221
|
+
lRBListDests.each do |iRBDestination|
|
222
|
+
lIdxDestCloned = lIdxDest
|
223
|
+
evt_radiobutton(iRBDestination) do |iEvent|
|
224
|
+
@DepUserChoice.setInstaller(lIdxInstallerCloned, lIdxDestCloned)
|
225
|
+
# If it is DEST_OTHER, call the LocationSelector
|
226
|
+
@Installer.accessPlugin('Installers', @DepUserChoice.DepDesc.Installers[lIdxInstallerCloned][0]) do |iPlugin|
|
227
|
+
iFlavour, iLocation = iPlugin.PossibleDestinations[lIdxDestCloned]
|
228
|
+
if (iFlavour == DEST_OTHER)
|
229
|
+
@DepUserChoice.selectOtherInstallLocation(iLocation)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
refreshComponents
|
233
|
+
end
|
234
|
+
lIdxDest += 1
|
235
|
+
end
|
236
|
+
lIdxInstaller += 1
|
237
|
+
end
|
238
|
+
|
239
|
+
# Refresh the components
|
240
|
+
refreshComponents
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
# Refresh components
|
245
|
+
def refreshComponents
|
246
|
+
# Testers icons
|
247
|
+
lIdxTester = 0
|
248
|
+
@TesterComponents.each do |iTesterComponentsList|
|
249
|
+
iSBStatus, iSTTitle = iTesterComponentsList
|
250
|
+
# Check if the Tester is resolved
|
251
|
+
if (@DepUserChoice.ResolvedTesters.has_key?(lIdxTester))
|
252
|
+
iSBStatus.bitmap, lError = getBitmapFromURL("#{@IconsDir}/ValidOK.png")
|
253
|
+
else
|
254
|
+
iSBStatus.bitmap, lError = getBitmapFromURL("#{@IconsDir}/ValidKO.png")
|
255
|
+
end
|
256
|
+
lIdxTester += 1
|
257
|
+
end
|
258
|
+
# Selections
|
259
|
+
@RBLocate.set_value(@DepUserChoice.Locate)
|
260
|
+
@RBIgnore.set_value(@DepUserChoice.Ignore)
|
261
|
+
@RBInstall.set_value(@DepUserChoice.IdxInstaller != nil)
|
262
|
+
lIdxInstaller = 0
|
263
|
+
@InstallerComponents.each do |iInstallerComponentsInfo|
|
264
|
+
lRBInstaller, lSBIcon, lRBListDests = iInstallerComponentsInfo
|
265
|
+
lRBInstaller.set_value((@DepUserChoice.IdxInstaller == lIdxInstaller))
|
266
|
+
lIdxDest = 0
|
267
|
+
lRBListDests.each do |iRBDestination|
|
268
|
+
iRBDestination.set_value(
|
269
|
+
((@DepUserChoice.IdxInstaller == lIdxInstaller) and
|
270
|
+
(@DepUserChoice.IdxDestination == lIdxDest))
|
271
|
+
)
|
272
|
+
# Change the text if it is DEST_OTHER
|
273
|
+
@Installer.accessPlugin('Installers', @DepUserChoice.DepDesc.Installers[lIdxInstaller][0]) do |iPlugin|
|
274
|
+
iFlavour, iLocation = iPlugin.PossibleDestinations[lIdxDest]
|
275
|
+
if (iFlavour == DEST_OTHER)
|
276
|
+
# If it is the current one, use OtherLocation
|
277
|
+
if ((@DepUserChoice.IdxInstaller == lIdxInstaller) and
|
278
|
+
(@DepUserChoice.IdxDestination == lIdxDest))
|
279
|
+
iRBDestination.label = "Other (#{@DepUserChoice.OtherLocation})"
|
280
|
+
else
|
281
|
+
iRBDestination.label = "Other (Choose #{iLocation})"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
lIdxDest += 1
|
286
|
+
end
|
287
|
+
lIdxInstaller += 1
|
288
|
+
end
|
289
|
+
# Fit again, as some labels might have changed
|
290
|
+
self.fit
|
291
|
+
# Notify refresh
|
292
|
+
@NotifierControl.notifyRefresh(self)
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|