RDI 0.1.0.20091020
Sign up to get free protection for your applications and to get access to all the features.
- 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
|