qtbindings 4.6.3.4 → 4.8.3.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.
Files changed (75) hide show
  1. data/KNOWN_ISSUES.txt +19 -5
  2. data/README.txt +119 -93
  3. data/Rakefile +28 -27
  4. data/examples/desktop/systray/window.rb +43 -47
  5. data/examples/draganddrop/dropsite/dropsitewidget.rb +10 -9
  6. data/examples/mainwindows/mdi/mainwindow.rb +4 -4
  7. data/examples/network/broadcastsender/sender.rb +3 -1
  8. data/examples/qtscribble/scribble.rb +270 -0
  9. data/examples/ruboids/LICENSE.txt +58 -0
  10. data/examples/run_all.rb +1 -0
  11. data/examples/textedit/textedit.rb +150 -0
  12. data/examples/widgets/scribble/scribblearea.rb +19 -19
  13. data/ext/cmake/modules/BasicFindPackageVersion.cmake.in +30 -0
  14. data/ext/cmake/modules/FindLibraryWithDebug.cmake +113 -0
  15. data/ext/cmake/modules/FindPhonon.cmake +71 -0
  16. data/ext/cmake/modules/FindQImageBlitz.cmake +51 -0
  17. data/ext/cmake/modules/FindRuby.cmake +17 -17
  18. data/ext/cmake/modules/MacroOptionalFindPackage.cmake +6 -26
  19. data/ext/cmake/modules/MacroWriteBasicCMakeVersionFile.cmake +22 -0
  20. data/ext/cmake/modules/SmokeConfig.cmake.in +109 -0
  21. data/ext/generator/cmake/BasicFindPackageVersion.cmake.in +30 -0
  22. data/ext/generator/cmake/CMakeLists.txt +24 -0
  23. data/ext/generator/cmake/FindLibraryWithDebug.cmake +113 -0
  24. data/ext/generator/cmake/FindPhonon.cmake +71 -0
  25. data/ext/generator/cmake/FindQImageBlitz.cmake +51 -0
  26. data/ext/generator/cmake/FindQScintilla.cmake +57 -0
  27. data/ext/generator/cmake/FindQwt5.cmake +104 -0
  28. data/ext/generator/cmake/HandleImportedTargetsInCMakeRequiredLibraries.cmake +85 -0
  29. data/ext/generator/cmake/MacroLogFeature.cmake +146 -0
  30. data/ext/generator/cmake/MacroOptionalAddBindings.cmake +47 -0
  31. data/ext/generator/cmake/MacroOptionalFindPackage.cmake +28 -0
  32. data/ext/generator/cmake/MacroWriteBasicCMakeVersionFile.cmake +22 -0
  33. data/ext/generator/cmake/SmokeConfig.cmake.in +109 -0
  34. data/ext/generator/config.h +25 -0
  35. data/ext/generator/generatorpreprocessor.cpp +60 -41
  36. data/ext/generator/generators/dump/CMakeLists.txt +5 -0
  37. data/ext/generator/generators/smoke/CMakeLists.txt +5 -0
  38. data/ext/generator/generators/smoke/globals.h +3 -1
  39. data/ext/generator/generators/smoke/helpers.cpp +21 -2
  40. data/ext/generator/generators/smoke/writeSmokeDataFile.cpp +26 -1
  41. data/ext/generator/main.cpp +5 -1
  42. data/ext/generator/options.cpp +1 -0
  43. data/ext/generator/options.h +1 -0
  44. data/ext/generator/parser/CMakeLists.txt +10 -1
  45. data/ext/generator/parser/parser.cpp +6 -6
  46. data/ext/generator/parser/parser.h +2 -12
  47. data/ext/generator/parser/parsesession.cpp +1 -0
  48. data/ext/generator/parser/rpp/CMakeLists.txt +6 -0
  49. data/ext/generator/parser/rpp/chartools.cpp +3 -3
  50. data/ext/generator/parser/rpp/chartools.h +3 -1
  51. data/ext/generator/parser/rpp/pp-scanner.cpp +2 -1
  52. data/ext/generator/parser/rpp/tests/CMakeLists.txt +4 -0
  53. data/ext/generator/parser/tests/CMakeLists.txt +16 -0
  54. data/ext/generator/smoke.h +557 -0
  55. data/ext/generator/smokegen_string.h +43 -0
  56. data/ext/generator/type.cpp +15 -6
  57. data/ext/generator/type_compiler.cpp +2 -0
  58. data/ext/ruby/qtruby/src/qtruby.cpp +147 -143
  59. data/ext/ruby/qttest/qttesthandlers.cpp +1 -0
  60. data/ext/smoke/qtcore/QtGuess.txt +23 -25
  61. data/ext/smoke/qtcore/smokeconfig.xml +1 -0
  62. data/ext/smoke/qtdbus/smokeconfig.xml +2 -0
  63. data/ext/smoke/qtgui/smokeconfig.xml +14 -4
  64. data/ext/smoke/qthelp/smokeconfig.xml +1 -0
  65. data/ext/smoke/qtmultimedia/smokeconfig.xml +1 -0
  66. data/ext/smoke/qtnetwork/smokeconfig.xml +2 -0
  67. data/ext/smoke/qtopengl/smokeconfig.xml +1 -0
  68. data/ext/smoke/qtsql/smokeconfig.xml +1 -0
  69. data/ext/smoke/qtsvg/smokeconfig.xml +1 -0
  70. data/ext/smoke/qtwebkit/smokeconfig.xml +3 -0
  71. data/extconf.rb +37 -23
  72. data/lib/Qt/qtruby4.rb +4 -4
  73. data/lib/Qt4.rb +1 -1
  74. data/lib/qtbindings_version.rb +2 -2
  75. metadata +50 -40
