Update with current status
[gnash.git] / gui / qt / Qt4Gui.cpp
blob8c9488253a9763aeea851616e7d531bb87af6406
1 // Qt4Gui.cpp: KDE4/Qt4 Gui implementation for Gnash window
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "gnashconfig.h"
23 #endif
25 #include <map>
27 #include <QMainWindow>
28 #include <QX11Info>
29 #include <QMenu>
30 #include <QMenuBar>
31 #include <QWidget>
32 #include <QCursor>
33 #include <QApplication>
34 #include <QPainter>
35 #include <QMouseEvent>
36 #include <QResizeEvent>
37 #include <QTimer>
38 #include <QEvent>
39 #include <QDialog>
40 #include <QDialogButtonBox>
41 #include <QLayout>
42 #include <QPushButton>
43 #include <QTreeWidget>
44 #include <QTreeWidgetItem>
45 #include <QStack>
46 #include <QTabWidget>
47 #include <QFrame>
48 #include <QLabel>
49 #include <QSlider>
50 #include <QLineEdit>
51 #include <QCheckBox>
52 #include <QLCDNumber>
53 #include <QSpinBox>
54 #include <QClipboard>
55 #include <QString>
56 #include <QDesktopWidget>
57 #include <QMessageBox>
59 #include "Range2d.h"
61 #include "movie_definition.h"
62 #include "log.h"
64 #include "gui.h"
65 #include "Qt4Gui.h"
66 #include "Qt4Gui.moc"
67 #include "Renderer.h"
68 #include "RunResources.h"
69 #include "GnashException.h"
71 // Macro for using gettext strings where Qt expects QStrings
72 #define _q(Str) QString::fromUtf8(_(Str))
74 extern "C" {
75 #include <X11/Xlib.h>
78 namespace gnash
81 Qt4Gui::Qt4Gui(unsigned long xid, float scale, bool loop, RunResources& r)
83 Gui(xid, scale, loop, r),
84 _numArgs(0),
85 _embedWidget(NULL),
86 _drawingWidget(NULL),
87 _interval(0),
88 _advanceTimer(0)
89 , fileMenu(NULL)
90 , propertiesAction(NULL)
91 , quitAction(NULL)
92 , editMenu(NULL)
93 , preferencesAction(NULL)
94 , movieControlMenu(NULL)
95 , playAction(NULL)
96 , pauseAction(NULL)
97 , stopAction(NULL)
98 , restartAction(NULL)
99 , viewMenu(NULL)
100 , refreshAction(NULL)
101 , fullscreenAction(NULL)
106 Qt4Gui::~Qt4Gui()
110 void
111 Qt4Gui::setClipboard(const std::string& copy)
113 QClipboard* cb = QApplication::clipboard();
114 assert(cb);
115 cb->setText(QString::fromStdString(copy));
118 bool
119 Qt4Gui::init(int /*argc*/, char ** /*argv*/[])
121 char** r = NULL;
123 _application.reset(new QApplication(_numArgs, r));
124 _window.reset(new QMainWindow());
125 _embedWidget = new EmbedWidget(*this);
126 _drawingWidget = _embedWidget->drawingWidget();
128 std::string renderer = _runResources.getRenderBackend();
130 if (renderer == "cairo") {
131 #ifdef RENDERER_CAIRO
132 log_debug("Using Cairo renderer");
133 _glue.reset(new Qt4CairoGlue());
134 #else
135 log_error(_("Cairo renderer not supported!"));
136 return false;
137 #endif
138 } else if (renderer == "opengl") {
139 #ifdef RENDERER_OPENGL
140 log_debug("Using OpenGL renderer");
141 _glue.reset(new Qt4OglGlue());
142 #else
143 log_error(_("OpenGL renderer not supported!"));
144 return false;
145 #endif
146 } else if (renderer == "agg") {
147 #ifdef RENDERER_AGG
148 log_debug("Using AGG renderer");
149 _glue.reset(new Qt4AggGlue());
150 #else
151 log_error(_("AGG renderer not supported!"));
152 return false;
153 #endif
155 else {
156 boost::format fmt = boost::format("Non-existent renderer %1% "
157 "specified") % renderer;
158 throw gnash::GnashException(fmt.str());
161 setupActions();
162 setupMenus();
164 if (!_xid) {
165 createMainMenu();
168 // Make sure key events are ready to be passed
169 // before the widget can receive them.
170 setupKeyMap();
172 return true;
175 bool
176 Qt4Gui::run()
178 return _application->exec();
181 bool
182 Qt4Gui::createWindow(const char* windowtitle, int width, int height,
183 int xPosition, int yPosition)
185 _width = width;
186 _height = height;
188 _drawingWidget->setMinimumSize(_width, _height);
190 // Enable receiving of mouse events.
191 _drawingWidget->setMouseTracking(true);
192 _drawingWidget->setFocusPolicy(Qt::StrongFocus);
193 _window->setWindowTitle(windowtitle);
194 _window->setWindowIcon(QIcon(PKGDATADIR"/GnashG.png"));
196 if(_xid) {
197 _embedWidget->embedInto(_xid);
198 _embedWidget->show();
199 // Adjust width and height to the window we're being embedded into...
200 XWindowAttributes winAttributes;
201 XGetWindowAttributes(QX11Info::display(), _xid, &winAttributes);
202 _width=winAttributes.width;
203 _height=winAttributes.height;
204 } else {
205 // The QMainWindow takes ownership of the widgets.
206 _window->setCentralWidget(_embedWidget);
207 if (xPosition > -1 || yPosition > -1)
208 _window->move(xPosition, yPosition);
209 _window->show();
212 _glue->prepDrawingArea(_drawingWidget);
214 _renderer.reset(_glue->createRenderHandler());
216 if (!_renderer.get()) {
217 return false;
220 _validbounds.setTo(0, 0, _width, _height);
221 _glue->initBuffer(_width, _height);
223 // log_debug("Setting renderer");
225 _runResources.setRenderer(_renderer);
227 // log_debug("Set renderer");
229 return true;
233 void
234 Qt4Gui::resizeWindow(int width, int height)
236 _width = width;
237 _height = height;
239 _drawingWidget->setMinimumSize(_width, _height);
242 void
243 Qt4Gui::popupMenu(const QPoint& point)
245 QMenu popupMenu(_drawingWidget);
246 popupMenu.addMenu(fileMenu);
247 popupMenu.addMenu(editMenu);
248 popupMenu.addMenu(movieControlMenu);
249 popupMenu.addMenu(viewMenu);
250 popupMenu.exec(point);
254 void
255 Qt4Gui::renderBuffer()
258 for (DrawBounds::const_iterator i = _drawbounds.begin(),
259 e = _drawbounds.end(); i != e; ++i) {
261 // it may happen that a particular range is out of the screen, which
262 // will lead to bounds==null.
263 if (i->isNull()) continue;
265 assert(i->isFinite());
267 _drawingWidget->update(i->getMinX(), i->getMinY(),
268 i->width(), i->height());
273 void
274 Qt4Gui::renderWidget(const QRect& updateRect)
276 // This call renders onto the widget using a QPainter,
277 // which *must only happen inside a paint event*.
278 _glue->render(updateRect);
281 void
282 Qt4Gui::setInvalidatedRegions(const InvalidatedRanges& ranges)
284 _renderer->set_invalidated_regions(ranges);
286 _drawbounds.clear();
288 for (size_t i = 0, e = ranges.size(); i != e; ++i) {
290 geometry::Range2d<int> bounds = Intersection(
291 _renderer->world_to_pixel(ranges.getRange(i)),
292 _validbounds);
294 // It may happen that a particular range is out of the screen, which
295 // will lead to bounds==null.
296 if (bounds.isNull()) continue;
298 assert(bounds.isFinite());
300 _drawbounds.push_back(bounds);
305 void
306 Qt4Gui::setTimeout(unsigned int timeout)
308 // This must go through Gui::quit() to make sure screenshots are
309 // handled if necessary.
310 QTimer::singleShot(timeout, _drawingWidget, SLOT(quit()));
313 void
314 Qt4Gui::setInterval(unsigned int interval)
316 _interval = interval;
317 _advanceTimer = _drawingWidget->startTimer(_interval);
320 void
321 Qt4Gui::setCursor(gnash_cursor_type newcursor)
323 if (! _mouseShown) return;
325 switch (newcursor) {
326 case CURSOR_HAND:
327 _drawingWidget->setCursor(Qt::PointingHandCursor);
328 break;
329 case CURSOR_INPUT:
330 _drawingWidget->setCursor(Qt::IBeamCursor);
331 break;
332 default:
333 _drawingWidget->unsetCursor();
337 bool
338 Qt4Gui::showMouse(bool show)
340 bool prevState = _mouseShown;
341 _mouseShown = show;
343 if (show) {
344 _drawingWidget->unsetCursor();
346 else {
347 _drawingWidget->setCursor(Qt::BlankCursor);
350 return prevState;
353 void
354 Qt4Gui::setFullscreen()
356 _fullscreen = true;
357 fullscreenAction->setChecked(_fullscreen);
359 _embedWidget->setWindowFlags(Qt::Window);
360 _embedWidget->showFullScreen();
363 void
364 Qt4Gui::unsetFullscreen()
366 _fullscreen = false;
367 fullscreenAction->setChecked(_fullscreen);
369 if (_embedWidget->isFullScreen()) {
370 _embedWidget->setWindowFlags(Qt::Widget);
371 _embedWidget->showNormal();
372 if (_xid) {
373 _embedWidget->embedInto(_xid);
378 double
379 Qt4Gui::getScreenDPI() const
381 assert(_drawingWidget);
382 // Should this be logical or physical DPI?
383 return _drawingWidget->logicalDpiX();
386 std::pair<int, int>
387 Qt4Gui::screenResolution() const
389 QDesktopWidget* d = QApplication::desktop();
390 assert(d);
392 const QRect c = d->screenGeometry();
393 return std::make_pair(c.width(), c.height());
396 gnash::key::code
397 Qt4Gui::qtToGnashKey(QKeyEvent *event)
400 // This should be initialized by now.
401 assert (!_keyMap.empty());
403 // Gnash uses its own keycodes to map key events
404 // to the three sometimes weird and confusing values that flash movies
405 // can refer to. See GnashKey.h for the keycodes and map.
407 // Gnash's keycodes are gnash::key::code. They are mainly in ascii order.
408 // Standard ascii characters (32-127) have the same value. Extended ascii
409 // characters (160-254) are in ascii order but correspond to
410 // gnash::key::code
411 // 169-263. Non-character values must normally be mapped separately.
413 const int key = event->key();
415 if (key >= Qt::Key_0 && key <= Qt::Key_9) {
416 return static_cast<gnash::key::code>(
417 key - Qt::Key_0 + gnash::key::_0);
420 // All other characters between ascii 32 and 126 are simple.
421 // From space (32) to slash (47):
422 else if (key >= Qt::Key_Space && key <= Qt::Key_AsciiTilde) {
423 return static_cast<gnash::key::code>(
424 key - Qt::Key_Space + gnash::key::SPACE);
427 // Function keys:
428 else if (key >= Qt::Key_F1 && key <= Qt::Key_F15) {
429 return static_cast<gnash::key::code>(
430 key - Qt::Key_F1 + gnash::key::F1);
433 // Extended ascii from non-breaking (160) space to ÿ (264) is in the same
434 // order.
435 else if (key >= Qt::Key_nobreakspace && key <= Qt::Key_ydiaeresis) {
436 return static_cast<gnash::key::code>(
437 key - Qt::Key_nobreakspace + gnash::key::NOBREAKSPACE);
440 const KeyMap::const_iterator it = _keyMap.find(key);
442 if (it == _keyMap.end()) return gnash::key::INVALID;
444 return it->second;
449 Qt4Gui::qtToGnashModifier(const Qt::KeyboardModifiers modifiers)
451 int gnashModifier = gnash::key::GNASH_MOD_NONE;
453 if (modifiers & Qt::ShiftModifier)
454 gnashModifier = gnashModifier | gnash::key::GNASH_MOD_SHIFT;
455 if (modifiers & Qt::ControlModifier)
456 gnashModifier = gnashModifier | gnash::key::GNASH_MOD_CONTROL;
457 if (modifiers & Qt::AltModifier)
458 gnashModifier = gnashModifier | gnash::key::GNASH_MOD_ALT;
460 return gnashModifier;
463 void
464 Qt4Gui::handleKeyEvent(QKeyEvent *event, bool down)
466 gnash::key::code c = qtToGnashKey(event);
467 int mod = qtToGnashModifier(event->modifiers());
468 notify_key_event(c, mod, down);
471 void
472 Qt4Gui::resize(int width, int height)
474 _glue->resize(width, height);
475 resize_view(width, height);
478 void
479 Qt4Gui::showProperties()
481 QDialog* propsDialog = new QDialog(_drawingWidget);
482 propsDialog->setWindowTitle(_q("Movie properties"));
483 propsDialog->setAttribute(Qt::WA_DeleteOnClose);
484 propsDialog->resize(500, 300);
486 QDialogButtonBox *dialogButtons = new QDialogButtonBox(
487 QDialogButtonBox::Close, Qt::Horizontal, propsDialog);
488 dialogButtons->button(QDialogButtonBox::Close)->setDefault(true);
490 QVBoxLayout* layout = new QVBoxLayout(propsDialog);
491 propsDialog->connect(dialogButtons->button(QDialogButtonBox::Close),
492 SIGNAL(clicked()), SLOT(close()));
494 #ifdef USE_SWFTREE
495 std::unique_ptr<movie_root::InfoTree> infoptr = getMovieInfo();
496 const movie_root::InfoTree& info = *infoptr;
498 QTreeWidget *tree = new QTreeWidget();
499 tree->setColumnCount(2);
500 QStringList treeHeader;
501 treeHeader.append(_q("Variable"));
502 treeHeader.append(_q("Value"));
503 tree->setHeaderLabels(treeHeader);
505 QList<QTreeWidgetItem *> items;
507 int prevDepth = 0;
508 QStack<QTreeWidgetItem*> stack;
509 for (movie_root::InfoTree::iterator i = info.begin(), e = info.end();
510 i != e; ++i) {
512 const movie_root::InfoTree::value_type& p = *i;
514 QStringList cols;
515 cols.append(p.first.c_str());
516 cols.append(p.second.c_str());
517 QTreeWidgetItem* item = new QTreeWidgetItem(cols);
519 int newDepth = info.depth(i);
521 if (newDepth == 0) {
522 // Insert top level entries directly into the tree widget.
523 items.append(item);
524 stack.clear();
525 } else {
526 // The position to insert the new row.
527 QTreeWidgetItem* parent = NULL;
529 if (newDepth == prevDepth ) {
530 // Pop an extra time if there is a sibling on the stack.
531 int size = stack.size();
532 if (size + 1 > newDepth)
533 stack.pop();
535 parent = stack.pop();
536 } else if (newDepth > prevDepth) {
537 parent = stack.pop();
538 } else if (newDepth < prevDepth) {
539 // Pop until the stack has the right depth.
540 int size = stack.size();
541 for (int j = 0; j < (size + 1) - newDepth; ++j) {
542 parent = stack.pop();
546 parent->addChild(item);
547 stack.push(parent);
550 stack.push(item);
551 prevDepth = newDepth;
553 tree->insertTopLevelItems(0, items);
554 layout->addWidget(tree);
556 #endif // USE_SWFTREE
557 layout->addWidget(dialogButtons);
559 propsDialog->show();
560 propsDialog->activateWindow();
563 void
564 Qt4Gui::showPreferences()
566 Qt4GuiPrefs::PreferencesDialog* prefsDialog = new Qt4GuiPrefs::PreferencesDialog(_drawingWidget);
568 prefsDialog->setAttribute(Qt::WA_DeleteOnClose);
569 prefsDialog->show();
570 prefsDialog->raise();
571 prefsDialog->activateWindow();
574 bool
575 Qt4Gui::yesno(const std::string& question)
577 _drawingWidget->killTimer(_advanceTimer);
579 QMessageBox* dialog = new QMessageBox(_drawingWidget);
580 dialog->setText(QString::fromStdString(question));
581 dialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
582 dialog->setDefaultButton(QMessageBox::Yes);
583 const int ret = dialog->exec();
585 _advanceTimer = _drawingWidget->startTimer(_interval);
588 if (ret == QMessageBox::Yes) return true;
589 return false;
592 void
593 Qt4Gui::quitUI()
595 _application->quit();
598 void
599 Qt4Gui::setupActions()
602 // File Menu actions
603 propertiesAction = new QAction(_q("Properties"), _window.get());
604 _drawingWidget->connect(propertiesAction, SIGNAL(triggered()),
605 _drawingWidget, SLOT(properties()));
607 quitAction = new QAction(_q("Quit Gnash"), _window.get());
608 // This must go through Gui::quit() to make sure we don't exit
609 // before doing whatever the Gui wants to do on exit.
610 _drawingWidget->connect(quitAction, SIGNAL(triggered()),
611 _drawingWidget, SLOT(quit()));
613 // Edit Menu actions
614 preferencesAction = new QAction(_q("Preferences"), _window.get());
615 _drawingWidget->connect(preferencesAction, SIGNAL(triggered()),
616 _drawingWidget, SLOT(preferences()));
618 // Movie Control Menu actions
619 playAction = new QAction(_q("Play"), _window.get());
620 _drawingWidget->connect(playAction, SIGNAL(triggered()),
621 _drawingWidget, SLOT(play()));
623 pauseAction = new QAction(_q("Pause"), _window.get());
624 _drawingWidget->connect(pauseAction, SIGNAL(triggered()),
625 _drawingWidget, SLOT(pause()));
627 stopAction = new QAction(_q("Stop"), _window.get());
628 _drawingWidget->connect(stopAction, SIGNAL(triggered()),
629 _drawingWidget, SLOT(stop()));
631 restartAction = new QAction(_q("Restart"), _window.get());
632 _drawingWidget->connect(restartAction, SIGNAL(triggered()),
633 _drawingWidget, SLOT(restart()));
635 // View Menu actions
636 refreshAction = new QAction(_q("Refresh"), _window.get());
637 _drawingWidget->connect(refreshAction, SIGNAL(triggered()),
638 _drawingWidget, SLOT(refresh()));
640 fullscreenAction = new QAction(_q("Fullscreen"), _window.get());
641 fullscreenAction->setCheckable(true);
642 _drawingWidget->connect(fullscreenAction, SIGNAL(toggled(bool)),
643 _drawingWidget, SLOT(fullscreen(bool)));
647 void
648 Qt4Gui::setupMenus()
650 /// The menus are children of the QMainWindow so that
651 /// they are destroyed on exit. The QMainWindow already has
652 /// ownership of the main QMenuBar.
654 // Set up the File menu.
655 fileMenu = new QMenu(_q("File"), _window.get());
656 fileMenu->addAction(propertiesAction);
657 fileMenu->addAction(quitAction);
659 // Set up the Edit menu.
660 editMenu = new QMenu(_q("Edit"), _window.get());
661 editMenu->addAction(preferencesAction);
663 // Set up the Movie Control menu
664 movieControlMenu = new QMenu(_q("Movie Control"), _window.get());
665 movieControlMenu->addAction(playAction);
666 movieControlMenu->addAction(pauseAction);
667 movieControlMenu->addAction(stopAction);
668 movieControlMenu->addAction(restartAction);
670 // Set up the View menu
671 viewMenu = new QMenu(_q("View"), _window.get());
672 viewMenu->addAction(refreshAction);
673 viewMenu->addAction(fullscreenAction);
677 void
678 Qt4Gui::createMainMenu()
680 std::unique_ptr<QMenuBar> mainMenu(new QMenuBar);
682 // Set up the menu bar.
683 mainMenu->addMenu(fileMenu);
684 mainMenu->addMenu(editMenu);
685 mainMenu->addMenu(movieControlMenu);
686 mainMenu->addMenu(viewMenu);
688 // The QMainWindow::setMenuBar transfers ownership
689 // of the QMenuBar.
690 _window->setMenuBar(mainMenu.release());
694 void
695 Qt4Gui::setupKeyMap()
697 // We only want to do this once, although it would not
698 // be harmful to do it more.
699 assert (_keyMap.empty());
701 _keyMap = {
702 {Qt::Key_Backspace, gnash::key::BACKSPACE},
703 {Qt::Key_Tab, gnash::key::TAB},
704 {Qt::Key_Clear, gnash::key::CLEAR},
705 {Qt::Key_Return, gnash::key::ENTER},
706 {Qt::Key_Enter, gnash::key::ENTER},
707 {Qt::Key_Shift, gnash::key::SHIFT},
708 {Qt::Key_Control, gnash::key::CONTROL},
709 {Qt::Key_Alt, gnash::key::ALT},
710 {Qt::Key_CapsLock, gnash::key::CAPSLOCK},
711 {Qt::Key_Escape, gnash::key::ESCAPE},
712 {Qt::Key_Space, gnash::key::SPACE},
713 {Qt::Key_PageDown, gnash::key::PGDN},
714 {Qt::Key_PageUp, gnash::key::PGUP},
715 {Qt::Key_Home, gnash::key::HOME},
716 {Qt::Key_End, gnash::key::END},
717 {Qt::Key_Left, gnash::key::LEFT},
718 {Qt::Key_Up, gnash::key::UP},
719 {Qt::Key_Right, gnash::key::RIGHT},
720 {Qt::Key_Down, gnash::key::DOWN},
721 {Qt::Key_Insert, gnash::key::INSERT},
722 {Qt::Key_Delete, gnash::key::DELETEKEY},
723 {Qt::Key_Help, gnash::key::HELP},
724 {Qt::Key_NumLock, gnash::key::NUM_LOCK},
725 {Qt::Key_Semicolon, gnash::key::SEMICOLON},
726 {Qt::Key_Equal, gnash::key::EQUALS},
727 {Qt::Key_Minus, gnash::key::MINUS},
728 {Qt::Key_Slash, gnash::key::SLASH},
729 {Qt::Key_BracketLeft, gnash::key::LEFT_BRACKET},
730 {Qt::Key_Backslash, gnash::key::BACKSLASH},
731 {Qt::Key_BracketRight, gnash::key::RIGHT_BRACKET},
732 {Qt::Key_QuoteDbl, gnash::key::DOUBLE_QUOTE} };
735 void
736 Qt4Gui::playHook()
738 _embedWidget->hidePlayButton();
741 void
742 Qt4Gui::stopHook()
744 _embedWidget->showPlayButton();
747 /// EmbedWidget implementation
749 EmbedWidget::EmbedWidget(Qt4Gui& gui)
750 : QX11EmbedWidget()
752 _drawingWidget = new DrawingWidget(gui);
753 _playButton = new QPushButton(_q("Click to Play"), this);
755 QVBoxLayout* layout = new QVBoxLayout(this);
756 layout->setContentsMargins(0,0,0,0);
757 layout->setSpacing(0);
758 layout->addWidget(_playButton);
759 layout->addWidget(_drawingWidget);
760 _playButton->hide();
762 connect(_playButton, SIGNAL(clicked()), this, SLOT(hidePlayButton()));
763 connect(_playButton, SIGNAL(clicked()), _drawingWidget, SLOT(play()));
766 void
767 EmbedWidget::hidePlayButton()
769 _playButton->hide();
772 void
773 EmbedWidget::showPlayButton()
775 _playButton->show();
778 namespace Qt4GuiPrefs {
780 PreferencesDialog::PreferencesDialog(QWidget* parent)
782 QDialog(parent),
783 _rcfile(RcInitFile::getDefaultInstance())
785 setWindowTitle(_q("Gnash preferences"));
786 setAttribute(Qt::WA_DeleteOnClose);
788 QDialogButtonBox *buttons = new QDialogButtonBox(
789 QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
791 QVBoxLayout *vLayout = new QVBoxLayout(this);
793 QLabel* tmpLabel;
795 // Make notebook pages.
796 QTabWidget *tabs = new QTabWidget;
798 // Logging tab
799 QFrame* loggingTab = new QFrame();
800 tabs->addTab(loggingTab, _q("Logging"));
801 QVBoxLayout* layout = new QVBoxLayout (loggingTab);
803 tmpLabel = new QLabel(_q("<b>Logging options</b>"), loggingTab);
804 layout->addWidget(tmpLabel);
806 tmpLabel = new QLabel(_q("Verbosity level"), loggingTab);
807 layout->addWidget(tmpLabel);
809 QLCDNumber* lcd = new QLCDNumber(loggingTab);
810 lcd->display(_rcfile.verbosityLevel());
811 lcd->setNumDigits(2);
812 layout->addWidget(lcd);
814 _verbositySlider = new QSlider(loggingTab);
815 _verbositySlider->setOrientation(Qt::Horizontal);
816 _verbositySlider->setMaximum(10);
817 _verbositySlider->setSingleStep(1);
818 _verbositySlider->setPageStep(1);
819 _verbositySlider->setValue(_rcfile.verbosityLevel());
820 connect(_verbositySlider, SIGNAL(valueChanged(int)),
821 lcd, SLOT(display(int)));
822 layout->addWidget(_verbositySlider);
824 _logToFileToggle = new QCheckBox(_q("Log to file"), loggingTab);
825 _logToFileToggle->setChecked(_rcfile.useWriteLog());
826 layout->addWidget(_logToFileToggle);
828 _logFileName = new QLineEdit(_rcfile.getDebugLog().c_str(), loggingTab);
829 layout->addWidget(_logFileName);
831 _parserDumpToggle = new QCheckBox(_q("Log parser output"), loggingTab);
832 _parserDumpToggle->setChecked(_rcfile.useParserDump());
833 layout->addWidget(_parserDumpToggle);
835 _actionDumpToggle = new QCheckBox(_q("Log SWF actions"), loggingTab);
836 _actionDumpToggle->setChecked(_rcfile.useActionDump());
837 layout->addWidget(_actionDumpToggle);
839 _malformedSWFToggle = new QCheckBox(_q("Log malformed SWF errors"),
840 loggingTab);
841 _malformedSWFToggle->setChecked(_rcfile.showMalformedSWFErrors());
842 layout->addWidget(_malformedSWFToggle);
844 _ASCodingErrorToggle = new QCheckBox(_q("Log ActionScript coding errors"),
845 loggingTab);
846 _ASCodingErrorToggle->setChecked(_rcfile.showASCodingErrors());
847 layout->addWidget(_ASCodingErrorToggle);
849 // Security tab
850 QFrame* securityTab = new QFrame(tabs);
851 tabs->addTab(securityTab, _q("Security"));
852 layout = new QVBoxLayout (securityTab);
854 tmpLabel = new QLabel(_q("<b>Network connections</b>"), securityTab);
855 layout->addWidget(tmpLabel);
857 _localHostToggle = new QCheckBox(_q("Connect only to local host"),
858 securityTab);
859 _localHostToggle->setChecked(_rcfile.useLocalHost());
860 layout->addWidget(_localHostToggle);
862 _localDomainToggle = new QCheckBox(_q("Connect only to local domain"),
863 securityTab);
864 _localDomainToggle->setChecked(_rcfile.useLocalDomain());
865 layout->addWidget(_localDomainToggle);
867 _insecureSSLToggle = new QCheckBox(_q("Disable SSL verification"),
868 securityTab);
869 _insecureSSLToggle->setChecked(_rcfile.insecureSSL());
870 layout->addWidget(_insecureSSLToggle);
872 tmpLabel = new QLabel(_q("<b>Privacy</b>"), securityTab);
873 layout->addWidget(tmpLabel);
875 tmpLabel = new QLabel(_q("Shared objects directory:"), securityTab);
876 layout->addWidget(tmpLabel);
877 _solSandboxDir = new QLineEdit(_rcfile.getSOLSafeDir().c_str(),
878 securityTab);
879 layout->addWidget(_solSandboxDir);
881 _solReadOnlyToggle = new QCheckBox(_q("Do not write Shared Object files"),
882 securityTab);
883 _solReadOnlyToggle->setChecked(_rcfile.getSOLReadOnly());
884 layout->addWidget(_solReadOnlyToggle);
886 _solLocalDomainToggle = new QCheckBox(
887 _q("Only access local Shared Object files"), securityTab);
888 _solLocalDomainToggle->setChecked(_rcfile.getSOLLocalDomain());
889 layout->addWidget(_solLocalDomainToggle);
891 _localConnectionToggle = new QCheckBox(
892 _q("Disable Local Connection object"), securityTab);
893 _localConnectionToggle->setChecked(_rcfile.getLocalConnection());
894 layout->addWidget(_localConnectionToggle);
895 layout->addStretch();
897 // Network tab
898 QFrame* networkTab = new QFrame(tabs);
899 tabs->addTab(networkTab, _q("Network"));
900 layout = new QVBoxLayout (networkTab);
902 tmpLabel = new QLabel(_q("<b>Network preferences</b>"), networkTab);
903 layout->addWidget(tmpLabel);
905 tmpLabel = new QLabel(_q("Network timeout in seconds"), networkTab);
906 layout->addWidget(tmpLabel);
908 _streamsTimeoutScale = new QSpinBox(networkTab);
909 _streamsTimeoutScale->setMinimum(0);
910 _streamsTimeoutScale->setMaximum(300);
911 _streamsTimeoutScale->setValue(_rcfile.getStreamsTimeout());
912 layout->addWidget(_streamsTimeoutScale);
913 layout->addStretch();
915 // Network tab
916 QFrame* mediaTab = new QFrame(tabs);
917 tabs->addTab(mediaTab, _q("Media"));
918 layout = new QVBoxLayout (mediaTab);
920 tmpLabel = new QLabel(_q("<b>Sound</b>"), mediaTab);
921 layout->addWidget(tmpLabel);
923 _soundToggle = new QCheckBox(_q("Use sound handler"), mediaTab);
924 _soundToggle->setChecked(_rcfile.useSound());
925 layout->addWidget(_soundToggle);
927 _saveStreamingMediaToggle = new QCheckBox(_q("Save media streams to disk"),
928 mediaTab);
929 _saveStreamingMediaToggle->setChecked(_rcfile.saveStreamingMedia());
930 layout->addWidget(_saveStreamingMediaToggle);
932 _saveLoadedMediaToggle = new QCheckBox(
933 _q("Save dynamically loaded media to disk"), mediaTab);
934 _saveLoadedMediaToggle->setChecked(_rcfile.saveLoadedMedia());
935 layout->addWidget(_saveLoadedMediaToggle);
937 tmpLabel = new QLabel(_q("Saved media directory:"), mediaTab);
938 layout->addWidget(tmpLabel);
940 _mediaDir = new QLineEdit(_rcfile.getMediaDir().c_str(), mediaTab);
941 layout->addWidget(_mediaDir);
942 layout->addStretch();
944 // Player tab
945 QFrame* playerTab = new QFrame(tabs);
946 tabs->addTab(playerTab, _q("Player"));
947 layout = new QVBoxLayout (playerTab);
949 tmpLabel = new QLabel(_q("<b>Player description</b>"), playerTab);
950 layout->addWidget(tmpLabel);
952 tmpLabel = new QLabel(_q("Player version:"), playerTab);
953 layout->addWidget(tmpLabel);
954 _versionText = new QLineEdit(_rcfile.getFlashVersionString().c_str(),
955 playerTab);
956 layout->addWidget(_versionText);
958 tmpLabel = new QLabel(_q("Operating system:"), playerTab);
959 layout->addWidget(tmpLabel);
961 _osText = new QLineEdit(playerTab);
962 if (_rcfile.getFlashSystemOS().empty()) {
963 _osText->setText(_q("<Autodetect>"));
964 } else {
965 _osText->setText(_rcfile.getFlashSystemOS().c_str());
967 layout->addWidget(_osText);
969 tmpLabel = new QLabel(_q("URL opener:"), playerTab);
970 layout->addWidget(tmpLabel);
972 _urlOpenerText = new QLineEdit(_rcfile.getURLOpenerFormat().c_str(),
973 playerTab);
974 layout->addWidget(_urlOpenerText);
976 tmpLabel = new QLabel(_q("<b>Performance</b>"), playerTab);
977 layout->addWidget(tmpLabel);
979 tmpLabel = new QLabel(_q("Max size of movie library:"), playerTab);
980 layout->addWidget(tmpLabel);
982 _librarySize = new QSpinBox(playerTab);
983 _librarySize->setMinimum(0);
984 _librarySize->setMaximum(100);
985 _librarySize->setValue(_rcfile.getMovieLibraryLimit());
986 layout->addWidget(_librarySize);
988 _startStoppedToggle = new QCheckBox(_q("Start Gnash in pause mode"),
989 playerTab);
990 _startStoppedToggle->setChecked(_rcfile.startStopped());
991 layout->addWidget(_startStoppedToggle);
992 layout->addStretch();
993 // End of notebook tabs
995 vLayout->addWidget(tabs);
996 vLayout->addStretch();
997 vLayout->addWidget(buttons);
999 // Connect the dialog buttons.
1000 connect(buttons, SIGNAL(accepted()), this, SLOT(savePreferences()));
1001 connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
1004 void
1005 PreferencesDialog::savePreferences()
1007 // Logging tab widgets
1008 _rcfile.verbosityLevel(_verbositySlider->value());
1009 _rcfile.useWriteLog(_logToFileToggle->isChecked());
1010 _rcfile.setDebugLog(_logFileName->text().toStdString());
1011 _rcfile.useParserDump(_parserDumpToggle->isChecked());
1012 _rcfile.useActionDump(_actionDumpToggle->isChecked());
1013 _rcfile.showMalformedSWFErrors(_malformedSWFToggle->isChecked());
1014 _rcfile.showASCodingErrors(_ASCodingErrorToggle->isChecked());
1016 // Security tab widgets
1017 _rcfile.useLocalHost(_localHostToggle->isChecked());
1018 _rcfile.useLocalDomain(_localDomainToggle->isChecked());
1019 _rcfile.insecureSSL(_insecureSSLToggle->isChecked());
1020 _rcfile.setSOLSafeDir(_solSandboxDir->text().toStdString());
1021 _rcfile.setSOLReadOnly(_solReadOnlyToggle->isChecked());
1022 _rcfile.setSOLLocalDomain(_solLocalDomainToggle->isChecked());
1023 _rcfile.setLocalConnection(_localConnectionToggle->isChecked());
1025 // Network tab widgets
1026 _rcfile.setStreamsTimeout(_streamsTimeoutScale->value());
1028 // Media tab widgets
1029 _rcfile.useSound(_soundToggle->isChecked());
1030 _rcfile.saveStreamingMedia(_saveStreamingMediaToggle->isChecked());
1031 _rcfile.saveLoadedMedia(_saveLoadedMediaToggle->isChecked());
1032 _rcfile.setMediaDir(_mediaDir->text().toStdString());
1034 // Player tab widgets
1035 _rcfile.setFlashVersionString(_versionText->text().toStdString());
1036 if (_osText->text() != _q("<Autodetect>")) {
1037 _rcfile.setFlashSystemOS(_osText->text().toStdString());
1039 _rcfile.setURLOpenerFormat(_urlOpenerText->text().toStdString());
1040 _rcfile.setMovieLibraryLimit(_librarySize->value());
1041 _rcfile.startStopped(_startStoppedToggle->isChecked());
1043 // Save the file.
1044 _rcfile.updateFile();
1046 // Allow the dialog to close normally.
1047 emit accept();
1050 } // End of Qt4GuiPrefs namespace