1#!/usr/bin/env kross 2 3# Load the Qt4-QtRuby module. 4begin 5 require 'Qt' 6rescue LoadError 7 raise "Failed to load the required QtRuby module. Please install Qt4-QtRuby." 8end 9 10# Load the Words scripting module. 11begin 12 require 'Words' 13rescue LoadError 14 # If loading failed (cause the script was not executed from within 15 # a running Words instance) we try to load the Kross module and 16 # ask it to load the Words module for us. 17 require 'Kross' 18 Words = Kross.module('Words') 19 20 # Testcase to fill Words with some content. You are also able to e.g. 21 # load a document here with "Words.document().openUrl('/path/file.odt')" 22 mytextframeset1 = Words.addTextFrameSet("myFirstTextFrame") 23 mytextframeset1.addTextFrame() 24 mytextframeset1.document().setHtml("<h1>First Header</h1><p>Some text</p><p>Some more text with <b>bold</b> and <i>italic</i> and <u>underline</u> to test the stuff.</p>") 25 mytextframeset2 = Words.addTextFrameSet("mySecondTextFrame") 26 mytextframeset2.addTextFrame() 27 mytextframeset2.document().setHtml("<h1>Second Header</h1><h2>First Sub Header</h2><p>Some text.</p><h2>Second Sub Header</h2><p>Some text.</p>") 28end 29 30######################################################################### 31# Pages - Each item is able to provide different pages 32 33# The Page interface class. 34class Page 35 def initialize(label) 36 @label = label 37 end 38 def label 39 return @label 40 end 41 def createWidget(parent) 42 return nil 43 end 44end 45 46# The PropertyPage class implements properties displayed within a table. 47class PropertyPage < Page 48 49 class Property 50 def initialize(name, value) 51 @name = name 52 @value = value 53 end 54 def name 55 return @name.to_s 56 end 57 def value 58 return @value.to_s 59 end 60 end 61 62 def initialize(label, properties = []) 63 super(label) 64 @properties = properties 65 end 66 67 def createWidget(parent) 68 table = Qt::TableWidget.new(parent) 69 table.setColumnCount(2) 70 table.setHorizontalHeaderLabels( ["Name","Value"] ) 71 table.verticalHeader().hide 72 table.alternatingRowColors = true 73 #table.horizontalHeader().resizeSections( Qt::HeaderView::ResizeToContents ) 74 table.horizontalHeader().setStretchLastSection(true) 75 #table.setEditTriggers( Qt::AbstractItemView::AllEditTriggers ) 76 table.setEditTriggers( Qt::AbstractItemView::NoEditTriggers ) 77 #@table.setSortingEnabled(true) 78 for property in @properties 79 rows = table.rowCount 80 table.insertRow(rows) 81 table.setItem(rows, 0, Qt::TableWidgetItem.new( property.name )) 82 table.setItem(rows, 1, Qt::TableWidgetItem.new( property.value )) 83 end 84 return table 85 end 86 87 def addProperty(property) 88 @properties.push(property) 89 end 90 91end 92 93# The TextEditPage class implements a simple texteditor. 94class TextEditPage < Page 95 def initialize(label, text = "") 96 super(label) 97 @text = text 98 end 99 def createWidget(parent) 100 edit = Qt::TextEdit.new(parent) 101 if @text 102 edit.plainText = @text.to_s 103 end 104 edit.readOnly = true 105 return edit 106 end 107end 108 109# The TextBrowserPage class implements a simple browser. 110class TextBrowserPage < Page 111 def initialize(label, text = "") 112 super(label) 113 @text = text 114 end 115 def createWidget(parent) 116 edit = Qt::TextBrowser.new(parent) 117 if @text 118 edit.html = @text.to_s 119 end 120 edit.readOnly = true 121 return edit 122 end 123end 124 125######################################################################### 126# Items displayed within the TreeModel. 127 128# Item is the interface class for all items. 129class Item 130 131 def initialize(parentitem = nil, data = nil) 132 @parentitem = parentitem 133 @data = data 134 @childitems = [] 135 @pages = [] 136 end 137 138 def parent 139 return @parentitem 140 end 141 142 def hasChildren 143 return @childitems.length > 0 144 end 145 146 def child(row) 147 return @childitems[row] 148 end 149 150 def childCount 151 return @childitems.length 152 end 153 154 def row 155 #if !@parentitem.nil? 156 # return @parentitem.childitems.index(self) 157 #end 158 return 0 159 end 160 161 def page(index) 162 return @pages[index] 163 end 164 165 def pageCount 166 return @pages.length 167 end 168 169end 170 171# FrameItem for Words Frame objects. 172class FrameItem < Item 173 174 class TextFrameItem < Item 175 def initialize(parentitem, textframe) 176 super(parentitem, textframe) 177 #cursor = textframe.firstCursorPosition() 178 for i in 0..(textframe.childFrameCount() - 1) 179 f = textframe.childFrame(i) 180 if f 181 puts "TextFrameItem %s" % f.to_s 182 @childitems.push( TextFrameItem.new(self, f) ) 183 end 184 end 185 if @data.text 186 @pages.push( TextEditPage.new("Text", @data.text) ) 187 end 188 end 189 def data(column) 190 #return Qt::Variant.new( "TextFrame %i-%i" % [@data.firstPosition(),@data.lastPosition()] ) 191 return Qt::Variant.new( "TextFrame" ) 192 end 193 end 194 195 class TextListItem < Item 196 def initialize(parentitem, textlist) 197 super(parentitem, textlist) 198 if @data.text 199 @pages.push( TextEditPage.new("Text", @data.text) ) 200 end 201 end 202 def data(column) 203 return Qt::Variant.new( "TextList" ) 204 end 205 end 206 207 class TextTableItem < Item 208 def initialize(parentitem, texttable) 209 super(parentitem, texttable) 210 if @data.text 211 @pages.push( TextEditPage.new("Text", @data.text) ) 212 end 213 end 214 def data(column) 215 return Qt::Variant.new( "TextTable" ) 216 end 217 end 218 219 class TextDocumentItem < Item 220 def initialize(frameitem, textdoc) 221 super(frameitem, textdoc) 222 223 @pages.push( 224 PropertyPage.new("Properties", [ 225 PropertyPage::Property.new("width", @data.width), 226 PropertyPage::Property.new("height", @data.height), 227 PropertyPage::Property.new("pageCount", @data.pageCount), 228 PropertyPage::Property.new("isModified", @data.isModified), 229 ] ) 230 ) 231 232 varpage = PropertyPage.new("Variables") 233 for n in @data.variableNames 234 varpage.addProperty( PropertyPage::Property.new(n, @data.variableValue(n)) ) 235 end 236 @pages.push(varpage) 237 238 @pages.push( TextEditPage.new("Text", @data.toText) ) 239 @pages.push( TextEditPage.new("HTML", @data.toHtml) ) 240 @pages.push( TextEditPage.new("Style", @data.defaultStyleSheet) ) 241 @pages.push( TextBrowserPage.new("Preview", @data.toHtml) ) 242 243 @rootframe = textdoc.rootFrame 244 end 245 246 def hasChildren 247 return true 248 end 249 def child(row) 250 if @childitems.length <= 0 251 lazyLoadChildren() 252 end 253 return @childitems[row] 254 end 255 def childCount 256 if @childitems.length <= 0 257 lazyLoadChildren() 258 end 259 return @childitems.length 260 end 261 def data(column) 262 return Qt::Variant.new("Document") 263 end 264 265 def lazyLoadChildren 266 textcursor = @rootframe.firstCursorPosition() 267 addCurrentBlock(textcursor) 268 while textcursor.movePosition( textcursor.NextBlock ) 269 addCurrentBlock(textcursor) 270 end 271 end 272 def addCurrentBlock(textcursor) 273 if textcursor.currentTable() 274 @childitems.push( TextTableItem.new(self, textcursor.currentTable()) ) 275 elsif textcursor.currentList() 276 @childitems.push( TextListItem.new(self, textcursor.currentList()) ) 277 elsif textcursor.currentFrame() 278 @childitems.push( TextFrameItem.new(self, textcursor.currentFrame()) ) 279 end 280 end 281 end 282 283 def initialize(framesetitem, frame) 284 super(framesetitem, frame) 285 frameset = frame.frameSet 286 textdoc = frameset.document 287 if textdoc != 0 288 @childitems.push( TextDocumentItem.new(self, textdoc) ) 289 end 290 @pages.push( 291 PropertyPage.new("Properties", [ 292 PropertyPage::Property.new("width", @data.width), 293 PropertyPage::Property.new("shapeId", @data.shapeId), 294 PropertyPage::Property.new("visible", @data.isVisible), 295 PropertyPage::Property.new("rotation", @data.rotation), 296 PropertyPage::Property.new("width", @data.width), 297 PropertyPage::Property.new("height", @data.height), 298 PropertyPage::Property.new("positionX", @data.positionX), 299 PropertyPage::Property.new("positionY", @data.positionY), 300 PropertyPage::Property.new("zIndex", @data.zIndex), 301 ] ) 302 ) 303 end 304 305 def data(column) 306 return Qt::Variant.new( @data.shapeId().to_s ) 307 end 308 309end 310 311# FramesetItem for Words FrameSet objects. 312class FramesetItem < Item 313 314 def initialize(rootitem, frameset) 315 super(rootitem, frameset) 316 for i in 0..(frameset.frameCount() - 1) 317 f = frameset.frame(i) 318 if f 319 puts "FramesetItem frame=%s" % f.to_s 320 @childitems.push( FrameItem.new(self, f) ) 321 end 322 end 323 @pages.push( 324 PropertyPage.new("Properties", [ 325 PropertyPage::Property.new("name", @data.name), 326 PropertyPage::Property.new("frameCount", @data.frameCount), 327 PropertyPage::Property.new("isText", @data.document != 0), 328 ] ) 329 ) 330 331 end 332 333 def data(column) 334 return Qt::Variant.new( @data.name().to_s ) 335 end 336 337end 338 339# Rootitem within the TreeModel. 340class RootItem < Item 341 342 def initialize 343 super(nil, nil) 344 for i in 0..(Words.frameSetCount() - 1) 345 f = Words.frameSet(i) 346 if f 347 puts "RootItem %s" % f.to_s 348 @childitems.push( FramesetItem.new(self, f) ) 349 end 350 end 351 end 352 353 def data(column) 354 return Qt::Variant.new 355 end 356 357end 358 359######################################################################### 360# TreeModel - The model that handles the items. 361 362class TreeModel < Qt::AbstractItemModel 363 364 def initialize(parent) 365 super(parent) 366 @rootItem = RootItem.new 367 end 368 369 def columnCount(parent) 370 return 1 371 end 372 373 def flags(index) 374 if !index.valid? 375 return Qt::ItemIsEnabled 376 end 377 return Qt::ItemIsEnabled | Qt::ItemIsSelectable 378 end 379 380 def index(row, column, parent) 381 if !parent.valid? 382 parentItem = @rootItem 383 else 384 parentItem = parent.internalPointer 385 end 386 childItem = parentItem.child(row) 387 if !childItem.nil? 388 return createIndex(row, column, childItem) 389 end 390 return Qt::ModelIndex.new 391 end 392 393 def parent(index) 394 if index.valid? 395 parentItem = index.internalPointer.parent 396 if parentItem != @rootItem 397 return createIndex(parentItem.row, 0, parentItem) 398 end 399 end 400 return Qt::ModelIndex.new 401 end 402 403 def data(index, role) 404 if !index.valid? 405 return Qt::Variant.new 406 end 407 if role == Qt::DisplayRole 408 item = index.internalPointer 409 return item.data(index.column) 410 end 411 return Qt::Variant.new 412 end 413 414 def rowCount(parent) 415 if !parent.valid? 416 parentItem = @rootItem 417 else 418 parentItem = parent.internalPointer 419 end 420 return parentItem.childCount 421 end 422 423 def hasChildren(parent) 424 if !parent.valid? 425 parentItem = @rootItem 426 else 427 parentItem = parent.internalPointer 428 end 429 return parentItem.hasChildren 430 end 431 432end 433 434######################################################################### 435# Dialog - The main dialog window. 436 437class Dialog < Qt::Dialog 438 439 slots 'slotCurrentChanged(const QModelIndex&, const QModelIndex&)' 440 441 def recursiveExpand(level, modelindex) 442 level += 1 443 for i in 0..(@view.model.rowCount(modelindex) - 1) 444 idx = @view.model().index(i,0,modelindex) 445 if level <= 2 446 @view.expand( idx ) 447 recursiveExpand(level, idx) 448 end 449 end 450 end 451 452 def initialize 453 super() 454 self.windowTitle = 'Document Tree' 455 456 layout = Qt::HBoxLayout.new 457 setLayout(layout) 458 splitter = Qt::Splitter.new(self) 459 layout.addWidget(splitter) 460 461 @view = Qt::TreeView.new(self) 462 @view.header().setVisible(false) 463 @view.model = TreeModel.new(self) 464 @view.selectionModel = Qt::ItemSelectionModel.new(@view.model) 465 recursiveExpand(0, Qt::ModelIndex.new) 466 #@view.expandAll 467 @view.show 468 splitter.addWidget(@view) 469 470 editorwidget = Qt::Widget.new(self) 471 editorlayout = Qt::VBoxLayout.new 472 editorlayout.setMargin(0) 473 editorwidget.setLayout(editorlayout) 474 #@label = Qt::Label.new(editorwidget) 475 #editorlayout.addWidget(@label) 476 @tab = Qt::TabWidget.new(self) 477 editorlayout.addWidget(@tab) 478 #layout.addSpacing(10) 479 #layout.addStretch(1) 480 splitter.addWidget(editorwidget) 481 editorwidget.resize( Qt::Size.new(360, 400).expandedTo( editorwidget.minimumSizeHint ) ) 482 483 connect(@view.selectionModel, SIGNAL('currentChanged(const QModelIndex&, const QModelIndex&)'), self, SLOT('slotCurrentChanged(const QModelIndex&, const QModelIndex&)')) 484 resize( Qt::Size.new(700, 520).expandedTo( minimumSizeHint ) ); 485 end 486 487 def slotCurrentChanged(current, prev) 488 while @tab.count > 0; @tab.removeTab(0); end 489 if current.valid? 490 #@label.text = @view.model().data(current, Qt::DisplayRole) 491 for i in 0..(current.internalPointer.pageCount() - 1) 492 page = current.internalPointer.page(i) 493 widget = page.createWidget(@tab) 494 if widget != nil 495 @tab.addTab(widget, page.label) 496 end 497 end 498 end 499 end 500 501end 502 503dialog = Dialog.new 504dialog.exec 505