@@ -39,7 +39,7 @@ class DropArea < Qt::Label
39
39
  setAlignment(Qt::AlignCenter)
40
40
  setAcceptDrops(true)
41
41
  setAutoFillBackground(true)
42
- clear()
42
+ clear()
43
43
  end
44
44
 
45
45
  def dragEnterEvent(event)
@@ -50,28 +50,29 @@ class DropArea < Qt::Label
50
50
  # emit changed(event.mimeData())
51
51
  end
52
52
 
53
- def dragMoveEvent(event)
54
- event.acceptProposedAction()
55
- end
53
+ def dragMoveEvent(event)
54
+ event.acceptProposedAction()
55
+ end
56
56
 
57
57
  def dropEvent(event)
58
58
  mimeData = event.mimeData()
59
- if mimeData.hasText
59
+ if mimeData.hasText
60
60
  setText(mimeData.text())
61
61
  setTextFormat(Qt::PlainText)
62
62
  end
63
63
 
64
-
65
64
  formats = mimeData.formats()
66
65
  formats.each do |format|
67
- if format.startsWith("image/")
68
- pixmap = createPixmap(mimeData.data(format), format)
66
+ if format.start_with?("image/")
67
+ pixmap = Qt::Pixmap.new
68
+ pixmap.loadFromData(mimeData.data(format), format)
69
69
  if !pixmap.nil?
70
70
  setPixmap(pixmap)
71
71
  break
72
72
  end
73
73
  end
74
- text = createPlainText(mimeData.data(format), format)
74
+ #text = createPlainText(mimeData.data(format), format)
75
+ text = mimeData.data(format).to_s
75
76
  if !text.empty?
76
77
  setText(text)
77
78
  break
@@ -84,7 +84,7 @@ class MainWindow < Qt::MainWindow
84
84
  if !fileName.nil?
85
85
  existing = findMdiChild(fileName)
86
86
  if !existing.nil?
87
- @mdiArea.activeSubWindow = existing
87
+ @mdiArea.setActiveSubWindow(existing)
88
88
  return
