kgem 0.1.0

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/lib/gemviews.rb ADDED
@@ -0,0 +1,554 @@
1
+ require 'cgi'
2
+ require 'benchmark'
3
+ require 'date'
4
+
5
+
6
+
7
+
8
+ #--------------------------------------------------------------------------------
9
+ #--------------------------------------------------------------------------------
10
+ #
11
+ #
12
+ class DockGemViewer < Qt::Object
13
+ attr_reader :previewWin
14
+ def initialize(parent, detailView, filesView, terminalWin, previewWin)
15
+ super(nil)
16
+ @parent = parent
17
+ @detailView = detailView
18
+ @filesView = filesView
19
+ @terminalWin = terminalWin
20
+ @downloadWatcher = []
21
+ @installWatcher = []
22
+ @previewWin = previewWin
23
+
24
+ @detailView.setGetSpecProc(
25
+ Proc.new do |g|
26
+ gem = GemItem::getGemfromPath(g.name)
27
+ setDetail(gem)
28
+ end
29
+ )
30
+ end
31
+
32
+
33
+ def setDetail(gem)
34
+ @detailView.setDetail(gem)
35
+ end
36
+
37
+ def setFiles(files)
38
+ @filesView.setFiles(files)
39
+ end
40
+
41
+ def setInstallWin(win)
42
+ @installWin = win
43
+ end
44
+
45
+ # @param ex : Exception.
46
+ def setError(gem, ex)
47
+ @detailView.setError(gem, ex)
48
+ end
49
+
50
+ def setPreviewProc(proc)
51
+ @filesView.setPreviewProc(proc)
52
+ end
53
+
54
+ def addDownloadWatcher(watcher)
55
+ @downloadWatcher << watcher
56
+ end
57
+
58
+ def notifyDownload
59
+ @downloadWatcher.each do |w| w.notifyDownload end
60
+ end
61
+
62
+ def addInstallWatcher(watcher)
63
+ @installWatcher << watcher
64
+ end
65
+
66
+ def notifyInstall
67
+ @installWatcher.each do |w| w.notifyInstall end
68
+ end
69
+
70
+ #--------------------------------------------------------------
71
+ #
72
+ #
73
+ slots :cleanUp
74
+ def cleanUp
75
+ res = KDE::MessageBox::questionYesNo(
76
+ @parent, Qt::Object.i18n('Clean up old versions of installed gems in the local repository. Clean Up ?'), Qt::Object.i18n('Clean Up.'))
77
+ return unless res == KDE::MessageBox::Yes
78
+
79
+ args = %w{ cleanup }
80
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
81
+ @terminalWin.processStart(cmd, args) do |ret|
82
+ if ret == 0 then
83
+ passiveMessage("Cleaned Up old versions of gems (system).")
84
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
85
+ @terminalWin.processStart(cmd, args, \
86
+ i18n("Cleaned Up old versions of gems (in user).")) do |ret|
87
+ notifyInstall
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+
94
+ slots :pristineAll
95
+ def pristineAll
96
+ res = KDE::MessageBox::questionYesNo(
97
+ @parent, Qt::Object.i18n(<<-EOF
98
+ Restores installed gems to pristine condition from files located in the gem cache.
99
+
100
+ The pristine command compares the installed gems with the contents of the cached gem and restores any files that don't match the cached gem's copy. If you have made modifications to your installed gems, the pristine command will revert them. After all the gem's files have been checked all bin.
101
+
102
+ Pristine All ?
103
+ EOF
104
+ ), Qt::Object.i18n('Pristine All.'))
105
+ return unless res == KDE::MessageBox::Yes
106
+
107
+ args = %w{ pristine --all }
108
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
109
+ @terminalWin.processStart(cmd, args, i18n("Pristined All."))
110
+ end
111
+
112
+ slots :checkAlien
113
+ def checkAlien
114
+ cmd = "gem"
115
+ args = %w{ check --alien }
116
+ @terminalWin.visible = true
117
+ @terminalWin.processStart(cmd, args, i18n("checked alien see Output Dock window for detail."))
118
+ end
119
+
120
+
121
+ slots :checkStale
122
+ def checkStale
123
+ lines = %x{ gem stale }.split(/\n/)
124
+ stales = []
125
+ lines.each do |l|
126
+ gv, t = l.split(/ at /, 2)
127
+ atime = Date.parse(t.strip)
128
+ m = gv.match(/(.*)-([^\-]+)/)
129
+ stales << StaleGemItem.new( m[1].strip, m[2].strip, atime )
130
+ end
131
+ @installWin.setStaleTime(stales)
132
+ end
133
+
134
+ slots :testGem
135
+ def testGem(gem)
136
+ spec = gem.spec
137
+ return unless spec
138
+ args = %w{ check --test }
139
+ args += [ spec.name, '--version', spec.version.version ]
140
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
141
+ @terminalWin.processStart(cmd, args, i18n("Tested the gem. Please check output window"))
142
+ end
143
+
144
+ slots :updateSystem
145
+ def updateSystem
146
+ args = %w{ update --system }
147
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
148
+ @terminalWin.processStart(cmd, args, i18n("Updated All Gems."))
149
+ end
150
+
151
+ def upgradable(gem)
152
+ time = Benchmark.realtime { gem.availableVersions }
153
+ puts "Time : " + time.to_s
154
+ gem.availableVersions.first != gem.nowVersion
155
+ end
156
+
157
+ slots :updateAll
158
+ def updateAll
159
+ @updateDlg ||= UpdateDlg.new
160
+ return unless @updateDlg.confirmUpdateAll
161
+
162
+ args = @updateDlg.makeUpdateArgs
163
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
164
+ @terminalWin.processStart(cmd, args, i18n("Updated All Gems (in system).")) do |ret|
165
+ if ret == 0 then
166
+ args << '--user-install'
167
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
168
+ @terminalWin.processStart(cmd, args, i18n("Updated All Gems (in user).")) do |ret|
169
+ notifyInstall
170
+ notifyDownload
171
+ end
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+ def updateGem(gem)
178
+ unless upgradable(gem) then
179
+ res = KDE::MessageBox::questionYesNo(@parent, Qt::Object.i18n('Already Installed Latest Gem. install older version ?'), Qt::Object.i18n('Already Installed latest Gem.'))
180
+ return unless res == KDE::MessageBox::Yes
181
+ end
182
+
183
+ @updateDlg ||= UpdateDlg.new
184
+ return unless @updateDlg.selectOption(gem)
185
+
186
+ args = @updateDlg.makeUpdateArgs
187
+ if gem.installedLocal? then
188
+ args.push( '--user-install' )
189
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
190
+ else
191
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
192
+ end
193
+ @terminalWin.processStart(cmd, args, "Installed #{gem.package}") do |ret|
194
+ notifyInstall
195
+ notifyDownload
196
+ end
197
+ end
198
+
199
+ def install(gem, localFlag)
200
+ return unless gem
201
+
202
+ @selectInstallVerDlg ||= SelectInstallVerDlg.new
203
+ return unless @selectInstallVerDlg.selectVersion(gem)
204
+
205
+ args = @selectInstallVerDlg.makeInstallArgs(localFlag)
206
+ if Settings.installInSystemDirFlag then
207
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
208
+ else
209
+ args.push( '--user-install' )
210
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
211
+ end
212
+ @terminalWin.processStart(cmd, args, "Installed #{gem.package}") do |ret|
213
+ notifyInstall
214
+ notifyDownload
215
+ end
216
+ end
217
+
218
+ def uninstall(gem)
219
+ return unless gem
220
+
221
+ args = [ 'uninstall' ]
222
+ args.push( gem.package )
223
+ puts "installedLocal? : " + gem.installedLocal?.inspect
224
+ if gem.installedLocal? then
225
+ args.push( '--user-install' )
226
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
227
+ else
228
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
229
+ end
230
+ @terminalWin.processStart(cmd, args, "Uninstalled #{gem.package}") do |ret|
231
+ notifyInstall
232
+ end
233
+ end
234
+
235
+ def download(gem)
236
+ @selectDownloadVerDlg ||= SelectDownloadVerDlg.new
237
+ return unless @selectDownloadVerDlg.selectVersion(gem)
238
+
239
+ if Settings.autoFetchFlag then
240
+ dir = Settings.autoFetchDir.pathOrUrl
241
+ else
242
+ dir = KDE::FileDialog::getExistingDirectory(Settings.autoFetchDir)
243
+ return unless dir
244
+ Settings.autoFetchDir.setUrl(dir)
245
+ end
246
+ Dir.chdir(dir)
247
+ cmd = 'gem'
248
+ args = @selectDownloadVerDlg.makeDownloadArgs
249
+ @terminalWin.processStart(cmd, args, "Downloaded #{gem.package}" \
250
+ "Download #{gem.package} failed.") do |ret|
251
+ notifyDownload
252
+ end
253
+ end
254
+
255
+ def generateRdoc(gem)
256
+ @GenerateRdocDlg ||= GenerateRdocDlg.new
257
+ return unless @GenerateRdocDlg.exec == Qt::Dialog::Accepted
258
+
259
+ args = @GenerateRdocDlg.makeRdocArgs(gem)
260
+ return unless args
261
+ puts "installedLocal? : " + gem.installedLocal?.inspect
262
+ if !@GenerateRdocDlg.all? and gem.installedLocal? then
263
+ cmd = "#{APP_DIR}/bin/gemcmdwin.rb"
264
+ else
265
+ cmd = "#{APP_DIR}/bin/gemcmdwin-super.rb"
266
+ end
267
+ @terminalWin.processStart(cmd, args, "Generated rdoc/ri for #{gem.package}")
268
+ end
269
+
270
+ def getGemPaths
271
+ @gemPath ||= %x{gem environment gempath}.chomp.split(/:/)
272
+ end
273
+
274
+ def findGemPath(path)
275
+ paths = getGemPaths
276
+ file = nil
277
+ paths.find do |p|
278
+ file = p + path
279
+ File.exist? file
280
+ end
281
+ file
282
+ end
283
+
284
+ def viewGemRdoc(gem)
285
+ return unless gem
286
+
287
+ # make rdoc path
288
+ pkg = gem.package
289
+ ver = gem.nowVersion
290
+ url = findGemPath('/doc/' + pkg + '-' + ver + '/rdoc/index.html')
291
+ cmd= Mime::services('.html').first.exec
292
+ cmd.gsub!(/%\w+/, url)
293
+ fork do exec(cmd) end
294
+ end
295
+
296
+ def viewGemDir(gem)
297
+ return unless gem
298
+
299
+ pkg = gem.package
300
+ ver = gem.nowVersion
301
+ url = findGemPath('/gems/' + pkg + '-' + ver)
302
+ cmd = KDE::MimeTypeTrader.self.query('inode/directory').first.exec[/\w+/]
303
+ cmd += " " + url
304
+ fork do exec(cmd) end
305
+ end
306
+ end
307
+
308
+ #--------------------------------------------------------------------
309
+ #
310
+ #
311
+ class DetailWin < Qt::DockWidget
312
+ def initialize(parent)
313
+ super('Detail', parent)
314
+ self.objectName = 'Detail'
315
+ createWidget
316
+ end
317
+
318
+ def createWidget
319
+ @textPart = Qt::TextBrowser.new
320
+ connect(@textPart, SIGNAL('anchorClicked(const QUrl&)')) do |url|
321
+ cmd= Mime::services('.html').first.exec
322
+ cmd.gsub!(/%\w+/, url.toString.shellescape)
323
+ fork do exec(cmd) end
324
+ end
325
+ @textPart.openLinks = false
326
+ @moreInfoBtn = KDE::PushButton.new(i18n('More Information'))
327
+ connect(@moreInfoBtn, SIGNAL(:clicked), self, SLOT(:moreInfo))
328
+ @moreInfoBtn.hide
329
+
330
+ lw = VBoxLayoutWidget.new do |l|
331
+ l.addWidget(@textPart)
332
+ l.addWidget(@moreInfoBtn)
333
+ end
334
+ setWidget(lw)
335
+ end
336
+
337
+ class HtmlStr < String
338
+ def insertHtml(str)
339
+ self.concat(str)
340
+ end
341
+
342
+ def insertItem(name, value)
343
+ if value && !value.empty?
344
+ insertHtml("<tr><td>#{name}</td><td>: #{CGI.escapeHTML(value)}</td></tr>")
345
+ end
346
+ end
347
+
348
+ def insertDep(name, value, val2='')
349
+ insertHtml("<tr><td>#{name}</td><td>&nbsp; #{CGI.escapeHTML(value)}</td><td> &nbsp;: #{CGI.escapeHTML(val2)}</td></tr>")
350
+ end
351
+
352
+ def insertUrl(name, url)
353
+ if url && !url.empty?
354
+ insertHtml("<tr><td>#{name}</td><td>:<a href='#{url}'>#{url}</a></td></tr>")
355
+ end
356
+ end
357
+ end
358
+
359
+ public
360
+ def setDetail(gem)
361
+ return unless gem
362
+
363
+ @currentGem = gem
364
+ @textPart.clear
365
+ @moreInfoBtn.hide
366
+ return unless gem
367
+ spec = gem.spec
368
+ html = HtmlStr.new
369
+ html.insertHtml("<font size='+1'>#{gem.package}</font><br>")
370
+ html.insertHtml(gem.summary.gsub(/\n/,'<br>'))
371
+ html.insertHtml("<table>")
372
+ author = gem.author
373
+ if author.kind_of? Array then
374
+ author = author.join(', ')
375
+ end
376
+ html.insertItem('Author', author)
377
+ html.insertItem('Version', gem.version)
378
+ if spec then
379
+ html.insertItem('Date', spec.date.strftime('%F'))
380
+ end
381
+ html.insertUrl('Rubyforge', gem.rubyforge)
382
+ html.insertUrl('homepage', gem.homepage)
383
+ html.insertUrl('platform', gem.platform) if gem.platform !~ /ruby/i
384
+ html.insertHtml("</table>")
385
+ if spec then
386
+ deps = spec.dependencies
387
+ if deps.size > 0 then
388
+ html.insertHtml('Dependencies')
389
+ html.insertHtml("<table>")
390
+ deps.each do |dep|
391
+ html.insertDep('&nbsp;'*2 + dep.name, dep.requirement.to_s, dep.type.to_s)
392
+ end
393
+ html.insertHtml("</table>")
394
+ end
395
+ end
396
+ if spec then
397
+ if spec.description then
398
+ html.insertHtml('<p>'+spec.description.gsub(/\n/,'<br>'))
399
+ end
400
+ else
401
+ @moreInfoBtn.show
402
+ end
403
+
404
+ @textPart.insertHtml(html)
405
+ end
406
+
407
+ # @param ex : Exception.
408
+ def setError(gem, ex)
409
+ @textPart.clear
410
+ @textPart.append(<<-EOF
411
+ #{ex.to_s} : Can not get #{gem.package} gem specification data.
412
+ EOF
413
+ )
414
+ end
415
+
416
+ def setGetSpecProc(proc)
417
+ @getSpecProc = proc
418
+ end
419
+
420
+ slots :moreInfo
421
+ def moreInfo
422
+ @getSpecProc.call(@currentGem) if @getSpecProc
423
+ end
424
+ end
425
+
426
+ #--------------------------------------------------------------------
427
+ #
428
+ #
429
+ class FileListWin < Qt::DockWidget
430
+ def initialize(parent)
431
+ super('Files', parent)
432
+ self.objectName = 'Files'
433
+ @previewProc = nil
434
+ createWidget
435
+ end
436
+
437
+ def createWidget
438
+ @fileList = Qt::ListWidget.new
439
+ connect(@fileList, SIGNAL('itemClicked(QListWidgetItem *)'), self,
440
+ SLOT('itemClicked(QListWidgetItem *)'))
441
+ setWidget(@fileList)
442
+ end
443
+
444
+ def setFiles(files)
445
+ @fileList.clear
446
+ @fileList.addItems(files) if files
447
+ end
448
+
449
+ def setPreviewProc(proc)
450
+ @previewProc = proc
451
+ end
452
+
453
+ slots 'itemClicked(QListWidgetItem *)'
454
+ def itemClicked(item)
455
+ @previewProc.call(item) if @previewProc
456
+ end
457
+ end
458
+
459
+ #--------------------------------------------------------------------
460
+ #
461
+ #
462
+ class TerminalWin < Qt::DockWidget
463
+ slots 'processfinished(int,QProcess::ExitStatus)'
464
+ slots 'cleanup(QObject*)'
465
+ slots :processReadyRead
466
+
467
+ def initialize(parent)
468
+ super('Output', parent)
469
+ self.objectName = 'Terminal'
470
+ createWidget
471
+ processSetup
472
+
473
+ connect(self, SIGNAL('destroyed(QObject*)'), self, SLOT('cleanup(QObject*)'))
474
+ end
475
+
476
+ def createWidget
477
+ @textEdit = Qt::TextEdit.new
478
+ @textEdit.readOnly = true
479
+ @clearBtn = KDE::PushButton.new(KDE::Icon.new('edit-clear'), i18n('Clear'))
480
+ connect(@clearBtn, SIGNAL(:clicked), @textEdit, SLOT(:clear))
481
+
482
+ lw = VBoxLayoutWidget.new do |l|
483
+ l.addWidget(@textEdit)
484
+ l.addWidgets(nil, @clearBtn)
485
+ end
486
+ setWidget(lw)
487
+ end
488
+
489
+ def processSetup
490
+ @process = Qt::Process.new(self)
491
+ @process.setProcessChannelMode(Qt::Process::MergedChannels)
492
+ connect(@process, SIGNAL('finished(int,QProcess::ExitStatus)'),
493
+ self, SLOT('processfinished(int,QProcess::ExitStatus)'))
494
+ connect(@process, SIGNAL(:readyReadStandardOutput),
495
+ self, SLOT(:processReadyRead))
496
+ connect(@process, SIGNAL(:readyReadStandardError),
497
+ self, SLOT(:processReadyRead))
498
+ end
499
+
500
+ def write(text)
501
+ @textEdit.append(text)
502
+ end
503
+
504
+ def processStart(cmd, args, successMsg='Successed', failMsg='Failed', &block)
505
+ unless @process.state == Qt::Process::NotRunning
506
+ msg = "process is already running."
507
+ write(msg)
508
+ KDE::MessageBox::information(self, msg)
509
+ return
510
+ end
511
+ msg = "execute : " + cmd.inspect + " " + args.join(' ').inspect + "\n"
512
+ print msg
513
+ write(msg)
514
+ @successMsg = successMsg
515
+ @failMsg = failMsg
516
+ @error = 0
517
+ @canceled = 1
518
+ @process.start(cmd, args)
519
+ @finishProc = block
520
+ end
521
+
522
+ def processfinished(exitCode, exitStatus)
523
+ write( @process.readAll.data )
524
+ # puts "exitCode:#{exitCode}, @error:#{@error}, @canceled:#{@canceled}"
525
+ ret = exitCode | @error | @canceled
526
+ msg = ret == 0 ? @successMsg : @failMsg
527
+ passiveMessage(msg)
528
+ if @finishProc
529
+ @finishProc.call(ret)
530
+ end
531
+ end
532
+
533
+ def checkErrorInMsg(msg)
534
+ @canceled = 0
535
+ if msg =~ /Exiting [\w\s]+ exit_code (\d)/i
536
+ @error = $1.to_i
537
+ end
538
+ end
539
+
540
+ def processReadyRead
541
+ lines = @process.readAll.data
542
+ lines.gsub!(/~?ScimInputContextPlugin.*?\n/, '')
543
+ unless lines.empty?
544
+ print lines
545
+ write( lines )
546
+ checkErrorInMsg(lines)
547
+ end
548
+ end
549
+
550
+ def cleanup(obj)
551
+ puts "killing all process."
552
+ @process.kill
553
+ end
554
+ end