qtbindings 4.6.3.4 → 4.8.3.0

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