89
89
  end
90
90
 
@@ -352,10 +352,10 @@ class MainWindow < Qt::MainWindow
352
352
  def findMdiChild(fileName)
353
353
  canonicalFilePath = Qt::FileInfo.new(fileName).canonicalFilePath()
354
354
 
355
- @mdiArea.windowList().each do |window|
356
- mdiChild = window
355
+ @mdiArea.subWindowList().each do |window|
356
+ mdiChild = window.widget
357
357
  if mdiChild.currentFile() == canonicalFilePath
358
- return mdiChild
358
+ return window
359
359
  end
360
360
  end
361
361
  return nil
@@ -63,7 +63,9 @@ class Sender < Qt::Dialog
63
63
  def broadcastDatagram()
64
64
  @statusLabel.text = tr("Now broadcasting datagram %d" % @messageNo)
65
65
  datagram = Qt::ByteArray.new("Broadcast message %d" % @messageNo)
66
- @udpSocket.writeDatagram(datagram.data(), datagram.size(),
66
+ @udpSocket.writeDatagram(datagram,
67
+ # method_missing with this syntax
68
+ #@udpSocket.writeDatagram(datagram.data(), datagram.size(),
67
69
  Qt::HostAddress.new(Qt::HostAddress::Broadcast), 45454)
68
70
  @messageNo += 1
69
71
  end
@@ -0,0 +1,270 @@
1
+ #!/usr/bin/env ruby -w
2
+
3
+ #
4
+ # A class that lets the user draw with the mouse. The
5
+ # window knows how to redraw itself.
6
+ #
7
+
8
+ require 'Qt'
9
+
10
+ class ScribbleArea < Qt::Widget
11
+
12
+ slots "setColor(QColor)", "slotLoad(const QString&)", "slotSave(const QString&)", "slotClearArea()"
13
+
14
+ #
15
+ # The constructor. Initializes the member variables.
16
+ #
17
+ def initialize(parent)
18
+ super(parent)
19
+ # initialize member variables
20
+ @_buffer = Qt::Pixmap.new()
21
+ @_last = Qt::Point.new()
22
+ @_currentcolor = Qt::black
23
+
24
+ # don't blank the window before repainting
25
+ setAttribute( Qt::WA_NoBackground )
26
+
27
+ # create a pop-up menu
28
+ @_popupmenu = Qt::Menu.new()
29
+ @_popupmenu.addAction( "&Clear", self, SLOT( "slotClearArea()" ) )
30
+ end
31
+
32
+ #
33
+ # This slot sets the curren color for the scribble area. It will be
34
+ # connected with the colorChanged( Qt::Color ) signal from the
35
+ # ScribbleWindow.
36
+ #
37
+ def setColor( new_color )
38
+ @_currentcolor = new_color
39
+ end
40
+
41
+ #
42
+ # This slot clears the drawing area by filling the off-screen buffer with
43
+ # white and copying it over to the window.
44
+ #
45
+ def slotClearArea()
46
+ # fill the off screen buffer with plain white
47
+ @_buffer.fill( white )
48
+
49
+ # and copy it over to the window
50
+ bitBlt( self, 0, 0, @_buffer )
51
+ end
52
+
53
+
54
+ #
55
+ # This method does the actual loading. It relies on Qt::Pixmap (and the
56
+ # underlying I/O machinery) to determine the filetype.
57
+ #
58
+ def slotLoad( filename )
59
+ if !@_buffer.load( filename )
60
+ Qt::MessageBox.warning( nil, "Load error", "Could not load file" )
61
+ end
62
+
63
+ repaint() # refresh the window
64
+ end
65
+
66
+
67
+ #
68
+ # This method does the actual saving. We hard-code the file type as
69
+ # BMP. Unix users might want to replace this with something like XPM.
70
+ #
71
+ def slotSave( filename )
72
+ if !@_buffer.save( filename, "BMP" )
73
+ Qt::MessageBox.warning( nil, "Save error", "Could not save file" )
74
+ end
75
+ end
76
+
77
+
78
+ #
79
+ # This method is called whenever the user presses the
80
+ # mouse over the window. It just records the position of the mouse
81
+ # at the time of the click.
82
+ #
83
+ def mousePressEvent(event)
84
+ if event.button() == RightButton
85
+ @_popupmenu.exec( Qt::Cursor.pos() )
86
+ else
87
+ @_last = event.pos() # retrieve the coordinates from the event
88
+ end
89
+ end
90
+
91
+
92
+ #
93
+ # The method is called whenever the usr moves the mouse
94
+ # while the mouse button is pressed. If we had called
95
+ # setMouseTracking(true) before, the method would also be called
96
+ # when the mouse was moved with any button pressed. We know that
97
+ # we haven't, and thus don't have to check whether any buttons are
98
+ # pressed.
99
+ #
100
+ def mouseMoveEvent(event)
101
+ # create a Qt::Painter object for drawing onto the window
102
+ windowpainter = Qt::Painter.new()
103
+ # and another Qt::Painter object for drawing int an off-screen pixmap
104
+ bufferpainter = Qt::Painter.new()
105
+
106
+ # start painting
107
+ windowpainter.begin( self ) # This painter paints onto the window
108
+ bufferpainter.begin( @_buffer ) # and this one paints in the buffer
109
+
110
+ # set a standard pen with the currently selected color
111
+ windowpainter.setPen( @_currentcolor )
112
+ bufferpainter.setPen( @_currentcolor )
113
+
114
+ # draw a line in both the window and the buffer
115
+ windowpainter.drawLine( @_last, event.pos() )
116
+ bufferpainter.drawLine( @_last, event.pos() )
117
+
118
+ # done with painting
119
+ windowpainter.end()
120
+ bufferpainter.end()
121
+
122
+ # remember the current mouse position
123
+ @_last = event.pos()
124
+ end
125
+
126
+ #
127
+ # This method is called whenever the widget needs
128
+ # painting, for example when it has been obscured and then revealed again.
129
+ #
130
+ def paintEvent(event)
131
+ bitBlt(self, 0, 0, @_buffer)
132
+ end
133
+
134
+ #
135
+ # This method get called whenever the widget needs
136
+ # painting, for example, when it has been obscured and then revealed again.
137
+ #
138
+ def resizeEvent(event)
139
+ save = Qt::Pixmap.new( @_buffer )
140
+ @_buffer = save.scaled(event.size.width, event.size.height)
141
+ @_buffer.fill( Qt::Color.new(Qt::white) )
142
+ drawPixmap( @_buffer, 0, 0, save )
143
+ end
144
+ end
145
+
146
+ class ScribbleWindow < Qt::Widget
147
+
148
+ slots "slotAbout()", "slotAboutQt()", "slotColorMenu(int)", "slotLoad()", "slotSave()"
149
+ signals "colorChanged(QColor)", "load(const QString&)", "save(const QString&)"
150
+
151
+ COLOR_MENU_ID_BLACK = 0
152
+ COLOR_MENU_ID_RED = 1
153
+ COLOR_MENU_ID_BLUE = 2
154
+ COLOR_MENU_ID_GREEN = 3
155
+ COLOR_MENU_ID_YELLOW = 4
156
+
157
+ def initialize()
158
+ super
159
+ # The next lines build the menu bar. We first create the menus
160
+ # one by one, then add them to the menu bar. #
161
+ @_menubar = Qt::MenuBar.new( self ) # create a menu bar
162
+
163
+ @_filemenu = @_menubar.addMenu( "&File" ) # create a file menu
164
+ @_filemenu.addAction( "&Load", self, SLOT( "slotLoad()" ) )
165
+ @_filemenu.addAction( "&Save", self, SLOT( "slotSave()" ) )
166
+ @_filemenu.addSeparator()
167
+ @_filemenu.addAction( "&Quit", $qApp, SLOT( "quit()" ) )
168
+
169
+ @_colormenu = @_menubar.addMenu( "&Color" ) # create a color menu
170
+ # @_colormenu.addAction( "B&lack", COLOR_MENU_ID_BLACK)
171
+ # @_colormenu.addAction( "&Red", COLOR_MENU_ID_RED)
172
+ # @_colormenu.addAction( "&Blue", COLOR_MENU_ID_BLUE)
173
+ # @_colormenu.addAction( "&Green", COLOR_MENU_ID_GREEN)
174
+ # @_colormenu.addAction( "&Yellow", COLOR_MENU_ID_YELLOW)
175
+ # Qt::Object.connect( @_colormenu, SIGNAL( "activated( int )" ),
176
+ # self, SLOT( "slotColorMenu( int )" ) )
177
+
178
+ @_helpmenu = @_menubar.addMenu( "&Help" ) # create a help menu
179
+ @_helpmenu.addAction( "&About QtScribble", self, SLOT( "slotAbout()" ) )
180
+ @_helpmenu.addAction( "&About Qt", self, SLOT( "slotAboutQt()" ) )
181
+
182
+ # We create a Qt::ScrollView and a ScribbleArea. The ScribbleArea will
183
+ # be managed by the scroll view.#
184
+ @_scrollview = Qt::ScrollArea.new( self )
185
+ @_scrollview.setGeometry( 0, @_menubar.height(),
186
+ width(), height() - @_menubar.height() )
187
+ @_scribblearea = ScribbleArea.new( @_scrollview )
188
+ @_scribblearea.setGeometry( 0, 0, 1000, 1000 )
189
+ # @_scrollview.addChild( @_scribblearea )
190
+ Qt::Object.connect( self, SIGNAL( "colorChanged(QColor)" ),
191
+ @_scribblearea, SLOT( "setColor(QColor)" ) )
192
+ Qt::Object.connect( self, SIGNAL( "save(const QString&)" ),
193
+ @_scribblearea, SLOT( "slotSave(const QString&)" ) )
194
+ Qt::Object.connect( self, SIGNAL( "load(const QString&)" ),
195
+ @_scribblearea, SLOT( "slotLoad(const QString&)" ) )
196
+ end
197
+
198
+ def resizeEvent( event )
199
+ # When the whole window is resized, we have to rearrange the geometry
200
+ # in the ScribbleWindow as well. Note that the ScribbleArea does not need
201
+ # to be changed.
202
+ @_scrollview.setGeometry( 0, @_menubar.height(),
203
+ width(), height() - @_menubar.height() )
204
+ end
205
+
206
+
207
+
208
+ def slotAbout()
209
+ Qt::MessageBox.information( self, "About QtScribble 5",
210
+ "This is the Scribble 5 application\n" +
211
+ "Copyright 1998 by Mathias Kalle Dalheimer\n")
212
+ end
213
+
214
+ def slotAboutQt()
215
+ Qt::MessageBox.aboutQt( self, "About Qt" )
216
+ end
217
+
218
+ def slotColorMenu( item )
219
+ case item
220
+ when COLOR_MENU_ID_BLACK
221
+ emit colorChanged( black )
222
+ when COLOR_MENU_ID_RED
223
+ emit colorChanged( darkRed )
224
+ when COLOR_MENU_ID_BLUE
225
+ emit colorChanged( darkBlue )
226
+ when COLOR_MENU_ID_GREEN
227
+ emit colorChanged( darkGreen )
228
+ when COLOR_MENU_ID_YELLOW
229
+ emit colorChanged( yellow )
230
+ end
231
+ end
232
+
233
+
234
+ #
235
+ # This is the slot for the menu item File/Load. It opens a
236
+ # Qt::FileDialog to ask the user for a filename, then emits a save()
237
+ # signal with the filename as parameter.
238
+ #
239
+ def slotLoad()
240
+ # Open a file dialog for loading. The default directory is the
241
+ # current directory, the filter *.bmp.
242
+ #
243
+ filename = Qt::FileDialog.getOpenFileName( ".", "*.bmp", self )
244
+ if !filename.nil?
245
+ emit load( filename )
246
+ end
247
+ end
248
+
249
+ #
250
+ # This is the slot for the menu item File/Load. It opens a
251
+ # Qt::FileDialog to ask the user for a filename, then emits a save()
252
+ # signal with the filename as parameter.
253
+ #
254
+ def slotSave()
255
+ # Open a file dialog for saving. The default directory is the
256
+ # current directory, the filter *.bmp.
257
+ #
258
+ filename = Qt::FileDialog.getSaveFileName( ".", "*.bmp", self )
259
+ if !filename.nil?
260
+ emit save( filename )
261
+ end
262
+ end
263
+ end
264
+
265
+ myapp = Qt::Application.new(ARGV)
266
+ mywidget = ScribbleWindow.new()
267
+ mywidget.setGeometry(50, 500, 400, 400)
268
+
269
+ mywidget.show()
270
+ myapp.exec()
@@ -0,0 +1,58 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see COPYING.txt file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
58
+
data/examples/run_all.rb CHANGED
@@ -5,6 +5,7 @@ windows = true if platform == 'mswin32' or platform == 'mingw32'
5
5
  files = Dir["**/main.rb"]
6
6
  files.each do |file|
7
7
  if windows
8
+ next if file.include?('qdbus') # because qdbus is Unix only
8
9
  command = "cd #{File.dirname(file).gsub('/', '\\')} && ruby -rubygems #{File.basename(file)}"
9
10
  else
10
11
  command = "cd #{File.dirname(file)} && ruby -rubygems #{File.basename(file)}"
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ require 'Qt'
4
+ require 'rexml/document'
5
+
6
+ require '../base/rui.rb'
7
+
8
+ class MyTextEditor < Qt::TextEdit
9
+ signals 'saved()'
10
+ slots 'insert_icon()', 'new()', 'open()', 'save_as()'
11
+ def initialize(w = nil)
12
+ @images = {}
13
+ @@next_image_id = 0
14
+ super(w)
15
+ self.setTextFormat(Qt::RichText)
16
+ end
17
+ def insert_richtext(richtext)
18
+ # todo, use a rand string
19
+ unique_string = '000___xxx123456789xxx___xxx123456789xxx___000'
20
+ insert(unique_string)
21
+ txt = self.text().gsub(unique_string, richtext)
22
+ self.setText(txt)
23
+ end
24
+ def next_image_id
25
+ @@next_image_id += 1
26
+ end
27
+ def load_image(fname, image_id)
28
+ pixmap = Qt::Pixmap.new(fname)
29
+ msfactory = Qt::MimeSourceFactory.defaultFactory
30
+ msfactory.setPixmap(image_id, pixmap)
31
+ @images[image_id] = fname
32
+ image_id
33
+ end
34
+ def insert_icon
35
+ fname = Qt::FileDialog.getOpenFileName
36
+ return if fname.nil?
37
+ image_id = "image_#{next_image_id}"
38
+ load_image(fname, image_id)
39
+ insert_richtext('<qt><img source="'+image_id+'"></qt>')
40
+ end
41
+ def createPopupMenu(pos) # virtual
42
+ pm = Qt::PopupMenu.new
43
+ pm.insertItem("Insert Image!", self, SLOT('insert_icon()'))
44
+ pm
45
+ end
46
+ def has_metadata
47
+ !@images.empty?
48
+ end
49
+ def metadata_fname(fname)
50
+ "#{fname}.metadata.xml"
51
+ end
52
+ def attempt_metadata_load(fname)
53
+ return unless File.exists?(metadata_fname(fname))
54
+ file = File.open(metadata_fname(fname))
55
+ @xmldoc = REXML::Document.new file
56
+ @xmldoc.root.elements.each("image") {
57
+ |image|
58
+ image_id = image.attributes["ident"]
59
+ img_fname = image.attributes["filename"]
60
+ load_image(img_fname, image_id)
61
+ }
62
+ end
63
+ def metadata_save_if_has(fname)
64
+ return if not has_metadata
65
+ metadata_doc = REXML::Document.new '<metadata/>'
66
+ @images.each {
67
+ |id, img_fname|
68
+ metadata_doc.root.add_element("image", {"filename"=>img_fname, "ident"=>id})
69
+ }
70
+ file = File.new(metadata_fname(fname), "w")
71
+ file.puts(metadata_doc)
72
+ file.close
73
+ end
74
+ def metadata_clear
75
+ @images = {}
76
+ end
77
+ def new(txt = "")
78
+ metadata_clear
79
+ self.setText(txt)
80
+ end
81
+ def open
82
+ fname = Qt::FileDialog.getOpenFileName
83
+ return if fname.nil?
84
+ unless File.exists?(fname)
85
+ Qt::MessageBox.critical(self, "File Does Not Exist", "Sorry, unable to find the requested file!")
86
+ return
87
+ end
88
+ return if fname.nil?
89
+ txt = File.open(fname).gets(nil)
90
+ metadata_clear
91
+ attempt_metadata_load(fname)
92
+ self.setText(txt)
93
+ end
94
+ def save_as
95
+ fname = Qt::FileDialog.getSaveFileName
96
+ return if fname.nil?
97
+ if File.exists?(fname)
98
+ Qt::MessageBox.critical(self, "File Already Exists", "Sorry, file already exists. Please choose a non-existing filename!")
99
+ return save_as
100
+ end
101
+ file = File.new(fname, "w")
102
+ file.puts(text())
103
+ file.close
104
+ metadata_save_if_has(fname)
105
+ emit saved()
106
+ end
107
+ end
108
+
109
+ class MyWidget < Qt::MainWindow
110
+ slots 'text_changed()', 'saved()'
111
+ def initialize()
112
+ super
113
+ @editor = MyTextEditor.new(self)
114
+ connect(@editor, SIGNAL('textChanged()'), self, SLOT('text_changed()'))
115
+ connect(@editor, SIGNAL('saved()'), self, SLOT('saved()'))
116
+
117
+ fileTools = Qt::ToolBar.new(self, "file operations")
118
+ fileMenu = Qt::PopupMenu.new(self)
119
+
120
+ actions = [
121
+ RAction.new("&New", Icons::FILE_NEW, @editor, SLOT('new()'), [fileTools, fileMenu]),
122
+ RAction.new("&Open...", Icons::FILE_OPEN, @editor, SLOT('open()'), [fileTools, fileMenu]),
123
+ @save = RAction.new("Save &As...", Icons::FILE_SAVE_AS, @editor, SLOT('save_as()'), [fileTools, fileMenu]),
124
+ RSeperator.new([fileMenu]),
125
+ RAction.new("E&xit", Icons::EXIT, $qApp, SLOT('quit()'), [fileMenu])
126
+ ]
127
+
128
+ build_actions(actions)
129
+
130
+ menubar = Qt::MenuBar.new(self)
131
+ menubar.insertItem("&File", fileMenu)
132
+
133
+ self.setCentralWidget(@editor)
134
+ end
135
+ def saved
136
+ @save.action.setEnabled(false)
137
+ end
138
+ def text_changed
139
+ @save.action.setEnabled(true)
140
+ end
141
+ end
142
+
143
+ a = Qt::Application.new(ARGV)
144
+
145
+ w = MyWidget.new
146
+ w.show
147
+
148
+ a.setMainWidget(w)
149
+ a.exec()
150
+ exit