1 | #!/usr/bin/env python |
---|
2 | # |
---|
3 | # main.py |
---|
4 | # Copyright (C) Yasumichi Akahoshi 2011 <yasumichi@vinelinux.org> |
---|
5 | # |
---|
6 | # pygtk-rpminstall is free software: you can redistribute it and/or modify it |
---|
7 | # under the terms of the GNU General Public License as published by the |
---|
8 | # Free Software Foundation, either version 3 of the License, or |
---|
9 | # (at your option) any later version. |
---|
10 | # |
---|
11 | # pygtk-rpminstall is distributed in the hope that it will be useful, but |
---|
12 | # WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
---|
14 | # See the GNU General Public License for more details. |
---|
15 | # |
---|
16 | # You should have received a copy of the GNU General Public License along |
---|
17 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
18 | |
---|
19 | |
---|
20 | from gi.repository import Gtk, GdkPixbuf, Gdk |
---|
21 | import os, sys, fnmatch |
---|
22 | import rpm |
---|
23 | import progress, dependdialog, installed |
---|
24 | |
---|
25 | #Comment the first line and uncomment the second before installing |
---|
26 | #or making the tarball (alternatively, use project variables) |
---|
27 | UI_FILE = "ui/rpminstall.ui" |
---|
28 | RPM_ICON = "ui/icons/rpm.png" |
---|
29 | |
---|
30 | rpmtsCallback_fd = None |
---|
31 | |
---|
32 | # |
---|
33 | # Class for main window |
---|
34 | # |
---|
35 | class GUI: |
---|
36 | def __init__(self): |
---|
37 | # Build user interface |
---|
38 | self.builder = Gtk.Builder() |
---|
39 | self.builder.set_translation_domain('rpminstall') |
---|
40 | self.builder.add_from_file(os.path.join (os.path.dirname(__file__), UI_FILE)) |
---|
41 | self.builder.connect_signals(self) |
---|
42 | self.build_file_list_view() |
---|
43 | |
---|
44 | # add packages from command line arguments |
---|
45 | self.add_packages_from_argv () |
---|
46 | |
---|
47 | # Show window |
---|
48 | self.window = self.builder.get_object('window') |
---|
49 | self.window.show_all() |
---|
50 | |
---|
51 | # |
---|
52 | # Build file list view |
---|
53 | # |
---|
54 | def build_file_list_view(self): |
---|
55 | # Build Column |
---|
56 | column_file = Gtk.TreeViewColumn(_("RPM Package")) |
---|
57 | |
---|
58 | renderer_pixbuf = Gtk.CellRendererPixbuf() |
---|
59 | column_file.pack_start(renderer_pixbuf,False) |
---|
60 | column_file.add_attribute(renderer_pixbuf,"pixbuf",0) |
---|
61 | |
---|
62 | renderer_text = Gtk.CellRendererText() |
---|
63 | column_file.pack_start(renderer_text, True) |
---|
64 | column_file.add_attribute(renderer_text, "text", 1) |
---|
65 | |
---|
66 | file_list_view = self.builder.get_object('file_list_view') |
---|
67 | file_list_view.append_column(column_file) |
---|
68 | |
---|
69 | # Enable multi select |
---|
70 | selection = file_list_view.get_selection() |
---|
71 | selection.set_mode(Gtk.SelectionMode.MULTIPLE) |
---|
72 | |
---|
73 | self.progress = 0 |
---|
74 | |
---|
75 | # |
---|
76 | # add packages from command line arguments |
---|
77 | # |
---|
78 | def add_packages_from_argv(self): |
---|
79 | file_liststore = self.builder.get_object('file_liststore') |
---|
80 | pixbuf = GdkPixbuf.Pixbuf.new_from_file(os.path.join(os.path.dirname(__file__), RPM_ICON)) |
---|
81 | |
---|
82 | for arg in sys.argv: |
---|
83 | for pattern in self.get_installable_pattern_list(): |
---|
84 | if fnmatch.fnmatchcase(arg, pattern): |
---|
85 | file_liststore.append([pixbuf, arg]) |
---|
86 | break |
---|
87 | |
---|
88 | # |
---|
89 | # Callback when add button is clicked |
---|
90 | # |
---|
91 | def add_button_clicked(self, window): |
---|
92 | dialog = Gtk.FileChooserDialog(_("Please choose a file"), window, |
---|
93 | Gtk.FileChooserAction.OPEN, |
---|
94 | (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, |
---|
95 | Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) |
---|
96 | dialog.set_select_multiple(True) |
---|
97 | |
---|
98 | filter_text = Gtk.FileFilter() |
---|
99 | filter_text.set_name(_("RPM Binary Package")) |
---|
100 | for pattern in self.get_installable_pattern_list(): |
---|
101 | filter_text.add_pattern(pattern) |
---|
102 | |
---|
103 | dialog.add_filter(filter_text) |
---|
104 | if dialog.run() == Gtk.ResponseType.OK: |
---|
105 | file_liststore = self.builder.get_object('file_liststore') |
---|
106 | pixbuf = GdkPixbuf.Pixbuf.new_from_file(os.path.join(os.path.dirname(__file__), RPM_ICON)) |
---|
107 | for fname in dialog.get_filenames(): |
---|
108 | file_liststore.append([pixbuf, fname]) |
---|
109 | |
---|
110 | dialog.destroy() |
---|
111 | |
---|
112 | # |
---|
113 | # Callback when delete button is clicked |
---|
114 | # |
---|
115 | def delete_button_clicked(self, button): |
---|
116 | file_list_view = self.builder.get_object('file_list_view') |
---|
117 | file_liststore = self.builder.get_object('file_liststore') |
---|
118 | selection = file_list_view.get_selection() |
---|
119 | while True: |
---|
120 | (unused, paths) = selection.get_selected_rows() |
---|
121 | if paths == []: |
---|
122 | break |
---|
123 | file_liststore.remove( file_liststore.get_iter(paths[0]) ) |
---|
124 | |
---|
125 | # |
---|
126 | # Callback when cancel button is clicked |
---|
127 | # |
---|
128 | def cancel_button_clicked(self,button): |
---|
129 | Gtk.main_quit() |
---|
130 | |
---|
131 | # |
---|
132 | # Callback when cancel button is clicked |
---|
133 | # |
---|
134 | def execute_button_clicked(self,widget): |
---|
135 | count = 0 |
---|
136 | file_liststore = self.builder.get_object('file_liststore') |
---|
137 | |
---|
138 | ts = rpm.TransactionSet() |
---|
139 | |
---|
140 | newer_installed = [] |
---|
141 | treeiter = file_liststore.get_iter_first() |
---|
142 | while treeiter != None: |
---|
143 | filename = str(file_liststore[treeiter][1]) |
---|
144 | fd = os.open(filename, os.O_RDONLY) |
---|
145 | h = None |
---|
146 | try: |
---|
147 | h = ts.hdrFromFdno(fd) |
---|
148 | installed_info = self.check_installed(h) |
---|
149 | if installed_info == None: |
---|
150 | ts.addInstall(h, filename, 'u') |
---|
151 | h = None |
---|
152 | os.close(fd) |
---|
153 | count = count + 1 |
---|
154 | else: |
---|
155 | newer_installed.append(installed_info) |
---|
156 | except rpm.error, e: |
---|
157 | print str(e) |
---|
158 | |
---|
159 | treeiter = file_liststore.iter_next(treeiter) |
---|
160 | |
---|
161 | if len(newer_installed) > 0: |
---|
162 | dialog = installed.InstalledDialog(newer_installed) |
---|
163 | dialog.run() |
---|
164 | |
---|
165 | if count > 0: |
---|
166 | if self.possibility_of_installation(ts): |
---|
167 | ts.order() |
---|
168 | dialog = progress.ProgressDialog(self.window, ts) |
---|
169 | response = dialog.run() |
---|
170 | else: |
---|
171 | dialog = Gtk.MessageDialog(self.window, 0, Gtk.MessageType.INFO, |
---|
172 | Gtk.ButtonsType.OK, _("No package is selected.")) |
---|
173 | dialog.run() |
---|
174 | dialog.destroy() |
---|
175 | |
---|
176 | # |
---|
177 | # check installed version |
---|
178 | # |
---|
179 | def check_installed(self, h): |
---|
180 | ts = rpm.TransactionSet() |
---|
181 | pkg_ds = h.dsOfHeader() |
---|
182 | for inst_h in ts.dbMatch('name', h['name']): |
---|
183 | inst_ds = inst_h.dsOfHeader() |
---|
184 | if pkg_ds.EVR() <= inst_ds.EVR(): |
---|
185 | return (h['name'], pkg_ds.EVR(), inst_ds.EVR()) |
---|
186 | else: |
---|
187 | return None |
---|
188 | |
---|
189 | # |
---|
190 | # check dependency |
---|
191 | # |
---|
192 | def possibility_of_installation(self, ts): |
---|
193 | unresolved_dependencies = ts.check() |
---|
194 | if not unresolved_dependencies: |
---|
195 | return True |
---|
196 | else: |
---|
197 | dialog = dependdialog.DependDialog(unresolved_dependencies) |
---|
198 | dialog.run () |
---|
199 | return False |
---|
200 | |
---|
201 | # |
---|
202 | # get installable pattern list |
---|
203 | # |
---|
204 | def get_installable_pattern_list(self): |
---|
205 | pattern_list = [ '*.noarch.rpm' ] |
---|
206 | |
---|
207 | arch = rpm.expandMacro('%{_arch}') |
---|
208 | if arch == 'i386': |
---|
209 | pattern_list.append('*.i?86.rpm') |
---|
210 | elif arch == 'x86_64': |
---|
211 | pattern_list.append('*.i?86.rpm') |
---|
212 | pattern_list.append('*.x86_64.rpm') |
---|
213 | else: |
---|
214 | pattern_list.append('*.' + arch + '.rpm') |
---|
215 | |
---|
216 | return pattern_list |
---|
217 | |
---|
218 | # |
---|
219 | # Callback when Gui is destroied |
---|
220 | # |
---|
221 | def destroy(window, self): |
---|
222 | Gtk.main_quit() |
---|
223 | |
---|