ktutorial-commits Mailing List for KTutorial (Page 8)
Status: Alpha
Brought to you by:
danxuliu
You can subscribe to this list here.
2010 |
Jan
(1) |
Feb
(36) |
Mar
(117) |
Apr
(11) |
May
(8) |
Jun
(1) |
Jul
|
Aug
(2) |
Sep
(21) |
Oct
(16) |
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(1) |
Feb
|
Mar
(6) |
Apr
(6) |
May
(15) |
Jun
(15) |
Jul
(6) |
Aug
|
Sep
(1) |
Oct
(4) |
Nov
|
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(10) |
Jul
(4) |
Aug
(29) |
Sep
(4) |
Oct
|
Nov
|
Dec
(2) |
From: <dan...@us...> - 2010-03-29 23:35:56
|
Revision: 213 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=213&view=rev Author: danxuliu Date: 2010-03-29 23:35:50 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Force clean state in newTutorial Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 22:43:26 UTC (rev 212) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 23:35:50 UTC (rev 213) @@ -398,6 +398,9 @@ void KTutorialEditor::newTutorial() { setTutorialToBeEdited(); mTutorialUrl = KUrl(); + //Force clean state, as setting an empty stack as clean would not emit + //cleanChanged() + handleUndoStackCleanChanged(true); } void KTutorialEditor::openTutorial() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 22:43:32
|
Revision: 212 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=212&view=rev Author: danxuliu Date: 2010-03-29 22:43:26 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Make caption consistent with clean state: new tutorials start now showing a clean state and they no longer show "[not saved]" in the caption when they enter in an clean state (due to an undo). The editor doesn't warn the user before closing a new empty tutorial, so it shouldn't show "[not saved]" in the caption either. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 22:24:45 UTC (rev 211) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 22:43:26 UTC (rev 212) @@ -381,21 +381,23 @@ void KTutorialEditor::handleUndoStackCleanChanged(bool clean) { QString caption = captionFromTutorialUrl(); - if (clean && !mTutorialUrl.isEmpty()) { - actionCollection()->action("file_save")->setEnabled(false); + if (clean) { setCaption(caption); } else { - actionCollection()->action("file_save")->setEnabled(true); setCaption(i18nc("@title:window Wrapper for the window title when the \ tutorial was modified but not saved yet", "%1 [not saved]", caption)); } + + if (clean && !mTutorialUrl.isEmpty()) { + actionCollection()->action("file_save")->setEnabled(false); + } else { + actionCollection()->action("file_save")->setEnabled(true); + } } void KTutorialEditor::newTutorial() { setTutorialToBeEdited(); mTutorialUrl = KUrl(); - //Force unclean state, as clearing the stack returns it to the clean state - handleUndoStackCleanChanged(false); } void KTutorialEditor::openTutorial() { Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 22:24:45 UTC (rev 211) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 22:43:26 UTC (rev 212) @@ -176,10 +176,9 @@ /** * Modifies the caption and enables or disables Save action based on the * clean state of the stack. - * When the stack is not clean or the tutorial does not have an associated - * URL, "[not saved]" is added after the caption (the URL or "New file", - * depending on the case). Otherwise, the caption is the URL associated to - * the tutorial. + * When the stack is not clean, "[not saved]" is added after the caption + * (the URL or "New file", depending on the case). Otherwise, the caption is + * the URL associated to the tutorial. * * When the stack is clean and the tutorial has an associated URL, the Save * action is disabled. Otherwise, it is enabled, so if there is no @@ -192,7 +191,7 @@ /** * Creates a new empty tutorial replacing the current one, if any. - * The tutorial URL is cleared and an unclean state is forced. + * The tutorial URL is cleared. */ void newTutorial(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 22:24:52
|
Revision: 211 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=211&view=rev Author: danxuliu Date: 2010-03-29 22:24:45 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Warn the user when a tutorial is going to be closed and the changes were not saved yet. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 17:17:44 UTC (rev 210) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 22:24:45 UTC (rev 211) @@ -73,9 +73,42 @@ setupGUI(); } +//protected: + +bool KTutorialEditor::queryClose() { + return queryCloseTutorial(); +} + //private: +bool KTutorialEditor::queryCloseTutorial() { + if (mUndoStack->isClean()) { + return true; + } + + QString text = i18nc("@label", "The tutorial has been modified.<nl/>" +"Do you want to save your changes or discard them?"); + QString caption = i18nc("@title:window", "Close tutorial"); + int button = KMessageBox::warningYesNoCancel(this, text, caption, + KStandardGuiItem::save(), + KStandardGuiItem::discard()); + + if (button == KMessageBox::Cancel) { + return false; + } + + if (button == KMessageBox::Yes) { + return saveTutorial(); + } + + return true; +} + void KTutorialEditor::setTutorialToBeEdited(Tutorial* tutorial) { + if (!queryCloseTutorial()) { + return; + } + if (!tutorial) { tutorial = new Tutorial(this); } @@ -147,7 +180,7 @@ actionCollection()->addAction("exportTutorial", action); connect(action, SIGNAL(triggered(bool)), this, SLOT(exportTutorial())); - KStandardAction::quit(kapp, SLOT(quit()), actionCollection()); + KStandardAction::quit(this, SLOT(close()), actionCollection()); mUndoStack->createUndoAction(actionCollection()); @@ -404,10 +437,9 @@ handleUndoStackCleanChanged(true); } -void KTutorialEditor::saveTutorial() { +bool KTutorialEditor::saveTutorial() { if (mTutorialUrl.isEmpty()) { - saveTutorialAs(); - return; + return saveTutorialAs(); } try { @@ -417,13 +449,15 @@ "save the tutorial:<nl/>%1", e.message()); QString caption = i18nc("@title:window", "Tutorial could not be saved"); KMessageBox::error(this, text, caption); - return; + return false; } mUndoStack->setClean(); + + return true; } -void KTutorialEditor::saveTutorialAs() { +bool KTutorialEditor::saveTutorialAs() { KUrl url = mTutorialUrl; QPointer<KFileDialog> dialog = new KFileDialog(url, QString(), this); @@ -436,7 +470,7 @@ dialog->filterWidget()->setEditable(false); if (dialog->exec() == QDialog::Rejected) { - return; + return false; } try { @@ -446,7 +480,7 @@ "save the tutorial:<nl/>%1", e.message()); QString caption = i18nc("@title:window", "Tutorial could not be saved"); KMessageBox::error(this, text, caption); - return; + return false; } mTutorialUrl = dialog->selectedUrl(); @@ -454,6 +488,8 @@ //Force clean state, as setting an empty stack as clean would not emit //cleanChanged() handleUndoStackCleanChanged(true); + + return true; } void KTutorialEditor::exportTutorial() { Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 17:17:44 UTC (rev 210) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 22:24:45 UTC (rev 211) @@ -43,6 +43,19 @@ */ KTutorialEditor(); +protected: + + /** + * Called before the window is closed, either by the user or indirectly by + * the session manager. + * It checks whether the tutorial can be closed or not. + * + * Reimplemented from KMainWindow::queryClose(). + * + * @return True if the window can be closed, false otherwise. + */ + virtual bool queryClose(); + private: /** @@ -91,12 +104,23 @@ Reaction* mCurrentReaction; /** + * Checks whether the tutorial can be closed or not. + * If the tutorial is not clean, the user is asked if it has to be saved or + * not, or if the close operation should be cancelled. + * + * @return True if the tutorial can be closed, false otherwise. + */ + bool queryCloseTutorial(); + + /** * Sets the tutorial to be edited. * It creates a new tutorial, prepares the tree view to represent it and * handles the selection of items. * * If the tutorial is null, a new empty tutorial is set. * + * Nothing is done if the previous tutorial should not be closed. + * * @param tutorial The tutorial to set. */ void setTutorialToBeEdited(Tutorial* tutorial = 0); @@ -184,15 +208,19 @@ * A clean state is set. If there is no tutorial URL it behaves like * saveTutorialAs(). * An error message is shown if the tutorial couldn't be saved. + * + * @return True if the tutorial was successfully saved, false otherwise. */ - void saveTutorial(); + bool saveTutorial(); /** * Shows a KFileDialog to select the file to save the tutorial to. * The tutorial URL is updated and a clean state is forced. * An error message is shown if the tutorial couldn't be saved. + * + * @return True if the tutorial was successfully saved, false otherwise. */ - void saveTutorialAs(); + bool saveTutorialAs(); /** * Shows a KFileDialog to select the file to save the exported tutorial in. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 17:17:50
|
Revision: 210 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=210&view=rev Author: danxuliu Date: 2010-03-29 17:17:44 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Enable or disable Save action and set caption based on the undo stack state. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 06:46:22 UTC (rev 209) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 17:17:44 UTC (rev 210) @@ -61,15 +61,14 @@ setCentralWidget(mTreeView); mUndoStack = new KUndoStack(this); - setTutorialToBeEdited(); + connect(mUndoStack, SIGNAL(cleanChanged(bool)), + this, SLOT(handleUndoStackCleanChanged(bool))); setupDocks(); setupActions(); - //Setting the url enables/disables File->Save action, so it has to be - //set after it is created - setTutorialUrl(KUrl()); + newTutorial(); setupGUI(); } @@ -115,24 +114,6 @@ mTutorial = tutorial; } -void KTutorialEditor::setTutorialUrl(const KUrl& url) { - mTutorialUrl = url; - - if (url.isEmpty()) { - actionCollection()->action("file_save")->setEnabled(false); - - setCaption(""); - } else { - actionCollection()->action("file_save")->setEnabled(true); - - QString caption = url.prettyUrl(); - if (caption.length() > 64) { - caption = "..." + caption.right(64); - } - setCaption(caption); - } -} - void KTutorialEditor::setupDocks() { mTutorialActionDock = new QDockWidget(i18nc("@title", "Edit tutorial"), this); @@ -308,6 +289,20 @@ mReactionActionDock->toggleViewAction()); } +QString KTutorialEditor::captionFromTutorialUrl() { + if (mTutorialUrl.isEmpty()) { + return i18nc("@title:window Window title for KTutorial editor when the \ +tutorial has no associated URL", "New file"); + } + + QString caption = mTutorialUrl.prettyUrl(); + if (caption.length() > 64) { + caption = "..." + caption.right(64); + } + + return caption; +} + int KTutorialEditor::showEditionDialog(CommandWidget* commandWidget) { commandWidget->setUndoStack(mUndoStack); @@ -351,9 +346,23 @@ } } +void KTutorialEditor::handleUndoStackCleanChanged(bool clean) { + QString caption = captionFromTutorialUrl(); + if (clean && !mTutorialUrl.isEmpty()) { + actionCollection()->action("file_save")->setEnabled(false); + setCaption(caption); + } else { + actionCollection()->action("file_save")->setEnabled(true); + setCaption(i18nc("@title:window Wrapper for the window title when the \ +tutorial was modified but not saved yet", "%1 [not saved]", caption)); + } +} + void KTutorialEditor::newTutorial() { setTutorialToBeEdited(); - setTutorialUrl(KUrl()); + mTutorialUrl = KUrl(); + //Force unclean state, as clearing the stack returns it to the clean state + handleUndoStackCleanChanged(false); } void KTutorialEditor::openTutorial() { @@ -388,10 +397,19 @@ } setTutorialToBeEdited(tutorial); - setTutorialUrl(dialog->selectedUrl()); + mTutorialUrl = dialog->selectedUrl(); + mUndoStack->setClean(); + //Force clean state, as setting an empty stack as clean would not emit + //cleanChanged() + handleUndoStackCleanChanged(true); } void KTutorialEditor::saveTutorial() { + if (mTutorialUrl.isEmpty()) { + saveTutorialAs(); + return; + } + try { Serialization::saveTutorial(mTutorial, mTutorialUrl); } catch (IOException e) { @@ -399,7 +417,10 @@ "save the tutorial:<nl/>%1", e.message()); QString caption = i18nc("@title:window", "Tutorial could not be saved"); KMessageBox::error(this, text, caption); + return; } + + mUndoStack->setClean(); } void KTutorialEditor::saveTutorialAs() { @@ -428,7 +449,11 @@ return; } - setTutorialUrl(dialog->selectedUrl()); + mTutorialUrl = dialog->selectedUrl(); + mUndoStack->setClean(); + //Force clean state, as setting an empty stack as clean would not emit + //cleanChanged() + handleUndoStackCleanChanged(true); } void KTutorialEditor::exportTutorial() { Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 06:46:22 UTC (rev 209) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 17:17:44 UTC (rev 210) @@ -102,16 +102,6 @@ void setTutorialToBeEdited(Tutorial* tutorial = 0); /** - * Sets the URL to save the tutorial to. - * An empty URL disables Save action, otherwise it is enabled. - * The caption (window title) is updated with the URL. The URL in the - * caption is shown truncated if it is too lengthy. - * - * @param url The URL to save the tutorial to. - */ - void setTutorialUrl(const KUrl& url); - - /** * Sets up the dock widgets. */ void setupDocks(); @@ -122,6 +112,15 @@ void setupActions(); /** + * Returns a caption (window title) string based on the tutorial URL. + * The caption contains the URL, which is truncated if it is too lengthy. If + * the URL is empty, "New file" is returned. + * + * @return A caption string based on the tutorial URL. + */ + QString captionFromTutorialUrl(); + + /** * Shows an EditionDialog for the given CommandWidget. * The undo stack used in the CommandWidget is mUndoStack. * @@ -151,27 +150,46 @@ void selectReaction(Reaction* reaction); /** + * Modifies the caption and enables or disables Save action based on the + * clean state of the stack. + * When the stack is not clean or the tutorial does not have an associated + * URL, "[not saved]" is added after the caption (the URL or "New file", + * depending on the case). Otherwise, the caption is the URL associated to + * the tutorial. + * + * When the stack is clean and the tutorial has an associated URL, the Save + * action is disabled. Otherwise, it is enabled, so if there is no + * associated URL the Save action is always kept enabled, even if the stack + * is clean. + * + * @param clean Whether the undo stack entered clean state or not. + */ + void handleUndoStackCleanChanged(bool clean); + + /** * Creates a new empty tutorial replacing the current one, if any. - * The tutorial URL is cleared. + * The tutorial URL is cleared and an unclean state is forced. */ void newTutorial(); /** * Shows a KFileDialog to select the file to open the tutorial from. - * The tutorial URL is updated. + * The tutorial URL is updated and a clean state is forced. * An error message is shown if the tutorial couldn't be opened. */ void openTutorial(); /** * Saves the tutorial to the tutorial URL. + * A clean state is set. If there is no tutorial URL it behaves like + * saveTutorialAs(). * An error message is shown if the tutorial couldn't be saved. */ void saveTutorial(); /** * Shows a KFileDialog to select the file to save the tutorial to. - * The tutorial URL is updated. + * The tutorial URL is updated and a clean state is forced. * An error message is shown if the tutorial couldn't be saved. */ void saveTutorialAs(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 06:46:28
|
Revision: 209 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=209&view=rev Author: danxuliu Date: 2010-03-29 06:46:22 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Fix removing a reaction from the middle and undoing the operation (the reaction was readded at the end). It required being able to add reactions at any position in the step, and not only at the end. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h trunk/ktutorial/ktutorial-editor/src/data/Step.cpp trunk/ktutorial/ktutorial-editor/src/data/Step.h trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.cpp trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.h trunk/ktutorial/ktutorial-editor/tests/unit/commands/StepCommandsTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/data/StepTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/view/StepTreeItemTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp 2010-03-29 06:46:22 UTC (rev 209) @@ -142,21 +142,46 @@ mDeleteReactionInDestructor = true; } + virtual void undo() { + mDeleteReactionInDestructor = true; + mStep->removeReaction(mReaction); + } + +}; + +class AddReactionAtEnd: public AddReaction { +public: + + AddReactionAtEnd(QUndoCommand* parent = 0): AddReaction(parent) { + } + virtual void redo() { mDeleteReactionInDestructor = false; mStep->addReaction(mReaction); } - virtual void undo() { - mDeleteReactionInDestructor = true; - mStep->removeReaction(mReaction); +}; + +class AddReactionAtIndex: public AddReaction { +public: + + int mIndex; + + AddReactionAtIndex(QUndoCommand* parent = 0): AddReaction(parent) { } + virtual void redo() { + mDeleteReactionInDestructor = false; + mStep->addReaction(mReaction, mIndex); + } + }; class RemoveReaction: public BaseReactionCommand { public: + int mIndex; + RemoveReaction(QUndoCommand* parent = 0): BaseReactionCommand(parent) { setText(i18nc("@action", "Remove reaction")); mDeleteReactionInDestructor = false; @@ -164,12 +189,13 @@ virtual void redo() { mDeleteReactionInDestructor = true; + mIndex = mStep->reactions().indexOf(mReaction); mStep->removeReaction(mReaction); } virtual void undo() { mDeleteReactionInDestructor = false; - mStep->addReaction(mReaction); + mStep->addReaction(mReaction, mIndex); } }; @@ -212,12 +238,21 @@ QUndoCommand* StepCommands::addReaction(Reaction* reaction, QUndoCommand* parent) { - AddReaction* command = new AddReaction(parent); + AddReactionAtEnd* command = new AddReactionAtEnd(parent); command->mStep = mStep; command->mReaction = reaction; return command; } +QUndoCommand* StepCommands::addReaction(Reaction* reaction, int index, + QUndoCommand* parent) { + AddReactionAtIndex* command = new AddReactionAtIndex(parent); + command->mStep = mStep; + command->mReaction = reaction; + command->mIndex = index; + return command; +} + QUndoCommand* StepCommands::removeReaction(Reaction* reaction, QUndoCommand* parent) { RemoveReaction* command = new RemoveReaction(parent); Modified: trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h 2010-03-29 06:46:22 UTC (rev 209) @@ -96,6 +96,20 @@ QUndoCommand* addReaction(Reaction* reaction, QUndoCommand* parent = 0); /** + * Creates a new undoable command to add the given reaction to the step at + * the given index. + * If the command was not executed yet, or it was undone, the reaction is + * deleted when the command is deleted. + * + * @param reaction The reaction to add to the step. + * @param index The index to add the reaction at. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* addReaction(Reaction* reaction, int index, + QUndoCommand* parent = 0); + + /** * Creates a new undoable command to remove the given reaction from the * step. * If the command was executed and not undone, the reaction is deleted when Modified: trunk/ktutorial/ktutorial-editor/src/data/Step.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/data/Step.cpp 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/src/data/Step.cpp 2010-03-29 06:46:22 UTC (rev 209) @@ -69,11 +69,15 @@ } void Step::addReaction(Reaction* reaction) { + addReaction(reaction, mReactions.count()); +} + +void Step::addReaction(Reaction* reaction, int index) { Q_ASSERT(!mReactions.contains(reaction)); - mReactions.append(reaction); + mReactions.insert(index, reaction); - emit reactionAdded(reaction); + emit reactionAdded(reaction, index); } QList<Reaction*> Step::reactions() const { Modified: trunk/ktutorial/ktutorial-editor/src/data/Step.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/data/Step.h 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/src/data/Step.h 2010-03-29 06:46:22 UTC (rev 209) @@ -30,7 +30,7 @@ * generate the code to create a true KTutorial::Step. * * When any attribute is modified, dataChanged(Step*) signal is emitted. When - * reactions are added or removed, reactionAdded(Reaction*) and + * reactions are added or removed, reactionAdded(Reaction*, int) and * reactionRemoved(Reaction*) are emitted. */ class Step: public QObject { @@ -64,6 +64,17 @@ * @param reaction The reaction to add. */ void addReaction(Reaction* reaction); + + /** + * Adds a new reaction to this Step at the given position. + * The Step gets ownership of the Reaction, so it is deleted when the + * Step is deleted. + * + * @param reaction The reaction to add. + * @param index The index to add the step at. + */ + void addReaction(Reaction* reaction, int index); + QList<Reaction*> reactions() const; /** @@ -87,8 +98,9 @@ * Emitted when the reaction is added to this Step. * * @param reaction The reaction added. + * @param index The index where the reaction was added. */ - void reactionAdded(Reaction* reaction); + void reactionAdded(Reaction* reaction, int index); /** * Emitted when the reaction is removed from this Step. Modified: trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.cpp 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.cpp 2010-03-29 06:46:22 UTC (rev 209) @@ -42,10 +42,10 @@ this, SLOT(update(Step*))); foreach(Reaction* reaction, step->reactions()) { - addReaction(reaction); + addReaction(reaction, mReactionTreeItems.count()); } - connect(step, SIGNAL(reactionAdded(Reaction*)), - this, SLOT(addReaction(Reaction*))); + connect(step, SIGNAL(reactionAdded(Reaction*, int)), + this, SLOT(addReaction(Reaction*, int))); connect(step, SIGNAL(reactionRemoved(Reaction*)), this, SLOT(removeReaction(Reaction*))); } @@ -118,12 +118,14 @@ childIndex++; } + + mReactionTreeItemBaseIndex = childIndex; } -void StepTreeItem::addReaction(Reaction* reaction) { +void StepTreeItem::addReaction(Reaction* reaction, int index) { ReactionTreeItem* reactionTreeItem = new ReactionTreeItem(reaction, this); - appendChild(reactionTreeItem); - mReactionTreeItems.append(reactionTreeItem); + insertChild(reactionTreeItem, mReactionTreeItemBaseIndex + index); + mReactionTreeItems.insert(index, reactionTreeItem); } void StepTreeItem::removeReaction(Reaction* reaction) { Modified: trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.h 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/src/view/StepTreeItem.h 2010-03-29 06:46:22 UTC (rev 209) @@ -127,6 +127,13 @@ QList<ReactionTreeItem*> mReactionTreeItems; /** + * The base index to add new ReactionTreeItems. + * It is the next index to the last optional data item (setup or tear down + * code). + */ + int mReactionTreeItemBaseIndex; + + /** * Returns the ReactionTreeItem for the given Reaction. * * @param reaction The Reaction to get its ReactionTreeItem. @@ -152,8 +159,9 @@ * Adds a new ReactionTreeItem when a Reaction is added in the step. * * @param step The Reaction added in the Step. + * @param index The index where the Reaction was added in the Step. */ - void addReaction(Reaction* reaction); + void addReaction(Reaction* reaction, int index); /** * Removes the ReactionTreeItem for the Reaction removed in the step. Modified: trunk/ktutorial/ktutorial-editor/tests/unit/commands/StepCommandsTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/commands/StepCommandsTest.cpp 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/tests/unit/commands/StepCommandsTest.cpp 2010-03-29 06:46:22 UTC (rev 209) @@ -47,8 +47,12 @@ void testAddReactionRedo(); void testAddReactionUndo(); + void testAddReactionAtIndexRedo(); + void testAddReactionAtIndexUndo(); + void testRemoveReactionRedo(); void testRemoveReactionUndo(); + void testRemoveReactionAtMiddleUndo(); }; @@ -204,6 +208,50 @@ QCOMPARE(step.reactions().count(), 0); } +void StepCommandsTest::testAddReactionAtIndexRedo() { + Step step; + StepCommands commands(&step); + QUndoCommand parent; + Reaction* reaction1 = new Reaction(); + Reaction* reaction2 = new Reaction(); + Reaction* reaction3 = new Reaction(); + + step.addReaction(reaction1); + step.addReaction(reaction3); + + QUndoCommand* command = commands.addReaction(reaction2, 1, &parent); + command->redo(); + + QCOMPARE(command->text(), i18nc("@action", "Add reaction")); + QCOMPARE(parent.child(0), command); + QCOMPARE(step.reactions().count(), 3); + QCOMPARE(step.reactions()[0], reaction1); + QCOMPARE(step.reactions()[1], reaction2); + QCOMPARE(step.reactions()[2], reaction3); +} + +void StepCommandsTest::testAddReactionAtIndexUndo() { + Step step; + StepCommands commands(&step); + QUndoCommand parent; + Reaction* reaction1 = new Reaction(); + Reaction* reaction2 = new Reaction(); + Reaction* reaction3 = new Reaction(); + + step.addReaction(reaction1); + step.addReaction(reaction3); + + QUndoCommand* command = commands.addReaction(reaction2, 1, &parent); + command->redo(); + command->undo(); + + QCOMPARE(command->text(), i18nc("@action", "Add reaction")); + QCOMPARE(parent.child(0), command); + QCOMPARE(step.reactions().count(), 2); + QCOMPARE(step.reactions()[0], reaction1); + QCOMPARE(step.reactions()[1], reaction3); +} + void StepCommandsTest::testRemoveReactionRedo() { Step step; StepCommands commands(&step); @@ -238,6 +286,30 @@ QCOMPARE(step.reactions()[0], reaction); } +void StepCommandsTest::testRemoveReactionAtMiddleUndo() { + Step step; + StepCommands commands(&step); + QUndoCommand parent; + Reaction* reaction1 = new Reaction(); + Reaction* reaction2 = new Reaction(); + Reaction* reaction3 = new Reaction(); + + step.addReaction(reaction1); + step.addReaction(reaction2); + step.addReaction(reaction3); + + QUndoCommand* command = commands.removeReaction(reaction2, &parent); + command->redo(); + command->undo(); + + QCOMPARE(command->text(), i18nc("@action", "Remove reaction")); + QCOMPARE(parent.child(0), command); + QCOMPARE(step.reactions().count(), 3); + QCOMPARE(step.reactions()[0], reaction1); + QCOMPARE(step.reactions()[1], reaction2); + QCOMPARE(step.reactions()[2], reaction3); +} + QTEST_MAIN(StepCommandsTest) #include "StepCommandsTest.moc" Modified: trunk/ktutorial/ktutorial-editor/tests/unit/data/StepTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/data/StepTest.cpp 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/tests/unit/data/StepTest.cpp 2010-03-29 06:46:22 UTC (rev 209) @@ -39,14 +39,18 @@ void testSetCustomTearDownCode(); void testAddReaction(); + void testAddReactionAtIndex(); void testRemoveReaction(); private: int mReactionStarType; - void assertReactionSignal(const QSignalSpy& spy, int index, - Reaction* reaction) const; + void assertReactionAddedSignal(const QSignalSpy& spy, int index, + Reaction* reaction, int reactionIndex) const; + void assertReactionRemovedSignal(const QSignalSpy& spy, int index, + Reaction* reaction) const; + }; void StepTest::initTestCase() { @@ -134,7 +138,7 @@ Reaction* reaction2 = new Reaction(); Reaction* reaction3 = new Reaction(); - QSignalSpy reactionAddedSpy(&step, SIGNAL(reactionAdded(Reaction*))); + QSignalSpy reactionAddedSpy(&step, SIGNAL(reactionAdded(Reaction*, int))); step.addReaction(reaction1); step.addReaction(reaction2); @@ -145,11 +149,33 @@ QCOMPARE(step.reactions()[1], reaction2); QCOMPARE(step.reactions()[2], reaction3); QCOMPARE(reactionAddedSpy.count(), 3); - assertReactionSignal(reactionAddedSpy, 0, reaction1); - assertReactionSignal(reactionAddedSpy, 1, reaction2); - assertReactionSignal(reactionAddedSpy, 2, reaction3); + assertReactionAddedSignal(reactionAddedSpy, 0, reaction1, 0); + assertReactionAddedSignal(reactionAddedSpy, 1, reaction2, 1); + assertReactionAddedSignal(reactionAddedSpy, 2, reaction3, 2); } +void StepTest::testAddReactionAtIndex() { + Step step; + Reaction* reaction1 = new Reaction(); + Reaction* reaction2 = new Reaction(); + Reaction* reaction3 = new Reaction(); + + QSignalSpy reactionAddedSpy(&step, SIGNAL(reactionAdded(Reaction*, int))); + + step.addReaction(reaction2, 0); + step.addReaction(reaction1, 0); + step.addReaction(reaction3, 2); + + QCOMPARE(step.reactions().count(), 3); + QCOMPARE(step.reactions()[0], reaction1); + QCOMPARE(step.reactions()[1], reaction2); + QCOMPARE(step.reactions()[2], reaction3); + QCOMPARE(reactionAddedSpy.count(), 3); + assertReactionAddedSignal(reactionAddedSpy, 0, reaction2, 0); + assertReactionAddedSignal(reactionAddedSpy, 1, reaction1, 0); + assertReactionAddedSignal(reactionAddedSpy, 2, reaction3, 2); +} + void StepTest::testRemoveReaction() { Step step; @@ -171,15 +197,15 @@ QCOMPARE(step.reactions()[0], &reaction1); QCOMPARE(step.reactions()[1], &reaction3); QCOMPARE(reactionRemovedSpy.count(), 1); - assertReactionSignal(reactionRemovedSpy, 0, &reaction2); + assertReactionRemovedSignal(reactionRemovedSpy, 0, &reaction2); step.removeReaction(&reaction1); step.removeReaction(&reaction3); QCOMPARE(step.reactions().count(), 0); QCOMPARE(reactionRemovedSpy.count(), 3); - assertReactionSignal(reactionRemovedSpy, 1, &reaction1); - assertReactionSignal(reactionRemovedSpy, 2, &reaction3); + assertReactionRemovedSignal(reactionRemovedSpy, 1, &reaction1); + assertReactionRemovedSignal(reactionRemovedSpy, 2, &reaction3); } /////////////////////////////////// Helpers //////////////////////////////////// @@ -187,8 +213,21 @@ //Reaction* must be declared as a metatype to be used in qvariant_cast Q_DECLARE_METATYPE(Reaction*); -void StepTest::assertReactionSignal(const QSignalSpy& spy, int index, - Reaction* reaction) const { +void StepTest::assertReactionAddedSignal(const QSignalSpy& spy, int index, + Reaction* reaction, + int reactionIndex) const { + QCOMPARE(spy.at(index).count(), 2); + + QVariant argument = spy.at(index).at(0); + QCOMPARE(argument.userType(), mReactionStarType); + QCOMPARE(qvariant_cast<Reaction*>(argument), reaction); + argument = spy.at(index).at(1); + QCOMPARE(argument.type(), QVariant::Int); + QCOMPARE(argument.toInt(), reactionIndex); +} + +void StepTest::assertReactionRemovedSignal(const QSignalSpy& spy, int index, + Reaction* reaction) const { QCOMPARE(spy.at(index).count(), 1); QVariant argument = spy.at(index).at(0); Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/StepTreeItemTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/StepTreeItemTest.cpp 2010-03-29 05:56:07 UTC (rev 208) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/StepTreeItemTest.cpp 2010-03-29 06:46:22 UTC (rev 209) @@ -53,6 +53,7 @@ void testStepSetCustomTearDownCodeEmpty(); void testStepAddReaction(); + void testStepAddReactionAtIndex(); void testStepRemoveReaction(); @@ -319,6 +320,26 @@ assertReaction(item.child(1), reaction); } +void StepTreeItemTest::testStepAddReactionAtIndex() { + Step step; + StepTreeItem item(&step); + + Reaction* reaction2 = new Reaction(); + step.addReaction(reaction2, 0); + + Reaction* reaction1 = new Reaction(); + step.addReaction(reaction1, 0); + + Reaction* reaction3 = new Reaction(); + step.addReaction(reaction3, 2); + + QCOMPARE(item.childCount(), 4); + assertEmptyText(item.child(0)); + assertReaction(item.child(1), reaction1); + assertReaction(item.child(2), reaction2); + assertReaction(item.child(3), reaction3); +} + void StepTreeItemTest::testStepRemoveReaction() { Step step; StepTreeItem item(&step); @@ -380,15 +401,28 @@ assertReaction(item.child(3), reaction1); assertReaction(item.child(4), reaction2); + Reaction* reaction3 = new Reaction(); + step.addReaction(reaction3, 1); + + QCOMPARE(item.text(), i18nc("@item", "Step (id not set)")); + QCOMPARE(item.childCount(), 6); + assertText(item.child(0), "The text"); + assertCustomSetupCode(item.child(1), "The setup code"); + assertCustomTearDownCode(item.child(2), "The tear down code"); + assertReaction(item.child(3), reaction1); + assertReaction(item.child(4), reaction3); + assertReaction(item.child(5), reaction2); + step.setId("The id"); QCOMPARE(item.text(), i18nc("@item", "Step %1", "The id")); - QCOMPARE(item.childCount(), 5); + QCOMPARE(item.childCount(), 6); assertText(item.child(0), "The text"); assertCustomSetupCode(item.child(1), "The setup code"); assertCustomTearDownCode(item.child(2), "The tear down code"); assertReaction(item.child(3), reaction1); - assertReaction(item.child(4), reaction2); + assertReaction(item.child(4), reaction3); + assertReaction(item.child(5), reaction2); } void StepTreeItemTest::testChildOrderWhenUnsettingDataInStep() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 05:56:14
|
Revision: 208 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=208&view=rev Author: danxuliu Date: 2010-03-29 05:56:07 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Fix removing an step from the middle and undoing the operation (the step was readded at the end). It required being able to add steps at any position in the tutorial, and not only at the end. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h trunk/ktutorial/ktutorial-editor/src/data/Tutorial.cpp trunk/ktutorial/ktutorial-editor/src/data/Tutorial.h trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.cpp trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.h trunk/ktutorial/ktutorial-editor/tests/unit/commands/TutorialCommandsTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/data/TutorialTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/view/TutorialTreeItemTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp 2010-03-29 05:56:07 UTC (rev 208) @@ -165,21 +165,46 @@ mDeleteStepInDestructor = true; } + virtual void undo() { + mDeleteStepInDestructor = true; + mTutorial->removeStep(mStep); + } + +}; + +class AddStepAtEnd: public AddStep { +public: + + AddStepAtEnd(QUndoCommand* parent = 0): AddStep(parent) { + } + virtual void redo() { mDeleteStepInDestructor = false; mTutorial->addStep(mStep); } - virtual void undo() { - mDeleteStepInDestructor = true; - mTutorial->removeStep(mStep); +}; + +class AddStepAtIndex: public AddStep { +public: + + int mIndex; + + AddStepAtIndex(QUndoCommand* parent = 0): AddStep(parent) { } + virtual void redo() { + mDeleteStepInDestructor = false; + mTutorial->addStep(mStep, mIndex); + } + }; class RemoveStep: public BaseStepCommand { public: + int mIndex; + RemoveStep(QUndoCommand* parent = 0): BaseStepCommand(parent) { setText(i18nc("@action", "Remove step")); mDeleteStepInDestructor = false; @@ -187,12 +212,13 @@ virtual void redo() { mDeleteStepInDestructor = true; + mIndex = mTutorial->steps().indexOf(mStep); mTutorial->removeStep(mStep); } virtual void undo() { mDeleteStepInDestructor = false; - mTutorial->addStep(mStep); + mTutorial->addStep(mStep, mIndex); } }; @@ -246,12 +272,21 @@ } QUndoCommand* TutorialCommands::addStep(Step* step, QUndoCommand* parent) { - AddStep* command = new AddStep(parent); + AddStepAtEnd* command = new AddStepAtEnd(parent); command->mTutorial = mTutorial; command->mStep = step; return command; } +QUndoCommand* TutorialCommands::addStep(Step* step, int index, + QUndoCommand* parent) { + AddStepAtIndex* command = new AddStepAtIndex(parent); + command->mTutorial = mTutorial; + command->mStep = step; + command->mIndex = index; + return command; +} + QUndoCommand* TutorialCommands::removeStep(Step* step, QUndoCommand* parent) { RemoveStep* command = new RemoveStep(parent); command->mTutorial = mTutorial; Modified: trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h 2010-03-29 05:56:07 UTC (rev 208) @@ -107,6 +107,19 @@ QUndoCommand* addStep(Step* step, QUndoCommand* parent = 0); /** + * Creates a new undoable command to add the given step to the tutorial at + * the given index. + * If the command was not executed yet, or it was undone, the step is + * deleted when the command is deleted. + * + * @param step The step to add to the tutorial. + * @param index The index to add the step at. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* addStep(Step* step, int index, QUndoCommand* parent = 0); + + /** * Creates a new undoable command to remove the given step from the * tutorial. * If the command was executed and not undone, the step is deleted when the Modified: trunk/ktutorial/ktutorial-editor/src/data/Tutorial.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/data/Tutorial.cpp 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/src/data/Tutorial.cpp 2010-03-29 05:56:07 UTC (rev 208) @@ -86,11 +86,15 @@ } void Tutorial::addStep(Step* step) { + addStep(step, mSteps.count()); +} + +void Tutorial::addStep(Step* step, int index) { Q_ASSERT(!mSteps.contains(step)); - mSteps.append(step); + mSteps.insert(index, step); - emit stepAdded(step); + emit stepAdded(step, index); } QList<Step*> Tutorial::steps() const { Modified: trunk/ktutorial/ktutorial-editor/src/data/Tutorial.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/data/Tutorial.h 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/src/data/Tutorial.h 2010-03-29 05:56:07 UTC (rev 208) @@ -31,8 +31,8 @@ * generate the code to create a true KTutorial::Tutorial. * * When any attribute is modified, dataChanged(Tutorial*) signal is emitted. - * When steps are added or removed, stepAdded(Step*) and stepRemoved(Step*) are - * emitted. + * When steps are added or removed, stepAdded(Step*, int) and stepRemoved(Step*) + * are emitted. */ class Tutorial: public QObject { Q_OBJECT @@ -76,6 +76,17 @@ * @param step The step to add. */ void addStep(Step* step); + + /** + * Adds a new step to this Tutorial at the given position. + * The Tutorial gets ownership of the Step, so it is deleted when the + * Tutorial is deleted. + * + * @param step The step to add. + * @param index The index to add the step at. + */ + void addStep(Step* step, int index); + QList<Step*> steps() const; /** @@ -99,8 +110,9 @@ * Emitted when the step is added to the tutorial. * * @param step The step added. + * @param index The index where the step was added. */ - void stepAdded(Step* step); + void stepAdded(Step* step, int index); /** * Emitted when the step is removed from the tutorial. Modified: trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.cpp 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.cpp 2010-03-29 05:56:07 UTC (rev 208) @@ -44,10 +44,10 @@ this, SLOT(update(Tutorial*))); foreach(Step* step, tutorial->steps()) { - addStep(step); + addStep(step, mStepTreeItems.count()); } - connect(tutorial, SIGNAL(stepAdded(Step*)), - this, SLOT(addStep(Step*))); + connect(tutorial, SIGNAL(stepAdded(Step*, int)), + this, SLOT(addStep(Step*, int))); connect(tutorial, SIGNAL(stepRemoved(Step*)), this, SLOT(removeStep(Step*))); } @@ -131,12 +131,14 @@ childIndex++; } + + mStepTreeItemBaseIndex = childIndex; } -void TutorialTreeItem::addStep(Step* step) { +void TutorialTreeItem::addStep(Step* step, int index) { StepTreeItem* stepTreeItem = new StepTreeItem(step, this); - appendChild(stepTreeItem); - mStepTreeItems.append(stepTreeItem); + insertChild(stepTreeItem, mStepTreeItemBaseIndex + index); + mStepTreeItems.insert(index, stepTreeItem); } void TutorialTreeItem::removeStep(Step* step) { Modified: trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.h 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/src/view/TutorialTreeItem.h 2010-03-29 05:56:07 UTC (rev 208) @@ -38,9 +38,9 @@ * | -The custom setup code * |-Tear down: * | -The custom tear down code - * |-Step first step added + * |-Step first step * | ... - * |-Step second step added + * |-Step second step * | ... * ... * @@ -131,6 +131,13 @@ QList<StepTreeItem*> mStepTreeItems; /** + * The base index to add new StepTreeItems. + * It is the next index to the last optional data item (license, setup or + * tear down code). + */ + int mStepTreeItemBaseIndex; + + /** * Returns the StepTreeItem for the given Step. * * @param step The Step to get its StepTreeItem. @@ -156,8 +163,9 @@ * Adds a new StepTreeItem when a Step is added in the tutorial. * * @param step The Step added in the Tutorial. + * @param index The index where the Step was added in the Tutorial. */ - void addStep(Step* step); + void addStep(Step* step, int index); /** * Removes the StepTreeItem for the Step removed in the tutorial. Modified: trunk/ktutorial/ktutorial-editor/tests/unit/commands/TutorialCommandsTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/commands/TutorialCommandsTest.cpp 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/tests/unit/commands/TutorialCommandsTest.cpp 2010-03-29 05:56:07 UTC (rev 208) @@ -50,8 +50,12 @@ void testAddStepRedo(); void testAddStepUndo(); + void testAddStepAtIndexRedo(); + void testAddStepAtIndexUndo(); + void testRemoveStepRedo(); void testRemoveStepUndo(); + void testRemoveStepAtMiddleUndo(); }; @@ -239,6 +243,50 @@ QCOMPARE(tutorial.steps().count(), 0); } +void TutorialCommandsTest::testAddStepAtIndexRedo() { + Tutorial tutorial; + TutorialCommands commands(&tutorial); + QUndoCommand parent; + Step* step1 = new Step(); + Step* step2 = new Step(); + Step* step3 = new Step(); + + tutorial.addStep(step1); + tutorial.addStep(step3); + + QUndoCommand* command = commands.addStep(step2, 1, &parent); + command->redo(); + + QCOMPARE(command->text(), i18nc("@action", "Add step")); + QCOMPARE(parent.child(0), command); + QCOMPARE(tutorial.steps().count(), 3); + QCOMPARE(tutorial.steps()[0], step1); + QCOMPARE(tutorial.steps()[1], step2); + QCOMPARE(tutorial.steps()[2], step3); +} + +void TutorialCommandsTest::testAddStepAtIndexUndo() { + Tutorial tutorial; + TutorialCommands commands(&tutorial); + QUndoCommand parent; + Step* step1 = new Step(); + Step* step2 = new Step(); + Step* step3 = new Step(); + + tutorial.addStep(step1); + tutorial.addStep(step3); + + QUndoCommand* command = commands.addStep(step2, 1, &parent); + command->redo(); + command->undo(); + + QCOMPARE(command->text(), i18nc("@action", "Add step")); + QCOMPARE(parent.child(0), command); + QCOMPARE(tutorial.steps().count(), 2); + QCOMPARE(tutorial.steps()[0], step1); + QCOMPARE(tutorial.steps()[1], step3); +} + void TutorialCommandsTest::testRemoveStepRedo() { Tutorial tutorial; TutorialCommands commands(&tutorial); @@ -273,6 +321,30 @@ QCOMPARE(tutorial.steps()[0], step); } +void TutorialCommandsTest::testRemoveStepAtMiddleUndo() { + Tutorial tutorial; + TutorialCommands commands(&tutorial); + QUndoCommand parent; + Step* step1 = new Step(); + Step* step2 = new Step(); + Step* step3 = new Step(); + + tutorial.addStep(step1); + tutorial.addStep(step2); + tutorial.addStep(step3); + + QUndoCommand* command = commands.removeStep(step2, &parent); + command->redo(); + command->undo(); + + QCOMPARE(command->text(), i18nc("@action", "Remove step")); + QCOMPARE(parent.child(0), command); + QCOMPARE(tutorial.steps().count(), 3); + QCOMPARE(tutorial.steps()[0], step1); + QCOMPARE(tutorial.steps()[1], step2); + QCOMPARE(tutorial.steps()[2], step3); +} + QTEST_MAIN(TutorialCommandsTest) #include "TutorialCommandsTest.moc" Modified: trunk/ktutorial/ktutorial-editor/tests/unit/data/TutorialTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/data/TutorialTest.cpp 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/tests/unit/data/TutorialTest.cpp 2010-03-29 05:56:07 UTC (rev 208) @@ -45,13 +45,16 @@ void testSetCustomTearDownCode(); void testAddStep(); + void testAddStepAtIndex(); void testRemoveStep(); private: int mStepStarType; - void assertStepSignal(const QSignalSpy& spy, int index, Step* step); + void assertStepAddedSignal(const QSignalSpy& spy, int index, Step* step, + int stepIndex); + void assertStepRemovedSignal(const QSignalSpy& spy, int index, Step* step); }; @@ -180,7 +183,7 @@ Step* step2 = new Step(); Step* step3 = new Step(); - QSignalSpy stepAddedSpy(&tutorial, SIGNAL(stepAdded(Step*))); + QSignalSpy stepAddedSpy(&tutorial, SIGNAL(stepAdded(Step*, int))); tutorial.addStep(step1); tutorial.addStep(step2); @@ -191,11 +194,33 @@ QCOMPARE(tutorial.steps()[1], step2); QCOMPARE(tutorial.steps()[2], step3); QCOMPARE(stepAddedSpy.count(), 3); - assertStepSignal(stepAddedSpy, 0, step1); - assertStepSignal(stepAddedSpy, 1, step2); - assertStepSignal(stepAddedSpy, 2, step3); + assertStepAddedSignal(stepAddedSpy, 0, step1, 0); + assertStepAddedSignal(stepAddedSpy, 1, step2, 1); + assertStepAddedSignal(stepAddedSpy, 2, step3, 2); } +void TutorialTest::testAddStepAtIndex() { + Tutorial tutorial; + Step* step1 = new Step(); + Step* step2 = new Step(); + Step* step3 = new Step(); + + QSignalSpy stepAddedSpy(&tutorial, SIGNAL(stepAdded(Step*, int))); + + tutorial.addStep(step2, 0); + tutorial.addStep(step1, 0); + tutorial.addStep(step3, 2); + + QCOMPARE(tutorial.steps().count(), 3); + QCOMPARE(tutorial.steps()[0], step1); + QCOMPARE(tutorial.steps()[1], step2); + QCOMPARE(tutorial.steps()[2], step3); + QCOMPARE(stepAddedSpy.count(), 3); + assertStepAddedSignal(stepAddedSpy, 0, step2, 0); + assertStepAddedSignal(stepAddedSpy, 1, step1, 0); + assertStepAddedSignal(stepAddedSpy, 2, step3, 2); +} + void TutorialTest::testRemoveStep() { Tutorial tutorial; @@ -217,21 +242,33 @@ QCOMPARE(tutorial.steps()[0], &step1); QCOMPARE(tutorial.steps()[1], &step3); QCOMPARE(stepRemovedSpy.count(), 1); - assertStepSignal(stepRemovedSpy, 0, &step2); + assertStepRemovedSignal(stepRemovedSpy, 0, &step2); tutorial.removeStep(&step1); tutorial.removeStep(&step3); QCOMPARE(tutorial.steps().count(), 0); QCOMPARE(stepRemovedSpy.count(), 3); - assertStepSignal(stepRemovedSpy, 1, &step1); - assertStepSignal(stepRemovedSpy, 2, &step3); + assertStepRemovedSignal(stepRemovedSpy, 1, &step1); + assertStepRemovedSignal(stepRemovedSpy, 2, &step3); } /////////////////////////////////// Helpers //////////////////////////////////// -void TutorialTest::assertStepSignal(const QSignalSpy& spy, int index, - Step* step) { +void TutorialTest::assertStepAddedSignal(const QSignalSpy& spy, int index, + Step* step, int stepIndex) { + QCOMPARE(spy.at(index).count(), 2); + + QVariant argument = spy.at(index).at(0); + QCOMPARE(argument.userType(), mStepStarType); + QCOMPARE(qvariant_cast<Step*>(argument), step); + argument = spy.at(index).at(1); + QCOMPARE(argument.type(), QVariant::Int); + QCOMPARE(argument.toInt(), stepIndex); +} + +void TutorialTest::assertStepRemovedSignal(const QSignalSpy& spy, int index, + Step* step) { QCOMPARE(spy.at(index).count(), 1); QVariant argument = spy.at(index).at(0); Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/TutorialTreeItemTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/TutorialTreeItemTest.cpp 2010-03-29 03:59:41 UTC (rev 207) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/TutorialTreeItemTest.cpp 2010-03-29 05:56:07 UTC (rev 208) @@ -57,6 +57,7 @@ void testTutorialSetCustomTearDownCodeEmpty(); void testTutorialAddStep(); + void testTutorialAddStepAtIndex(); void testTutorialRemoveStep(); @@ -398,6 +399,30 @@ assertStep(item.child(2), "Step id"); } +void TutorialTreeItemTest::testTutorialAddStepAtIndex() { + Tutorial tutorial; + TutorialTreeItem item(&tutorial); + + Step* step2 = new Step(); + step2->setId("Step id2"); + tutorial.addStep(step2, 0); + + Step* step1 = new Step(); + step1->setId("Step id1"); + tutorial.addStep(step1, 0); + + Step* step3 = new Step(); + step3->setId("Step id3"); + tutorial.addStep(step3, 2); + + QCOMPARE(item.childCount(), 5); + assertEmptyName(item.child(0)); + assertEmptyDescription(item.child(1)); + assertStep(item.child(2), "Step id1"); + assertStep(item.child(3), "Step id2"); + assertStep(item.child(4), "Step id3"); +} + void TutorialTreeItemTest::testTutorialRemoveStep() { Tutorial tutorial; TutorialTreeItem item(&tutorial); @@ -478,17 +503,32 @@ assertStep(item.child(4), "First step"); assertStep(item.child(5), "Second step"); - tutorial.setLicenseText("The license text"); + Step* step3 = new Step(); + step3->setId("Third step"); + tutorial.addStep(step3, 1); QCOMPARE(item.text(), i18nc("@item", "Tutorial %1", "theName")); QCOMPARE(item.childCount(), 7); assertName(item.child(0), "The name"); assertDescription(item.child(1), "The description"); + assertCustomSetupCode(item.child(2), "The setup code"); + assertCustomTearDownCode(item.child(3), "The tear down code"); + assertStep(item.child(4), "First step"); + assertStep(item.child(5), "Third step"); + assertStep(item.child(6), "Second step"); + + tutorial.setLicenseText("The license text"); + + QCOMPARE(item.text(), i18nc("@item", "Tutorial %1", "theName")); + QCOMPARE(item.childCount(), 8); + assertName(item.child(0), "The name"); + assertDescription(item.child(1), "The description"); assertLicenseText(item.child(2), "The license text"); assertCustomSetupCode(item.child(3), "The setup code"); assertCustomTearDownCode(item.child(4), "The tear down code"); assertStep(item.child(5), "First step"); - assertStep(item.child(6), "Second step"); + assertStep(item.child(6), "Third step"); + assertStep(item.child(7), "Second step"); } void TutorialTreeItemTest::testChildOrderWhenUnsettingDataInTutorial() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 03:59:47
|
Revision: 207 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=207&view=rev Author: danxuliu Date: 2010-03-29 03:59:41 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Ensure that no unnecessary commands are created to set a WaitFor Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp trunk/ktutorial/ktutorial-editor/tests/unit/view/ReactionWidgetTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp 2010-03-29 03:15:38 UTC (rev 206) +++ trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp 2010-03-29 03:59:41 UTC (rev 207) @@ -86,8 +86,10 @@ commands.append(reactionCommands.setOptionName(optionName, parent)); } - if (!mReaction->waitFor() || !mWaitForWidget->waitFor() || - *mReaction->waitFor() != *mWaitForWidget->waitFor()) { + if ((!mReaction->waitFor() && mWaitForWidget->waitFor()) || + (mReaction->waitFor() && !mWaitForWidget->waitFor()) || + (mReaction->waitFor() && mWaitForWidget->waitFor() && + *mReaction->waitFor() != *mWaitForWidget->waitFor())) { commands.append(reactionCommands.setWaitFor(mWaitForWidget->waitFor(), parent)); Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/ReactionWidgetTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/ReactionWidgetTest.cpp 2010-03-29 03:15:38 UTC (rev 206) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/ReactionWidgetTest.cpp 2010-03-29 03:59:41 UTC (rev 207) @@ -22,6 +22,7 @@ #include <QRadioButton> #include <QTreeView> +#include <QUndoStack> #include <KComboBox> #include <KDialog> @@ -48,7 +49,10 @@ void testSelectResponseTypeCustomCode(); void testSaveChanges(); - void testSaveChangesWithNoWaitFor(); + void testSaveChangesAddRootWaitFor(); + void testSaveChangesRemoveRootWaitFor(); + void testSaveChangesNoOldWaitForAndNoNewWaitFor(); + void testSaveChangesEqualWaitFor(); private: @@ -63,6 +67,7 @@ void addWaitForSignal(ReactionWidget* widget); void addWaitForSignalToRootWaitFor(ReactionWidget* widget); + void removeRootWaitFor(ReactionWidget* widget); }; @@ -180,21 +185,61 @@ QCOMPARE(reaction.customCode(), QString("The custom code")); } -void ReactionWidgetTest::testSaveChangesWithNoWaitFor() { +void ReactionWidgetTest::testSaveChangesAddRootWaitFor() { Reaction reaction; reaction.setTriggerType(Reaction::ConditionMet); ReactionWidget widget(&reaction); + addWaitForSignal(&widget); widget.saveChanges(); + QVERIFY(reaction.waitFor() != 0); + QVERIFY(qobject_cast<WaitForSignal*>(reaction.waitFor())); +} + +void ReactionWidgetTest::testSaveChangesRemoveRootWaitFor() { + Reaction reaction; + reaction.setTriggerType(Reaction::ConditionMet); + reaction.setWaitFor(new WaitForSignal()); + + ReactionWidget widget(&reaction); + + removeRootWaitFor(&widget); + widget.saveChanges(); + QCOMPARE(reaction.waitFor(), (WaitFor*)0); +} +void ReactionWidgetTest::testSaveChangesNoOldWaitForAndNoNewWaitFor() { + Reaction reaction; + + ReactionWidget widget(&reaction); + + QUndoStack undoStack; + widget.setUndoStack(&undoStack); + + widget.saveChanges(); + + QCOMPARE(undoStack.count(), 0); + QCOMPARE(reaction.waitFor(), (WaitFor*)0); +} + +void ReactionWidgetTest::testSaveChangesEqualWaitFor() { + Reaction reaction; + WaitForSignal* waitFor = new WaitForSignal(); + reaction.setWaitFor(waitFor); + + ReactionWidget widget(&reaction); + + QUndoStack undoStack; + widget.setUndoStack(&undoStack); + addWaitForSignal(&widget); widget.saveChanges(); - QVERIFY(reaction.waitFor() != 0); - QVERIFY(qobject_cast<WaitForSignal*>(reaction.waitFor())); + QCOMPARE(undoStack.count(), 0); + QCOMPARE(reaction.waitFor(), waitFor); } /////////////////////////////////// Helpers //////////////////////////////////// @@ -286,6 +331,14 @@ addWaitForSignal(widget); } +void ReactionWidgetTest::removeRootWaitFor(ReactionWidget* widget) { + QTreeView* tree = widget->findChild<QTreeView*>("waitForTreeView"); + QModelIndex index = tree->model()->index(0, 0); + tree->selectionModel()->select(index, QItemSelectionModel::SelectCurrent); + + widget->findChild<KPushButton*>("removeButton")->click(); +} + QTEST_MAIN(ReactionWidgetTest) #include "ReactionWidgetTest.moc" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 03:15:44
|
Revision: 206 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=206&view=rev Author: danxuliu Date: 2010-03-29 03:15:38 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Refactor the code to save the trigger and response types Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.h Modified: trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp 2010-03-29 00:36:12 UTC (rev 205) +++ trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp 2010-03-29 03:15:38 UTC (rev 206) @@ -51,12 +51,14 @@ connect(ui->responseStepRadioButton, SIGNAL(toggled(bool)), this, SLOT(selectResponseStep(bool))); + mCurrentTriggerType = reaction->triggerType(); if (reaction->triggerType() == Reaction::ConditionMet) { ui->triggerConditionRadioButton->setChecked(true); } else { ui->triggerOptionRadioButton->setChecked(true); } + mCurrentResponseType = reaction->responseType(); if (reaction->responseType() == Reaction::CustomCode) { ui->responseCodeRadioButton->setChecked(true); } else { @@ -106,30 +108,16 @@ commands.append(reactionCommands.setNextStepId(nextStepId, parent)); } - if (mReaction->triggerType() != Reaction::ConditionMet && - ui->triggerConditionRadioButton->isChecked()) { - commands.append(reactionCommands.setTriggerType(Reaction::ConditionMet, + if (mReaction->triggerType() != mCurrentTriggerType) { + commands.append(reactionCommands.setTriggerType(mCurrentTriggerType, parent)); } - if (mReaction->triggerType() != Reaction::OptionSelected && - ui->triggerOptionRadioButton->isChecked()) { - commands.append(reactionCommands.setTriggerType(Reaction::OptionSelected, - parent)); - } - - if (mReaction->responseType() != Reaction::CustomCode && - ui->responseCodeRadioButton->isChecked()) { - commands.append(reactionCommands.setResponseType(Reaction::CustomCode, + if (mReaction->responseType() != mCurrentResponseType) { + commands.append(reactionCommands.setResponseType(mCurrentResponseType, parent)); } - if (mReaction->responseType() != Reaction::NextStep && - ui->responseStepRadioButton->isChecked()) { - commands.append(reactionCommands.setResponseType(Reaction::NextStep, - parent)); - } - return commands; } @@ -142,6 +130,8 @@ ui->triggerOptionLineEdit->setEnabled(false); mWaitForWidget->setEnabled(true); + + mCurrentTriggerType = Reaction::ConditionMet; } void ReactionWidget::selectTriggerOption(bool checked) { @@ -151,6 +141,8 @@ mWaitForWidget->setEnabled(false); ui->triggerOptionLineEdit->setEnabled(true); + + mCurrentTriggerType = Reaction::OptionSelected; } void ReactionWidget::selectResponseStep(bool checked) { @@ -160,6 +152,8 @@ ui->responseCodeTextEdit->setEnabled(false); ui->responseStepLineEdit->setEnabled(true); + + mCurrentResponseType = Reaction::NextStep; } void ReactionWidget::selectResponseCode(bool checked) { @@ -169,4 +163,6 @@ ui->responseStepLineEdit->setEnabled(false); ui->responseCodeTextEdit->setEnabled(true); + + mCurrentResponseType = Reaction::CustomCode; } Modified: trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.h 2010-03-29 00:36:12 UTC (rev 205) +++ trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.h 2010-03-29 03:15:38 UTC (rev 206) @@ -22,8 +22,8 @@ #include <QPointer> #include "CommandWidget.h" +#include "../data/Reaction.h" -class Reaction; class WaitFor; class WaitForWidget; @@ -84,6 +84,16 @@ WaitForWidget* mWaitForWidget; /** + * The currently selected trigger type. + */ + Reaction::TriggerType mCurrentTriggerType; + + /** + * The currently selected response type. + */ + Reaction::ResponseType mCurrentResponseType; + + /** * The Ui Designer generated class. */ Ui::ReactionWidget* ui; @@ -92,7 +102,7 @@ /** * When the condition radio button is selected, it enables and disables the - * appropriate widgets. + * appropriate widgets, and updates the current trigger type. * * @param checked Whether the radio button was checked or unchecked. */ @@ -100,7 +110,7 @@ /** * When the option radio button is selected, it enables and disables the - * appropriate widgets. + * appropriate widgets, and updates the current trigger type. * * @param checked Whether the radio button was checked or unchecked. */ @@ -108,7 +118,7 @@ /** * When the custom code radio button is selected, it enables and disables - * the appropriate widgets. + * the appropriate widgets, and updates the current response type. * * @param checked Whether the radio button was checked or unchecked. */ @@ -116,7 +126,7 @@ /** * When the next step radio button is selected, it enables and disables the - * appropriate widgets. + * appropriate widgets, and updates the current response type. * * @param checked Whether the radio button was checked or unchecked. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-29 00:36:20
|
Revision: 205 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=205&view=rev Author: danxuliu Date: 2010-03-29 00:36:12 +0000 (Mon, 29 Mar 2010) Log Message: ----------- Add undo/redo support for every edit action Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.h trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.h trunk/ktutorial/ktutorial-editor/src/view/StepCustomCodeWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/StepCustomCodeWidget.h trunk/ktutorial/ktutorial-editor/src/view/StepDataWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/StepDataWidget.h trunk/ktutorial/ktutorial-editor/src/view/TutorialCustomCodeWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/TutorialCustomCodeWidget.h trunk/ktutorial/ktutorial-editor/src/view/TutorialInformationWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/TutorialInformationWidget.h trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/commands/ trunk/ktutorial/ktutorial-editor/src/commands/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.cpp trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.h trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.h trunk/ktutorial/ktutorial-editor/tests/unit/commands/ trunk/ktutorial/ktutorial-editor/tests/unit/commands/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/commands/ReactionCommandsTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/commands/StepCommandsTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/commands/TutorialCommandsTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/view/CommandWidgetTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-29 00:36:12 UTC (rev 205) @@ -4,6 +4,7 @@ include_directories(${KDE4_INCLUDES}) +add_subdirectory(commands) add_subdirectory(data) add_subdirectory(serialization) add_subdirectory(view) Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -28,8 +28,11 @@ #include <KFileFilterCombo> #include <KLocalizedString> #include <KMessageBox> +#include <KUndoStack> #include <KIO/NetAccess> +#include "commands/StepCommands.h" +#include "commands/TutorialCommands.h" #include "data/Reaction.h" #include "data/Step.h" #include "data/Tutorial.h" @@ -57,6 +60,7 @@ mTreeView->setObjectName("centralTreeView"); setCentralWidget(mTreeView); + mUndoStack = new KUndoStack(this); setTutorialToBeEdited(); setupDocks(); @@ -105,6 +109,8 @@ connect(selectionManager, SIGNAL(reactionSelected(Reaction*)), this, SLOT(selectReaction(Reaction*))); + mUndoStack->clear(); + delete mTutorial; mTutorial = tutorial; } @@ -162,6 +168,10 @@ KStandardAction::quit(kapp, SLOT(quit()), actionCollection()); + mUndoStack->createUndoAction(actionCollection()); + + mUndoStack->createRedoAction(actionCollection()); + ActionListWidget* actionListWidget = new ActionListWidget(mTutorialActionDock); @@ -298,8 +308,10 @@ mReactionActionDock->toggleViewAction()); } -int KTutorialEditor::showEditionDialog(EditionWidget* editionWidget) { - EditionDialog* dialog = new EditionDialog(editionWidget, this); +int KTutorialEditor::showEditionDialog(CommandWidget* commandWidget) { + commandWidget->setUndoStack(mUndoStack); + + EditionDialog* dialog = new EditionDialog(commandWidget, this); dialog->setObjectName("editionDialog"); int dialogCode = dialog->exec(); dialog->deleteLater(); @@ -468,10 +480,14 @@ void KTutorialEditor::addStep() { Step* step = new Step(); - if (showEditionDialog(new StepDataWidget(step)) == QDialog::Accepted) { - mTutorial->addStep(step); - } else { - delete step; + QUndoCommand* parentCommand = new QUndoCommand(); + parentCommand->setText(i18nc("@action", "Add step")); + TutorialCommands(mTutorial).addStep(step, parentCommand); + + CommandWidget* widget = new StepDataWidget(step); + widget->setParentUndoCommand(parentCommand); + if (showEditionDialog(widget) == QDialog::Rejected) { + delete parentCommand; } } @@ -494,12 +510,7 @@ void KTutorialEditor::removeStep() { Q_ASSERT(mCurrentStep); - //When the step is removed, mCurrentStep is changed because the selected - //item in the tree view changes. As mCurrentStep is one of the valid steps - //in the tutorial, deleting it leads to a crash the next time it is used. - Step* stepToRemove = mCurrentStep; - mTutorial->removeStep(stepToRemove); - stepToRemove->deleteLater(); + mUndoStack->push(TutorialCommands(mTutorial).removeStep(mCurrentStep)); } void KTutorialEditor::addReaction() { @@ -507,10 +518,14 @@ Reaction* reaction = new Reaction(); - if (showEditionDialog(new ReactionWidget(reaction)) == QDialog::Accepted) { - mCurrentStep->addReaction(reaction); - } else { - delete reaction; + QUndoCommand* parentCommand = new QUndoCommand(); + parentCommand->setText(i18nc("@action", "Add reaction")); + StepCommands(mCurrentStep).addReaction(reaction, parentCommand); + + CommandWidget* widget = new ReactionWidget(reaction); + widget->setParentUndoCommand(parentCommand); + if (showEditionDialog(widget) == QDialog::Rejected) { + delete parentCommand; } } @@ -523,11 +538,6 @@ void KTutorialEditor::removeReaction() { Q_ASSERT(mCurrentStep); - //When the reaction is removed, mCurrentReaction is changed because the - //selected item in the tree view changes. As mCurrentReaction is one of the - //valid reactions in the step, deleting it leads to a crash the next time it - //is used. - Reaction* reactionToRemove = mCurrentReaction; - mCurrentStep->removeReaction(reactionToRemove); - reactionToRemove->deleteLater(); + mUndoStack->push(StepCommands(mCurrentStep).removeReaction( + mCurrentReaction)); } Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-29 00:36:12 UTC (rev 205) @@ -22,7 +22,9 @@ #include <KXmlGuiWindow> #include <KUrl> +class CommandWidget; class EditionWidget; +class KUndoStack; class QTreeView; class Reaction; class Step; @@ -64,6 +66,11 @@ QDockWidget* mReactionActionDock; /** + * The stack of undoable commands. + */ + KUndoStack* mUndoStack; + + /** * The tutorial being edited. */ Tutorial* mTutorial; @@ -115,13 +122,14 @@ void setupActions(); /** - * Shows an EditionDialog for the given EditionWidget. + * Shows an EditionDialog for the given CommandWidget. + * The undo stack used in the CommandWidget is mUndoStack. * - * @param editionWidget The EditionWidget to wrap. + * @param commandWidget The CommandWidget to wrap. * @return QDialog::Accepted if the dialog was accepted, or * QDialog::Rejected if the dialog was rejected. */ - int showEditionDialog(EditionWidget* editionWidget); + int showEditionDialog(CommandWidget* commandWidget); private Q_SLOTS: Added: trunk/ktutorial/ktutorial-editor/src/commands/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/CMakeLists.txt 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,9 @@ +set(ktutorial_editor_commands_SRCS + ReactionCommands.cpp + StepCommands.cpp + TutorialCommands.cpp +) + +kde4_add_library(ktutorial_editor_commands ${ktutorial_editor_commands_SRCS}) + +target_link_libraries(ktutorial_editor_commands ktutorial_editor_data ${KDE4_KDEUI_LIBS}) Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,226 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "ReactionCommands.h" + +#include <QUndoCommand> + +#include <KLocalizedString> + +#include "../data/Reaction.h" +#include "../data/WaitFor.h" + +class SetReactionTriggerType: public QUndoCommand { +public: + + Reaction* mReaction; + Reaction::TriggerType mOldTriggerType; + Reaction::TriggerType mNewTriggerType; + + SetReactionTriggerType(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set reaction trigger type")); + } + + virtual void redo() { + mOldTriggerType = mReaction->triggerType(); + mReaction->setTriggerType(mNewTriggerType); + } + + virtual void undo() { + mReaction->setTriggerType(mOldTriggerType); + } + +}; + +class SetReactionOptionName: public QUndoCommand { +public: + + Reaction* mReaction; + QString mOldOptionName; + QString mNewOptionName; + + SetReactionOptionName(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set reaction option name")); + } + + virtual void redo() { + mOldOptionName = mReaction->optionName(); + mReaction->setOptionName(mNewOptionName); + } + + virtual void undo() { + mReaction->setOptionName(mOldOptionName); + } + +}; + +class SetReactionWaitFor: public QUndoCommand { +public: + + Reaction* mReaction; + WaitFor* mOldWaitFor; + WaitFor* mNewWaitFor; + bool mRedoDone; + + SetReactionWaitFor(QUndoCommand* parent = 0): QUndoCommand(parent), + mRedoDone(false) { + setText(i18nc("@action", "Set reaction condition to wait for")); + } + + virtual ~SetReactionWaitFor() { + if (mRedoDone) { + delete mOldWaitFor; + } else { + delete mNewWaitFor; + } + } + + virtual void redo() { + mRedoDone = true; + mOldWaitFor = mReaction->waitFor(); + mReaction->setWaitFor(mNewWaitFor); + } + + virtual void undo() { + mRedoDone = false; + mReaction->setWaitFor(mOldWaitFor); + } + +}; + +class SetReactionResponseType: public QUndoCommand { +public: + + Reaction* mReaction; + Reaction::ResponseType mOldResponseType; + Reaction::ResponseType mNewResponseType; + + SetReactionResponseType(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set reaction response type")); + } + + virtual void redo() { + mOldResponseType = mReaction->responseType(); + mReaction->setResponseType(mNewResponseType); + } + + virtual void undo() { + mReaction->setResponseType(mOldResponseType); + } + +}; + +class SetReactionNextStepId: public QUndoCommand { +public: + + Reaction* mReaction; + QString mOldNextStepId; + QString mNewNextStepId; + + SetReactionNextStepId(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set reaction next step id")); + } + + virtual void redo() { + mOldNextStepId = mReaction->nextStepId(); + mReaction->setNextStepId(mNewNextStepId); + } + + virtual void undo() { + mReaction->setNextStepId(mOldNextStepId); + } + +}; + +class SetReactionCustomCode: public QUndoCommand { +public: + + Reaction* mReaction; + QString mOldCustomCode; + QString mNewCustomCode; + + SetReactionCustomCode(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set reaction custom code")); + } + + virtual void redo() { + mOldCustomCode = mReaction->customCode(); + mReaction->setCustomCode(mNewCustomCode); + } + + virtual void undo() { + mReaction->setCustomCode(mOldCustomCode); + } + +}; + +//public: + +ReactionCommands::ReactionCommands(Reaction* reaction): + mReaction(reaction) { +} + +QUndoCommand* ReactionCommands::setTriggerType( + Reaction::TriggerType triggerType, + QUndoCommand* parent) { + SetReactionTriggerType* command = new SetReactionTriggerType(parent); + command->mReaction = mReaction; + command->mNewTriggerType = triggerType; + return command; +} + +QUndoCommand* ReactionCommands::setOptionName(const QString& optionName, + QUndoCommand* parent) { + SetReactionOptionName* command = new SetReactionOptionName(parent); + command->mReaction = mReaction; + command->mNewOptionName = optionName; + return command; +} + +QUndoCommand* ReactionCommands::setWaitFor(WaitFor* waitFor, + QUndoCommand* parent) { + SetReactionWaitFor* command = new SetReactionWaitFor(parent); + command->mReaction = mReaction; + command->mNewWaitFor = waitFor; + return command; +} + +QUndoCommand* ReactionCommands::setResponseType( + Reaction::ResponseType responseType, + QUndoCommand* parent) { + SetReactionResponseType* command = new SetReactionResponseType(parent); + command->mReaction = mReaction; + command->mNewResponseType = responseType; + return command; +} + +QUndoCommand* ReactionCommands::setNextStepId(const QString& nextStepId, + QUndoCommand* parent) { + SetReactionNextStepId* command = new SetReactionNextStepId(parent); + command->mReaction = mReaction; + command->mNewNextStepId = nextStepId; + return command; +} + +QUndoCommand* ReactionCommands::setCustomCode(const QString& customCode, + QUndoCommand* parent) { + SetReactionCustomCode* command = new SetReactionCustomCode(parent); + command->mReaction = mReaction; + command->mNewCustomCode = customCode; + return command; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.h 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef REACTIONCOMMANDS_H +#define REACTIONCOMMANDS_H + +#include <QString> + +#include "../data/Reaction.h" + +class QUndoCommand; +class WaitFor; + +/** + * Factory for reaction edition commands. + * This class provides methods to create undoable commands to edit a reaction. + * A different command is provided for each data modification method in the + * Reaction class. + * + * Note that each method just creates and returns the command. It does not + * execute it before returning. + * + * @see QUndoCommand + */ +class ReactionCommands { +public: + + /** + * Creates a new ReactionCommands for the given reaction. + * + * @param reaction The reaction to create the commands for. + */ + explicit ReactionCommands(Reaction* reaction); + + /** + * Creates a new undoable command to set the trigger type. + * + * @param triggerType The trigger type of the reaction to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setTriggerType(Reaction::TriggerType triggerType, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the option name. + * + * @param optionName The option name of the reaction to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setOptionName(const QString& optionName, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the condition to wait for. + * + * @param waitFor The condition to wait for of the reaction to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setWaitFor(WaitFor* waitFor, QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the response type. + * + * @param responseType The response type of the reaction to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setResponseType(Reaction::ResponseType responseType, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the next step id. + * + * @param nextStepId The next step id of the reaction to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setNextStepId(const QString& nextStepId, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the custom response code. + * + * @param customCode The custom response code of the reaction to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setCustomCode(const QString& customCode, + QUndoCommand* parent = 0); + +private: + + /** + * The reaction to create the commands for. + */ + Reaction* mReaction; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/ReactionCommands.h ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,227 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "StepCommands.h" + +#include <QUndoCommand> + +#include <KLocalizedString> + +#include "../data/Reaction.h" +#include "../data/Step.h" + +class SetStepId: public QUndoCommand { +public: + + Step* mStep; + QString mOldId; + QString mNewId; + + SetStepId(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set step id")); + } + + virtual void redo() { + mOldId = mStep->id(); + mStep->setId(mNewId); + } + + virtual void undo() { + mStep->setId(mOldId); + } + +}; + +class SetStepText: public QUndoCommand { +public: + + Step* mStep; + QString mOldText; + QString mNewText; + + SetStepText(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set step text")); + } + + virtual void redo() { + mOldText = mStep->text(); + mStep->setText(mNewText); + } + + virtual void undo() { + mStep->setText(mOldText); + } + +}; + +class SetStepCustomSetupCode: public QUndoCommand { +public: + + Step* mStep; + QString mOldCustomSetupCode; + QString mNewCustomSetupCode; + + SetStepCustomSetupCode(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set step setup code")); + } + + virtual void redo() { + mOldCustomSetupCode = mStep->customSetupCode(); + mStep->setCustomSetupCode(mNewCustomSetupCode); + } + + virtual void undo() { + mStep->setCustomSetupCode(mOldCustomSetupCode); + } + +}; + +class SetStepCustomTearDownCode: public QUndoCommand { +public: + + Step* mStep; + QString mOldCustomTearDownCode; + QString mNewCustomTearDownCode; + + SetStepCustomTearDownCode(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set step tear down code")); + } + + virtual void redo() { + mOldCustomTearDownCode = mStep->customTearDownCode(); + mStep->setCustomTearDownCode(mNewCustomTearDownCode); + } + + virtual void undo() { + mStep->setCustomTearDownCode(mOldCustomTearDownCode); + } + +}; + +class BaseReactionCommand: public QUndoCommand { +public: + + Step* mStep; + Reaction* mReaction; + bool mDeleteReactionInDestructor; + + BaseReactionCommand(QUndoCommand* parent = 0): QUndoCommand(parent), + mStep(0), + mReaction(0), + mDeleteReactionInDestructor(false) { + } + + virtual ~BaseReactionCommand() { + if (mDeleteReactionInDestructor) { + delete mReaction; + } + } + +}; + +class AddReaction: public BaseReactionCommand { +public: + + AddReaction(QUndoCommand* parent = 0): BaseReactionCommand(parent) { + setText(i18nc("@action", "Add reaction")); + mDeleteReactionInDestructor = true; + } + + virtual void redo() { + mDeleteReactionInDestructor = false; + mStep->addReaction(mReaction); + } + + virtual void undo() { + mDeleteReactionInDestructor = true; + mStep->removeReaction(mReaction); + } + +}; + +class RemoveReaction: public BaseReactionCommand { +public: + + RemoveReaction(QUndoCommand* parent = 0): BaseReactionCommand(parent) { + setText(i18nc("@action", "Remove reaction")); + mDeleteReactionInDestructor = false; + } + + virtual void redo() { + mDeleteReactionInDestructor = true; + mStep->removeReaction(mReaction); + } + + virtual void undo() { + mDeleteReactionInDestructor = false; + mStep->addReaction(mReaction); + } + +}; + +//public: + +StepCommands::StepCommands(Step* step): + mStep(step) { +} + +QUndoCommand* StepCommands::setId(const QString& id, QUndoCommand* parent) { + SetStepId* command = new SetStepId(parent); + command->mStep = mStep; + command->mNewId = id; + return command; +} + +QUndoCommand* StepCommands::setText(const QString& text, QUndoCommand* parent) { + SetStepText* command = new SetStepText(parent); + command->mStep = mStep; + command->mNewText = text; + return command; +} + +QUndoCommand* StepCommands::setCustomSetupCode(const QString& code, + QUndoCommand* parent) { + SetStepCustomSetupCode* command = new SetStepCustomSetupCode(parent); + command->mStep = mStep; + command->mNewCustomSetupCode = code; + return command; +} + +QUndoCommand* StepCommands::setCustomTearDownCode(const QString& code, + QUndoCommand* parent) { + SetStepCustomTearDownCode* command = new SetStepCustomTearDownCode(parent); + command->mStep = mStep; + command->mNewCustomTearDownCode = code; + return command; +} + +QUndoCommand* StepCommands::addReaction(Reaction* reaction, + QUndoCommand* parent) { + AddReaction* command = new AddReaction(parent); + command->mStep = mStep; + command->mReaction = reaction; + return command; +} + +QUndoCommand* StepCommands::removeReaction(Reaction* reaction, + QUndoCommand* parent) { + RemoveReaction* command = new RemoveReaction(parent); + command->mStep = mStep; + command->mReaction = reaction; + return command; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef STEPCOMMANDS_H +#define STEPCOMMANDS_H + +#include <QString> + +class QUndoCommand; +class Reaction; +class Step; + +/** + * Factory for step edition commands. + * This class provides methods to create undoable commands to edit a step. + * A different command is provided for each data modification method in the Step + * class. + * + * Note that each method just creates and returns the command. It does not + * execute it before returning. + * + * @see QUndoCommand + */ +class StepCommands { +public: + + /** + * Creates a new StepCommands for the given step. + * + * @param step The step to create the commands for. + */ + explicit StepCommands(Step* step); + + /** + * Creates a new undoable command to set the step id. + * + * @param id The id of the step to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setId(const QString& id, QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the step text. + * + * @param text The text of the step to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setText(const QString& text, QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the step custom setup code. + * + * @param code The custom setup code of the step to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setCustomSetupCode(const QString& code, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the step custom tear down code. + * + * @param code The custom tear down code of the step to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setCustomTearDownCode(const QString& code, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to add the given reaction to the step. + * If the command was not executed yet, or it was undone, the reaction is + * deleted when the command is deleted. + * + * @param reaction The reaction to add to the step. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* addReaction(Reaction* reaction, QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to remove the given reaction from the + * step. + * If the command was executed and not undone, the reaction is deleted when + * the command is deleted. + * + * @param reaction The reaction to remove from the step. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* removeReaction(Reaction* reaction, QUndoCommand* parent = 0); + +private: + + /** + * The step to create the commands for. + */ + Step* mStep; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/StepCommands.h ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,260 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "TutorialCommands.h" + +#include <QUndoCommand> + +#include <KLocalizedString> + +#include "../data/Step.h" +#include "../data/Tutorial.h" + +class SetTutorialName: public QUndoCommand { +public: + + Tutorial* mTutorial; + QString mOldName; + QString mNewName; + + SetTutorialName(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set tutorial name")); + } + + virtual void redo() { + mOldName = mTutorial->name(); + mTutorial->setName(mNewName); + } + + virtual void undo() { + mTutorial->setName(mOldName); + } + +}; + +class SetTutorialDescription: public QUndoCommand { +public: + + Tutorial* mTutorial; + QString mOldDescription; + QString mNewDescription; + + SetTutorialDescription(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set tutorial description")); + } + + virtual void redo() { + mOldDescription = mTutorial->description(); + mTutorial->setDescription(mNewDescription); + } + + virtual void undo() { + mTutorial->setDescription(mOldDescription); + } + +}; + +class SetTutorialLicenseText: public QUndoCommand { +public: + + Tutorial* mTutorial; + QString mOldLicenseText; + QString mNewLicenseText; + + SetTutorialLicenseText(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set tutorial license")); + } + + virtual void redo() { + mOldLicenseText = mTutorial->licenseText(); + mTutorial->setLicenseText(mNewLicenseText); + } + + virtual void undo() { + mTutorial->setLicenseText(mOldLicenseText); + } + +}; + +class SetTutorialCustomSetupCode: public QUndoCommand { +public: + + Tutorial* mTutorial; + QString mOldCustomSetupCode; + QString mNewCustomSetupCode; + + SetTutorialCustomSetupCode(QUndoCommand* parent = 0): QUndoCommand(parent) { + setText(i18nc("@action", "Set tutorial setup code")); + } + + virtual void redo() { + mOldCustomSetupCode = mTutorial->customSetupCode(); + mTutorial->setCustomSetupCode(mNewCustomSetupCode); + } + + virtual void undo() { + mTutorial->setCustomSetupCode(mOldCustomSetupCode); + } + +}; + +class SetTutorialCustomTearDownCode: public QUndoCommand { +public: + + Tutorial* mTutorial; + QString mOldCustomTearDownCode; + QString mNewCustomTearDownCode; + + SetTutorialCustomTearDownCode(QUndoCommand* parent = 0): + QUndoCommand(parent) { + setText(i18nc("@action", "Set tutorial tear down code")); + } + + virtual void redo() { + mOldCustomTearDownCode = mTutorial->customTearDownCode(); + mTutorial->setCustomTearDownCode(mNewCustomTearDownCode); + } + + virtual void undo() { + mTutorial->setCustomTearDownCode(mOldCustomTearDownCode); + } + +}; + +class BaseStepCommand: public QUndoCommand { +public: + + Tutorial* mTutorial; + Step* mStep; + bool mDeleteStepInDestructor; + + BaseStepCommand(QUndoCommand* parent = 0): QUndoCommand(parent), + mTutorial(0), + mStep(0), + mDeleteStepInDestructor(false) { + } + + virtual ~BaseStepCommand() { + if (mDeleteStepInDestructor) { + delete mStep; + } + } + +}; + +class AddStep: public BaseStepCommand { +public: + + AddStep(QUndoCommand* parent = 0): BaseStepCommand(parent) { + setText(i18nc("@action", "Add step")); + mDeleteStepInDestructor = true; + } + + virtual void redo() { + mDeleteStepInDestructor = false; + mTutorial->addStep(mStep); + } + + virtual void undo() { + mDeleteStepInDestructor = true; + mTutorial->removeStep(mStep); + } + +}; + +class RemoveStep: public BaseStepCommand { +public: + + RemoveStep(QUndoCommand* parent = 0): BaseStepCommand(parent) { + setText(i18nc("@action", "Remove step")); + mDeleteStepInDestructor = false; + } + + virtual void redo() { + mDeleteStepInDestructor = true; + mTutorial->removeStep(mStep); + } + + virtual void undo() { + mDeleteStepInDestructor = false; + mTutorial->addStep(mStep); + } + +}; + +//public: + +TutorialCommands::TutorialCommands(Tutorial* tutorial): + mTutorial(tutorial) { +} + +QUndoCommand* TutorialCommands::setName(const QString& name, + QUndoCommand* parent) { + SetTutorialName* command = new SetTutorialName(parent); + command->mTutorial = mTutorial; + command->mNewName = name; + return command; +} + +QUndoCommand* TutorialCommands::setDescription(const QString& description, + QUndoCommand* parent) { + SetTutorialDescription* command = new SetTutorialDescription(parent); + command->mTutorial = mTutorial; + command->mNewDescription = description; + return command; +} + +QUndoCommand* TutorialCommands::setLicenseText(const QString& licenseText, + QUndoCommand* parent) { + SetTutorialLicenseText* command = new SetTutorialLicenseText(parent); + command->mTutorial = mTutorial; + command->mNewLicenseText = licenseText; + return command; +} + +QUndoCommand* TutorialCommands::setCustomSetupCode(const QString& code, + QUndoCommand* parent) { + SetTutorialCustomSetupCode* command = + new SetTutorialCustomSetupCode(parent); + command->mTutorial = mTutorial; + command->mNewCustomSetupCode = code; + return command; +} + +QUndoCommand* TutorialCommands::setCustomTearDownCode(const QString& code, + QUndoCommand* parent) { + SetTutorialCustomTearDownCode* command = + new SetTutorialCustomTearDownCode(parent); + command->mTutorial = mTutorial; + command->mNewCustomTearDownCode = code; + return command; +} + +QUndoCommand* TutorialCommands::addStep(Step* step, QUndoCommand* parent) { + AddStep* command = new AddStep(parent); + command->mTutorial = mTutorial; + command->mStep = step; + return command; +} + +QUndoCommand* TutorialCommands::removeStep(Step* step, QUndoCommand* parent) { + RemoveStep* command = new RemoveStep(parent); + command->mTutorial = mTutorial; + command->mStep = step; + return command; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,130 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TUTORIALCOMMANDS_H +#define TUTORIALCOMMANDS_H + +#include <QString> + +class QUndoCommand; +class Step; +class Tutorial; + +/** + * Factory for tutorial edition commands. + * This class provides methods to create undoable commands to edit a tutorial. + * A different command is provided for each data modification method in the + * Tutorial class. + * + * Note that each method just creates and returns the command. It does not + * execute it before returning. + * + * @see QUndoCommand + */ +class TutorialCommands { +public: + + /** + * Creates a new TutorialCommands for the given tutorial. + * + * @param tutorial The tutorial to create the commands for. + */ + explicit TutorialCommands(Tutorial* tutorial); + + /** + * Creates a new undoable command to set the tutorial name. + * + * @param name The name of the tutorial to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setName(const QString& name, QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the tutorial description. + * + * @param description The description of the tutorial to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setDescription(const QString& description, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the tutorial license text. + * + * @param licenseText The license text of the tutorial to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setLicenseText(const QString& licenseText, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the tutorial custom setup code. + * + * @param code The custom setup code of the tutorial to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setCustomSetupCode(const QString& code, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to set the tutorial custom tear down code. + * + * @param code The custom tear down code of the tutorial to set. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* setCustomTearDownCode(const QString& code, + QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to add the given step to the tutorial. + * If the command was not executed yet, or it was undone, the step is + * deleted when the command is deleted. + * + * @param step The step to add to the tutorial. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* addStep(Step* step, QUndoCommand* parent = 0); + + /** + * Creates a new undoable command to remove the given step from the + * tutorial. + * If the command was executed and not undone, the step is deleted when the + * command is deleted. + * + * @param step The step to remove from the tutorial. + * @param parent The parent QUndoCommand. + * @return The new QUndoCommand. + */ + QUndoCommand* removeStep(Step* step, QUndoCommand* parent = 0); + +private: + + /** + * The tutorial to create the commands for. + */ + Tutorial* mTutorial; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/commands/TutorialCommands.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2010-03-29 00:36:12 UTC (rev 205) @@ -1,5 +1,6 @@ set(ktutorial_editor_view_SRCS ActionListWidget.cpp + CommandWidget.cpp EditionDialog.cpp EditionWidget.cpp LicenseWidget.cpp @@ -41,4 +42,8 @@ kde4_add_library(ktutorial_editor_view ${ktutorial_editor_view_SRCS}) -target_link_libraries(ktutorial_editor_view ktutorial_editor_data ${KDE4_KDEUI_LIBS}) +target_link_libraries(ktutorial_editor_view + ktutorial_editor_commands + ktutorial_editor_data + ${KDE4_KDEUI_LIBS} +) Added: trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "CommandWidget.h" + +#include <QUndoStack> + +//public: + +CommandWidget::CommandWidget(QWidget* parent): EditionWidget(parent), + mParentUndoCommand(0), + mUndoStack(0) { +} + +void CommandWidget::saveChanges() { + QUndoCommand* parent = mParentUndoCommand; + if (!parent) { + parent = new QUndoCommand(); + } + + QList<QUndoCommand*> commands = createSaveCommands(parent); + + if (!mParentUndoCommand && commands.count() > 1) { + parent->setText(windowTitle()); + } else if (!mParentUndoCommand && commands.count() == 1) { + parent->setText(parent->child(0)->text()); + } + + if (mUndoStack && (commands.count() > 0 || mParentUndoCommand)){ + mUndoStack->push(parent); + return; + } + + if (mUndoStack) { + delete parent; + return; + } + + if (mParentUndoCommand) { + return; + } + + parent->redo(); + delete parent; +} + +void CommandWidget::setParentUndoCommand(QUndoCommand* parentUndoCommand) { + mParentUndoCommand = parentUndoCommand; +} + +void CommandWidget::setUndoStack(QUndoStack* undoStack) { + mUndoStack = undoStack; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.h 2010-03-29 00:36:12 UTC (rev 205) @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef COMMANDWIDGET_H +#define COMMANDWIDGET_H + +#include "EditionWidget.h" + +class QUndoCommand; +class QUndoStack; + +/** + * Base abstract class for command widgets. + * Command widgets are edition widgets that use undoable commands to save the + * data, for example, to set the name of a tutorial. + * + * To be done or undone by the user, the command must be added to a stack of + * commands. The stack that the commands will be added to can be set using + * setUndoStack(QUndoStack*) method. When the stack is set, the commands that + * are executed to save the data are added to the stack, which effectively + * causes them to be executed. + * + * However, the CommandWidget does not add the commands directly to the stack. + * Each command can have a parent command. When this happens, the child commands + * are done when their parent is done, and are undone when their parent is + * undone. It makes easier to compose several small commands to be executed as + * one bigger command. + * + * All the commands created in the widget have the same parent command, which is + * the one added directly to the stack. If no parent command was set, a new one + * is created automatically. If it has several children, its name will be the + * window title of the widget. If it has only one child, its name will be the + * name of its child. + * + * Note that if there is a stack, but no parent command and no child commands + * (for example, because there were no changes to save), the automatically + * created parent command is not added to the stack. However, if a parent + * command was explicitly set it is added to the stack even if no children were + * added to it. + * + * If no stack is set but there is a parent command, the commands will be added + * to the parent without executing them. + * + * If no stack and no parent are set, the commands will be executed when the + * changes are saved, but they will be deleted afterwards. + * + * Subclasses must implement createSaveCommands(QUndoCommand*) method. It has + * to return the list of the commands to execute to save the changes. + * + * @see QUndoCommand + */ +class CommandWidget: public EditionWidget { +Q_OBJECT +public: + + /** + * Creates a new CommandWidget with the given parent widget. + * + * @param parent The parent widget. + */ + CommandWidget(QWidget* parent = 0); + + /** + * Saves the changes to the object being edited. + */ + virtual void saveChanges(); + + /** + * Sets the parent command. + * + * @param parentUndoCommand The parent command. + */ + void setParentUndoCommand(QUndoCommand* parentUndoCommand); + + /** + * Sets the undo stack to add the commands to. + * + * @param undoStack The undo stack. + */ + void setUndoStack(QUndoStack* undoStack); + +protected: + + /** + * Creates the commands needed to save the changes. + * Subclasses must implement this method. + * + * @param parent The parent of all the created commands. + * @return A list with the commands. + */ + virtual QList<QUndoCommand*> createSaveCommands(QUndoCommand* parent) = 0; + +private: + + /** + * The explicitly set parent command. + */ + QUndoCommand* mParentUndoCommand; + + /** + * The undo stack to add the commands to. + */ + QUndoStack* mUndoStack; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/view/CommandWidget.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.cpp 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -19,12 +19,13 @@ #include "LicenseWidget.h" #include "ui_LicenseWidget.h" +#include "../commands/TutorialCommands.h" #include "../data/Tutorial.h" //public: LicenseWidget::LicenseWidget(Tutorial* tutorial, QWidget* parent): - EditionWidget(parent), + CommandWidget(parent), mTutorial(tutorial) { ui = new Ui::LicenseWidget(); ui->setupUi(this); @@ -36,9 +37,16 @@ delete ui; } -void LicenseWidget::saveChanges() { +//protected: + +QList<QUndoCommand*> LicenseWidget::createSaveCommands(QUndoCommand* parent) { + QList<QUndoCommand*> commands; + TutorialCommands tutorialCommands(mTutorial); + QString licenseText = ui->licenseTextEdit->toPlainText(); if (mTutorial->licenseText() != licenseText) { - mTutorial->setLicenseText(licenseText); + commands.append(tutorialCommands.setLicenseText(licenseText, parent)); } + + return commands; } Modified: trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.h 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/view/LicenseWidget.h 2010-03-29 00:36:12 UTC (rev 205) @@ -19,7 +19,7 @@ #ifndef LICENSEWIDGET_H #define LICENSEWIDGET_H -#include "EditionWidget.h" +#include "CommandWidget.h" class Tutorial; @@ -28,9 +28,9 @@ } /** - * Edition widget for the license of a tutorial. + * Command widget for the license of a tutorial. */ -class LicenseWidget: public EditionWidget { +class LicenseWidget: public CommandWidget { Q_OBJECT public: @@ -47,10 +47,15 @@ */ virtual ~LicenseWidget(); +protected: + /** - * Saves the license in the tutorial. + * Commands to save the license of the tutorial. + * + * @param parent The parent command. + * @return A list with the commands. */ - virtual void saveChanges(); + virtual QList<QUndoCommand*> createSaveCommands(QUndoCommand* parent); private: Modified: trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp 2010-03-28 07:46:36 UTC (rev 204) +++ trunk/ktutorial/ktutorial-editor/src/view/ReactionWidget.cpp 2010-03-29 00:36:12 UTC (rev 205) @@ -20,13 +20,14 @@ #include "ui_ReactionWidget.h" #include "WaitForWidget.h" +#include "../commands/ReactionCommands.h" #include "../data/Reaction.h" #include "../data/WaitFor.h" //public: ReactionWidget::ReactionWidget(Reaction* reaction, QWidget* parent): - EditionWidget(parent), + CommandWidget(parent), mReaction(reaction), mWaitForClone(0) { @@ -72,51 +73,64 @@ delete ui; } -void ReactionWidget::saveChanges() { - if (mReaction->optionName() != ui->triggerOptionLineEdit->text()) { - mReaction->setOptionName(ui->triggerOptionLineEdit->text()); +//protected: + +QList<QUndoCommand*> ReactionWidget::createSaveCommands(QUndoCommand... [truncated message content] |
From: <dan...@us...> - 2010-03-28 07:46:42
|
Revision: 204 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=204&view=rev Author: danxuliu Date: 2010-03-28 07:46:36 +0000 (Sun, 28 Mar 2010) Log Message: ----------- Fix path to runMemCheck.py Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt Modified: trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) +++ trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt 2010-03-28 07:46:36 UTC (rev 204) @@ -24,7 +24,7 @@ MACRO(MEM_TESTS) FOREACH(_testname ${ARGN}) - add_test(ktutorial-editor-unit-mem-${_testname} ${CMAKE_CURRENT_SOURCE_DIR}/runMemcheck.py ${CMAKE_CURRENT_BINARY_DIR}/${_testname}Test ${CMAKE_CURRENT_BINARY_DIR}) + add_test(ktutorial-editor-unit-mem-${_testname} ${CMAKE_CURRENT_SOURCE_DIR}/../runMemcheck.py ${CMAKE_CURRENT_BINARY_DIR}/${_testname}Test ${CMAKE_CURRENT_BINARY_DIR}) ENDFOREACH(_testname) ENDMACRO(MEM_TESTS) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-28 00:53:47
|
Revision: 203 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=203&view=rev Author: danxuliu Date: 2010-03-28 00:53:41 +0000 (Sun, 28 Mar 2010) Log Message: ----------- CMakeLists.txt cleanups Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt Modified: trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) +++ trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) @@ -2,12 +2,12 @@ # In order to work, they must be compiled using -fPIC add_definitions("-fPIC") +include_directories(${KDE4_INCLUDES}) + add_subdirectory(data) add_subdirectory(serialization) add_subdirectory(view) -include_directories(${KDE4_INCLUDES}) - set(ktutorial_editor_SRCS Exception.cpp KTutorialEditor.cpp @@ -23,7 +23,6 @@ ktutorial_editor_data ktutorial_editor_serialization ktutorial_editor_view - ${KDE4_KIO_LIBS} ) kde4_add_executable(ktutorial-editor main.cpp) Modified: trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) +++ trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) @@ -1,5 +1,3 @@ -include_directories(${KDE4_INCLUDES}) - set(ktutorial_editor_serialization_SRCS DeserializationException.cpp IOException.cpp @@ -11,4 +9,4 @@ kde4_add_library(ktutorial_editor_serialization ${ktutorial_editor_serialization_SRCS}) -target_link_libraries(ktutorial_editor_serialization ktutorial_editor ${KDE4_LIBS}) +target_link_libraries(ktutorial_editor_serialization ktutorial_editor ${KDE4_KIO_LIBS}) Modified: trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) +++ trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) @@ -1,5 +1,3 @@ -include_directories(${KDE4_INCLUDES}) - set(ktutorial_editor_view_SRCS ActionListWidget.cpp EditionDialog.cpp Modified: trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) +++ trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) @@ -5,7 +5,6 @@ # Used by kde4_add_unit_test to set the full path to test executables set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) -# include_directories(${CMAKE_CURRENT_BINARY_DIR} ${ktutorial-editor_SOURCE_DIR}/src/view ${ktutorial-editor_BINARY_DIR}/src/view ${KDE4_INCLUDES}) include_directories(${ktutorial-editor_SOURCE_DIR}/src/ ${KDE4_INCLUDES}) MACRO(UNIT_TESTS) Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) @@ -1,7 +1,7 @@ # Used by kde4_add_unit_test to set the full path to test executables set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${ktutorial-editor_SOURCE_DIR}/src/serialization ${ktutorial-editor_BINARY_DIR}/src/serialization ${KDE4_INCLUDES}) +include_directories(${ktutorial-editor_SOURCE_DIR}/src/serialization ${KDE4_INCLUDES}) MACRO(UNIT_TESTS) FOREACH(_className ${ARGN}) Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt 2010-03-28 00:53:41 UTC (rev 203) @@ -1,7 +1,7 @@ # Used by kde4_add_unit_test to set the full path to test executables set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${ktutorial-editor_SOURCE_DIR}/src/view ${ktutorial-editor_BINARY_DIR}/src/view ${KDE4_INCLUDES}) +include_directories(${ktutorial-editor_SOURCE_DIR}/src/view ${KDE4_INCLUDES}) # Since Qt 4.6.0, this definition is needed for GUI testing. # It is backwards compatible with previous Qt versions, unlike the alternative This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-28 00:50:59
|
Revision: 202 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=202&view=rev Author: danxuliu Date: 2010-03-28 00:50:53 +0000 (Sun, 28 Mar 2010) Log Message: ----------- Ooops, add files missed in commit 201 Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/data/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt Added: trunk/ktutorial/ktutorial-editor/src/data/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/data/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/data/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) @@ -0,0 +1,12 @@ +set(ktutorial_editor_data_SRCS + Reaction.cpp + Step.cpp + Tutorial.cpp + WaitFor.cpp + WaitForComposed.cpp + WaitForEvent.cpp + WaitForNot.cpp + WaitForSignal.cpp +) + +kde4_add_library(ktutorial_editor_data ${ktutorial_editor_data_SRCS}) Property changes on: trunk/ktutorial/ktutorial-editor/src/data/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt 2010-03-28 00:50:53 UTC (rev 202) @@ -0,0 +1,40 @@ +# Used by kde4_add_unit_test to set the full path to test executables +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${ktutorial-editor_SOURCE_DIR}/src/data ${KDE4_INCLUDES}) + +MACRO(UNIT_TESTS) + FOREACH(_className ${ARGN}) + set(_testName ${_className}Test) + kde4_add_unit_test(${_testName} TESTNAME ktutorial-editor-unit-${_testName} ${_testName}.cpp) + target_link_libraries(${_testName} ktutorial_editor_data ${QT_QTTEST_LIBRARY}) + ENDFOREACH(_className) +ENDMACRO(UNIT_TESTS) + +unit_tests( + Reaction + Step + Tutorial + WaitFor + WaitForComposed + WaitForEvent + WaitForNot + WaitForSignal +) + +MACRO(MEM_TESTS) + FOREACH(_testname ${ARGN}) + add_test(ktutorial-editor-unit-mem-${_testname} ${CMAKE_CURRENT_SOURCE_DIR}/runMemcheck.py ${CMAKE_CURRENT_BINARY_DIR}/${_testname}Test ${CMAKE_CURRENT_BINARY_DIR}) + ENDFOREACH(_testname) +ENDMACRO(MEM_TESTS) + +mem_tests( + Reaction + Step + Tutorial + WaitFor + WaitForComposed + WaitForEvent + WaitForNot + WaitForSignal +) Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/data/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-27 07:05:54
|
Revision: 200 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=200&view=rev Author: danxuliu Date: 2010-03-27 07:05:48 +0000 (Sat, 27 Mar 2010) Log Message: ----------- Add actions to save and load a tutorial from XML Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-27 04:25:13 UTC (rev 199) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-27 07:05:48 UTC (rev 200) @@ -63,6 +63,10 @@ setupActions(); + //Setting the url enables/disables File->Save action, so it has to be + //set after it is created + setTutorialUrl(KUrl()); + setupGUI(); } @@ -105,6 +109,24 @@ mTutorial = tutorial; } +void KTutorialEditor::setTutorialUrl(const KUrl& url) { + mTutorialUrl = url; + + if (url.isEmpty()) { + actionCollection()->action("file_save")->setEnabled(false); + + setCaption(""); + } else { + actionCollection()->action("file_save")->setEnabled(true); + + QString caption = url.prettyUrl(); + if (caption.length() > 64) { + caption = "..." + caption.right(64); + } + setCaption(caption); + } +} + void KTutorialEditor::setupDocks() { mTutorialActionDock = new QDockWidget(i18nc("@title", "Edit tutorial"), this); @@ -124,6 +146,12 @@ void KTutorialEditor::setupActions() { KStandardAction::openNew(this, SLOT(newTutorial()), actionCollection()); + KStandardAction::open(this, SLOT(openTutorial()), actionCollection()); + + KStandardAction::save(this, SLOT(saveTutorial()), actionCollection()); + + KStandardAction::saveAs(this, SLOT(saveTutorialAs()), actionCollection()); + KAction* action = new KAction(this); action->setText(i18nc("@action", "Export...")); action->setStatusTip(i18nc("@info:status", "Exports the tutorial to a " @@ -313,8 +341,84 @@ void KTutorialEditor::newTutorial() { setTutorialToBeEdited(); + setTutorialUrl(KUrl()); } +void KTutorialEditor::openTutorial() { + KUrl url = mTutorialUrl; + QPointer<KFileDialog> dialog = new KFileDialog(url, QString(), this); + + dialog->setCaption(i18nc("@title", "Open Tutorial")); + dialog->setOperationMode(KFileDialog::Opening); + dialog->setFilter(i18nc("@item:inlistbox A KFileDialog filter", + "*.xml|XML file")); + + if (dialog->exec() == QDialog::Rejected) { + return; + } + + Tutorial* tutorial; + try { + tutorial = Serialization::loadTutorial(dialog->selectedUrl()); + } catch (IOException e) { + QString text = i18nc("@label", "There was a problem when trying to " +"open the file:<nl/>%1", e.message()); + QString caption = i18nc("@title:window", "File could not be read"); + KMessageBox::error(this, text, caption); + return; + } catch (DeserializationException e) { + QString text = i18nc("@label", "There was a problem when trying to " +"load the tutorial:<nl/>%1", e.message()); + QString caption = i18nc("@title:window", "Tutorial could not be " +"loaded"); + KMessageBox::error(this, text, caption); + return; + } + + setTutorialToBeEdited(tutorial); + setTutorialUrl(dialog->selectedUrl()); +} + +void KTutorialEditor::saveTutorial() { + try { + Serialization::saveTutorial(mTutorial, mTutorialUrl); + } catch (IOException e) { + QString text = i18nc("@label", "There was a problem when trying to " +"save the tutorial:<nl/>%1", e.message()); + QString caption = i18nc("@title:window", "Tutorial could not be saved"); + KMessageBox::error(this, text, caption); + } +} + +void KTutorialEditor::saveTutorialAs() { + KUrl url = mTutorialUrl; + QPointer<KFileDialog> dialog = new KFileDialog(url, QString(), this); + + dialog->setSelection(mTutorial->id()); + dialog->setCaption(i18nc("@title", "Save Tutorial")); + dialog->setOperationMode(KFileDialog::Saving); + dialog->setConfirmOverwrite(true); + dialog->setFilter(i18nc("@item:inlistbox A KFileDialog filter", + "*.xml|XML file")); + dialog->filterWidget()->setEditable(false); + + if (dialog->exec() == QDialog::Rejected) { + return; + } + + try { + Serialization::saveTutorial(mTutorial, dialog->selectedUrl()); + } catch (IOException e) { + QString text = i18nc("@label", "There was a problem when trying to " +"save the tutorial:<nl/>%1", e.message()); + QString caption = i18nc("@title:window", "Tutorial could not be saved"); + KMessageBox::error(this, text, caption); + return; + } + + setTutorialUrl(dialog->selectedUrl()); +} + void KTutorialEditor::exportTutorial() { KUrl url; QPointer<KFileDialog> dialog = new KFileDialog(url, QString(), this); Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-27 04:25:13 UTC (rev 199) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-27 07:05:48 UTC (rev 200) @@ -20,6 +20,7 @@ #define KTUTORIALEDITOR_H #include <KXmlGuiWindow> +#include <KUrl> class EditionWidget; class QTreeView; @@ -68,6 +69,11 @@ Tutorial* mTutorial; /** + * The URL to save the tutorial to. + */ + KUrl mTutorialUrl; + + /** * The currently selected step. */ Step* mCurrentStep; @@ -89,6 +95,16 @@ void setTutorialToBeEdited(Tutorial* tutorial = 0); /** + * Sets the URL to save the tutorial to. + * An empty URL disables Save action, otherwise it is enabled. + * The caption (window title) is updated with the URL. The URL in the + * caption is shown truncated if it is too lengthy. + * + * @param url The URL to save the tutorial to. + */ + void setTutorialUrl(const KUrl& url); + + /** * Sets up the dock widgets. */ void setupDocks(); @@ -128,10 +144,31 @@ /** * Creates a new empty tutorial replacing the current one, if any. + * The tutorial URL is cleared. */ void newTutorial(); /** + * Shows a KFileDialog to select the file to open the tutorial from. + * The tutorial URL is updated. + * An error message is shown if the tutorial couldn't be opened. + */ + void openTutorial(); + + /** + * Saves the tutorial to the tutorial URL. + * An error message is shown if the tutorial couldn't be saved. + */ + void saveTutorial(); + + /** + * Shows a KFileDialog to select the file to save the tutorial to. + * The tutorial URL is updated. + * An error message is shown if the tutorial couldn't be saved. + */ + void saveTutorialAs(); + + /** * Shows a KFileDialog to select the file to save the exported tutorial in. * An error message is shown if the tutorial couldn't be saved. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-27 04:25:20
|
Revision: 199 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=199&view=rev Author: danxuliu Date: 2010-03-27 04:25:13 +0000 (Sat, 27 Mar 2010) Log Message: ----------- Add action to create a new tutorial, replacing the current one Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-26 21:03:26 UTC (rev 198) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-27 04:25:13 UTC (rev 199) @@ -48,12 +48,16 @@ //public: -KTutorialEditor::KTutorialEditor(): KXmlGuiWindow(0) { +KTutorialEditor::KTutorialEditor(): KXmlGuiWindow(0), + mTutorial(0), + mCurrentStep(0), + mCurrentReaction(0) { + mTreeView = new QTreeView(); mTreeView->setObjectName("centralTreeView"); setCentralWidget(mTreeView); - setupTutorialToBeEdited(); + setTutorialToBeEdited(); setupDocks(); @@ -64,22 +68,41 @@ //private: -void KTutorialEditor::setupTutorialToBeEdited() { - mTutorial = new Tutorial(this); +void KTutorialEditor::setTutorialToBeEdited(Tutorial* tutorial) { + if (!tutorial) { + tutorial = new Tutorial(this); + } - TutorialTreeItem* tutorialTreeItem = new TutorialTreeItem(mTutorial); + //Clear the selection model to ensure that the actions are disabled as + //needed when the selection model is replaced + if (mTreeView->selectionModel()) { + mTreeView->selectionModel()->clear(); + } + + TutorialTreeItem* tutorialTreeItem = new TutorialTreeItem(tutorial); TreeModel* model = new TreeModel(tutorialTreeItem, mTreeView); + //Neither the old model nor the old selection model are deleted by the + //QTreeView when a new model is set (which creates a new selection model), + //so it must be done explicitly + QItemSelectionModel* oldSelectionModel = mTreeView->selectionModel(); QAbstractItemModel* oldModel = mTreeView->model(); mTreeView->setModel(model); + delete oldSelectionModel; delete oldModel; + //Parent object is set to the selection model, so the manager is also + //deleted when the selection model it watches is deleted TutorialTreeSelectionManager* selectionManager = - new TutorialTreeSelectionManager(mTreeView->selectionModel(), this); + new TutorialTreeSelectionManager(mTreeView->selectionModel(), + mTreeView->selectionModel()); connect(selectionManager, SIGNAL(stepSelected(Step*)), this, SLOT(selectStep(Step*))); connect(selectionManager, SIGNAL(reactionSelected(Reaction*)), this, SLOT(selectReaction(Reaction*))); + + delete mTutorial; + mTutorial = tutorial; } void KTutorialEditor::setupDocks() { @@ -99,6 +122,8 @@ } void KTutorialEditor::setupActions() { + KStandardAction::openNew(this, SLOT(newTutorial()), actionCollection()); + KAction* action = new KAction(this); action->setText(i18nc("@action", "Export...")); action->setStatusTip(i18nc("@info:status", "Exports the tutorial to a " @@ -286,6 +311,10 @@ } } +void KTutorialEditor::newTutorial() { + setTutorialToBeEdited(); +} + void KTutorialEditor::exportTutorial() { KUrl url; QPointer<KFileDialog> dialog = new KFileDialog(url, QString(), this); Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-26 21:03:26 UTC (rev 198) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.h 2010-03-27 04:25:13 UTC (rev 199) @@ -78,11 +78,15 @@ Reaction* mCurrentReaction; /** - * Sets up the tutorial to be edited. + * Sets the tutorial to be edited. * It creates a new tutorial, prepares the tree view to represent it and * handles the selection of items. + * + * If the tutorial is null, a new empty tutorial is set. + * + * @param tutorial The tutorial to set. */ - void setupTutorialToBeEdited(); + void setTutorialToBeEdited(Tutorial* tutorial = 0); /** * Sets up the dock widgets. @@ -123,6 +127,11 @@ void selectReaction(Reaction* reaction); /** + * Creates a new empty tutorial replacing the current one, if any. + */ + void newTutorial(); + + /** * Shows a KFileDialog to select the file to save the exported tutorial in. * An error message is shown if the tutorial couldn't be saved. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-26 21:03:33
|
Revision: 198 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=198&view=rev Author: danxuliu Date: 2010-03-26 21:03:26 +0000 (Fri, 26 Mar 2010) Log Message: ----------- -Use IOExceptions instead of return values to report errors. -Create base class Exception to be inherited by all the exceptions. It is just a subclass of std::exception using QString for the messages. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/Exception.cpp trunk/ktutorial/ktutorial-editor/src/Exception.h trunk/ktutorial/ktutorial-editor/src/serialization/IOException.cpp trunk/ktutorial/ktutorial-editor/src/serialization/IOException.h trunk/ktutorial/ktutorial-editor/tests/unit/ExceptionTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/serialization/IOExceptionTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-26 21:03:26 UTC (rev 198) @@ -8,6 +8,7 @@ include_directories(${KDE4_INCLUDES}) set(ktutorial_editor_SRCS + Exception.cpp KTutorialEditor.cpp Reaction.cpp Step.cpp Added: trunk/ktutorial/ktutorial-editor/src/Exception.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/Exception.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/Exception.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "Exception.h" + +//public: + +Exception::Exception(const QString& message): std::exception(), + mMessage(message) { +} + +Exception::~Exception() throw() { +} + +const char* Exception::what() const throw() { + return mMessage.toUtf8(); +} + +QString Exception::message() const throw() { + return mMessage; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/Exception.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/Exception.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/Exception.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/Exception.h 2010-03-26 21:03:26 UTC (rev 198) @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef EXCEPTION_H +#define EXCEPTION_H + +#include <exception> +#include <QString> + +/** + * Base class for exceptions. + */ +class Exception: public std::exception { +public: + + explicit Exception(const QString& message = QString()); + virtual ~Exception() throw(); + + /** + * Returns the exception message. + * + * @return The exception message. + */ + virtual const char* what() const throw(); + + /** + * Returns the exception message. + * + * @return The exception message. + */ + QString message() const throw(); + +private: + + QString mMessage; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/Exception.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/KTutorialEditor.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -301,10 +301,12 @@ return; } - if (!Serialization::exportTutorial(mTutorial, dialog->currentFilter(), - dialog->selectedUrl())) { + try { + Serialization::exportTutorial(mTutorial, dialog->currentFilter(), + dialog->selectedUrl()); + } catch (IOException e) { QString text = i18nc("@label", "There was a problem when trying to " -"save the exported tutorial:<nl/>%1", KIO::NetAccess::lastErrorString()); +"save the exported tutorial:<nl/>%1", e.message()); QString caption = i18nc("@title:window", "Exported tutorial could not " "be saved"); KMessageBox::error(this, text, caption); Modified: trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-26 21:03:26 UTC (rev 198) @@ -2,6 +2,7 @@ set(ktutorial_editor_serialization_SRCS DeserializationException.cpp + IOException.cpp JavascriptExporter.cpp Serialization.cpp TutorialReader.cpp Modified: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -21,17 +21,8 @@ //public: DeserializationException::DeserializationException(const QString& message): - std::exception(), - mMessage(message) { + Exception(message) { } DeserializationException::~DeserializationException() throw() { } - -const char* DeserializationException::what() const throw() { - return mMessage.toUtf8(); -} - -QString DeserializationException::message() const throw() { - return mMessage; -} Modified: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h 2010-03-26 21:03:26 UTC (rev 198) @@ -19,37 +19,18 @@ #ifndef DESERIALIZATIONEXCEPTION_H #define DESERIALIZATIONEXCEPTION_H -#include <exception> -#include <QString> +#include "../Exception.h" /** * Thrown when the XML can't be deserialized (for example, when it isn't well * formed). */ -class DeserializationException: public std::exception { +class DeserializationException: public Exception { public: explicit DeserializationException(const QString& message = QString()); virtual ~DeserializationException() throw(); - /** - * Returns the exception message. - * - * @return The exception message. - */ - virtual const char* what() const throw(); - - /** - * Returns the exception message. - * - * @return The exception message. - */ - QString message() const throw(); - -private: - - QString mMessage; - }; #endif Added: trunk/ktutorial/ktutorial-editor/src/serialization/IOException.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/IOException.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/IOException.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -0,0 +1,27 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "IOException.h" + +//public: + +IOException::IOException(const QString& message): Exception(message) { +} + +IOException::~IOException() throw() { +} Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/IOException.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/serialization/IOException.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/IOException.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/IOException.h 2010-03-26 21:03:26 UTC (rev 198) @@ -0,0 +1,36 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef IOEXCEPTION_H +#define IOEXCEPTION_H + +#include "../Exception.h" + +/** + * Thrown when an input/ouput operation fails (for example, writing to an + * unwritable file, or reading from a file that does not exist). + */ +class IOException: public Exception { +public: + + explicit IOException(const QString& message = QString()); + virtual ~IOException() throw(); + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/IOException.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -30,12 +30,12 @@ //public: Tutorial* Serialization::loadTutorial(const KUrl& url) -throw (DeserializationException) { +throw (DeserializationException, IOException) { Q_ASSERT(url.isValid()); QString temporaryFileName; if (!KIO::NetAccess::download(url, temporaryFileName, 0)) { - return 0; + throw IOException(KIO::NetAccess::lastErrorString()); } QFile temporaryFile(temporaryFileName); @@ -51,12 +51,13 @@ return TutorialReader().readTutorial(data); } -bool Serialization::saveTutorial(Tutorial* tutorial, const KUrl& url) { +void Serialization::saveTutorial(Tutorial* tutorial, const KUrl& url) +throw (IOException) { Q_ASSERT(tutorial); Q_ASSERT(url.isValid()); QString serializedTutorial = TutorialWriter().writeTutorial(tutorial); - return writeFile(serializedTutorial, url); + writeFile(serializedTutorial, url); } QString Serialization::availableExporterTypes() { @@ -71,8 +72,9 @@ return types; } -bool Serialization::exportTutorial(const Tutorial* tutorial, - const QString& type, const KUrl& url) { +void Serialization::exportTutorial(const Tutorial* tutorial, + const QString& type, const KUrl& url) +throw (IOException) { Q_ASSERT(tutorial); Q_ASSERT(url.isValid()); @@ -83,7 +85,7 @@ Q_ASSERT(false); } - return writeFile(exportedCode, url); + writeFile(exportedCode, url); } //private: @@ -95,7 +97,8 @@ return types; } -bool Serialization::writeFile(const QString& data, const KUrl& url) { +void Serialization::writeFile(const QString& data, const KUrl& url) +throw (IOException) { KTemporaryFile temporaryFile; temporaryFile.open(); QTextStream out(&temporaryFile); @@ -103,5 +106,7 @@ out.flush(); temporaryFile.close(); - return KIO::NetAccess::upload(temporaryFile.fileName(), url, 0); + if (!KIO::NetAccess::upload(temporaryFile.fileName(), url, 0)) { + throw IOException(KIO::NetAccess::lastErrorString()); + } } Modified: trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h 2010-03-26 21:03:26 UTC (rev 198) @@ -22,6 +22,7 @@ #include <QStringList> #include "DeserializationException.h" +#include "IOException.h" class KUrl; class Tutorial; @@ -38,36 +39,32 @@ /** * Loads a tutorial from the file specified by the given url. * The file must be a XML file that validates against the W3C Schema in - * Tutorial.xsd. + * Tutorial.xsd. The url can be local or remote. * - * The url can be local or remote. If the file can't be saved, null is - * returned. In that case, KIO::NetAccess can be asked for the error code - * and string. - * * @param url The url to load the tutorial from. * @return The loaded tutorial. * @throw DeserializationException If there was a problem deserializing the * tutorial. + * @throw IOException If there was a problem reading the contents from the + * file. * @see TutorialReader */ static Tutorial* loadTutorial(const KUrl& url) - throw (DeserializationException); + throw (DeserializationException, IOException); /** * Saves the tutorial to the file specified by the given url. * The file will be a XML file that validates against the W3C Schema in - * Tutorial.xsd. + * Tutorial.xsd. The url can be local or remote. * - * The url can be local or remote. If the file can't be saved, false is - * returned. In that case, KIO::NetAccess can be asked for the error code - * and string. - * * @param tutorial The tutorial to save. * @param url The url to save the tutorial to. - * @return True if the exported tutorial was saved, false otherwise. + * @throw IOException If there was a problem writing the contents to the + * file. * @see TutorialWriter */ - static bool saveTutorial(Tutorial* tutorial, const KUrl& url); + static void saveTutorial(Tutorial* tutorial, const KUrl& url) + throw (IOException); /** * Returns the available exporter types. @@ -86,18 +83,16 @@ * The type must be the extension fragment of one of the types returned by * availableExporterTypes(). It is the value returned by KDialog * currentFilter() method. + * The url can be local or remote. * - * The url can be local or remote. If the file can't be saved, false is - * returned. In that case, KIO::NetAccess can be asked for the error code - * and string. - * * @param tutorial The tutorial to export. * @param type The type of the exporter to use. * @param url The url to save the script file to. - * @return True if the exported tutorial was saved, false otherwise. + * @throw IOException If there was a problem writing the contents to the + * file. */ - static bool exportTutorial(const Tutorial* tutorial, const QString& type, - const KUrl& url); + static void exportTutorial(const Tutorial* tutorial, const QString& type, + const KUrl& url) throw (IOException); private: @@ -110,14 +105,15 @@ /** * Writes the data to the file specified by the given url. - * The url can be local or remote. If the file can't be saved, false is - * returned. In that case, KIO::NetAccess can be asked for the error code - * and string. + * The url can be local or remote. * * @param data The data to write to the file. - * @return True if the data was saved, false otherwise. + * @param url The url of the file to save the data to. + * @throw IOException If there was a problem writing the contents to the + * file. */ - static bool writeFile(const QString& data, const KUrl& url); + static void writeFile(const QString& data, const KUrl& url) + throw (IOException); }; Modified: trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt 2010-03-26 21:03:26 UTC (rev 198) @@ -16,6 +16,7 @@ ENDMACRO(UNIT_TESTS) unit_tests( + Exception Reaction Step Tutorial @@ -33,6 +34,7 @@ ENDMACRO(MEM_TESTS) mem_tests( + Exception Reaction Step Tutorial Added: trunk/ktutorial/ktutorial-editor/tests/unit/ExceptionTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/ExceptionTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/ExceptionTest.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "Exception.h" + +class ExceptionTest: public QObject { +Q_OBJECT + +private slots: + + void testConstructor(); + void testConstructorEmpty(); + +}; + +void ExceptionTest::testConstructor() { + Exception exception(QString("The message")); + + QCOMPARE(exception.what(), "The message"); + QCOMPARE(exception.message(), QString("The message")); +} + +void ExceptionTest::testConstructorEmpty() { + Exception exception; + + QCOMPARE(exception.what(), ""); + QCOMPARE(exception.message(), QString("")); +} + +QTEST_MAIN(ExceptionTest) + +#include "ExceptionTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/ExceptionTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 21:03:26 UTC (rev 198) @@ -13,6 +13,7 @@ unit_tests( DeserializationException + IOException JavascriptExporter Serialization TutorialReader @@ -27,6 +28,7 @@ mem_tests( DeserializationException + IOException JavascriptExporter Serialization TutorialReader Added: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/IOExceptionTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/IOExceptionTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/IOExceptionTest.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "IOException.h" + +class IOExceptionTest: public QObject { +Q_OBJECT + +private slots: + + void testConstructor(); + void testConstructorEmpty(); + +}; + +void IOExceptionTest::testConstructor() { + IOException exception(QString("The message")); + + QCOMPARE(exception.what(), "The message"); + QCOMPARE(exception.message(), QString("The message")); +} + +void IOExceptionTest::testConstructorEmpty() { + IOException exception; + + QCOMPARE(exception.what(), ""); + QCOMPARE(exception.message(), QString("")); +} + +QTEST_MAIN(IOExceptionTest) + +#include "IOExceptionTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/IOExceptionTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp 2010-03-26 19:40:54 UTC (rev 197) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp 2010-03-26 21:03:26 UTC (rev 198) @@ -28,6 +28,17 @@ #include "../Tutorial.h" +#define EXPECT_EXCEPTION(statement, exception) \ +do {\ + try {\ + statement;\ + QFAIL("Expected " #exception " not thrown");\ + } catch (exception e) {\ + } catch (Exception e) {\ + QFAIL("Expected " #exception " not thrown");\ + }\ +} while (0) + class SerializationTest: public QObject { Q_OBJECT @@ -80,8 +91,7 @@ KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; - QVERIFY(Serialization::saveTutorial(&tutorial, url)); - + Serialization::saveTutorial(&tutorial, url); QScopedPointer<Tutorial> loadedTutorial(Serialization::loadTutorial(url)); QVERIFY(loadedTutorial); @@ -96,7 +106,7 @@ writeFile(mFile, "<tutorial name=\"The name\"></tutorial>"); QVERIFY(QFile::setPermissions(mFile->fileName(), 0)); - QVERIFY(!Serialization::loadTutorial(url)); + EXPECT_EXCEPTION(Serialization::loadTutorial(url), IOException); } void SerializationTest::testLoadNotAnXmlFile() { @@ -105,11 +115,8 @@ mFile->open(QIODevice::WriteOnly | QIODevice::Text); writeFile(mFile, "Not an XML file"); - try { - QScopedPointer<Tutorial> tutorial(Serialization::loadTutorial(url)); - QFAIL("Expected DeserializationException not thrown"); - } catch (DeserializationException e) { - } + EXPECT_EXCEPTION(Serialization::loadTutorial(url), + DeserializationException); } void SerializationTest::testLoadXmlNotWellFormed() { @@ -118,11 +125,8 @@ mFile->open(QIODevice::WriteOnly | QIODevice::Text); writeFile(mFile, "<tutorial><step></invalidEndElement></tutorial>"); - try { - QScopedPointer<Tutorial> tutorial(Serialization::loadTutorial(url)); - QFAIL("Expected DeserializationException not thrown"); - } catch (DeserializationException e) { - } + EXPECT_EXCEPTION(Serialization::loadTutorial(url), + DeserializationException); } void SerializationTest::testLoadXmlWithoutRootTutorialElement() { @@ -131,11 +135,8 @@ mFile->open(QIODevice::WriteOnly | QIODevice::Text); writeFile(mFile, "<unknownRootElement></unknownRootElement>"); - try { - QScopedPointer<Tutorial> tutorial(Serialization::loadTutorial(url)); - QFAIL("Expected DeserializationException not thrown"); - } catch (DeserializationException e) { - } + EXPECT_EXCEPTION(Serialization::loadTutorial(url), + DeserializationException); } void SerializationTest::testSaveToExistingUrl() { @@ -148,7 +149,7 @@ mFile->open(QIODevice::WriteOnly | QIODevice::Text); writeFile(mFile, "Hello world!"); - QVERIFY(Serialization::saveTutorial(&tutorial, url)); + Serialization::saveTutorial(&tutorial, url); QVERIFY(mFile->exists()); QVERIFY(mFile->open(QIODevice::ReadOnly | QIODevice::Text)); @@ -174,7 +175,7 @@ writeFile(mFile, "Hello world!"); QVERIFY(QFile::setPermissions(mFile->fileName(), 0)); - QVERIFY(!Serialization::saveTutorial(&tutorial, url)); + EXPECT_EXCEPTION(Serialization::saveTutorial(&tutorial, url), IOException); } void SerializationTest::testAvailableExporterTypes() { @@ -191,7 +192,7 @@ KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.js"; - QVERIFY(Serialization::exportTutorial(&tutorial, "*.js", url)); + Serialization::exportTutorial(&tutorial, "*.js", url); mFile = new QFile(url.toLocalFile()); QVERIFY(mFile->exists()); @@ -219,7 +220,7 @@ mFile->open(QIODevice::WriteOnly | QIODevice::Text); writeFile(mFile, "Hello world!"); - QVERIFY(Serialization::exportTutorial(&tutorial, "*.js", url)); + Serialization::exportTutorial(&tutorial, "*.js", url); QVERIFY(mFile->exists()); QVERIFY(mFile->open(QIODevice::ReadOnly | QIODevice::Text)); @@ -247,7 +248,8 @@ writeFile(mFile, "Hello world!"); QVERIFY(QFile::setPermissions(mFile->fileName(), 0)); - QVERIFY(!Serialization::exportTutorial(&tutorial, "*.js", url)); + EXPECT_EXCEPTION(Serialization::exportTutorial(&tutorial, "*.js", url), + IOException); } /////////////////////////////////// Helpers //////////////////////////////////// This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-26 19:41:02
|
Revision: 197 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=197&view=rev Author: danxuliu Date: 2010-03-26 19:40:54 +0000 (Fri, 26 Mar 2010) Log Message: ----------- Add loadTutorial and saveTutorial methods to Serialization facade. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp 2010-03-26 19:34:21 UTC (rev 196) +++ trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.cpp 2010-03-26 19:40:54 UTC (rev 197) @@ -24,9 +24,41 @@ #include <KIO/NetAccess> #include "JavascriptExporter.h" +#include "TutorialReader.h" +#include "TutorialWriter.h" //public: +Tutorial* Serialization::loadTutorial(const KUrl& url) +throw (DeserializationException) { + Q_ASSERT(url.isValid()); + + QString temporaryFileName; + if (!KIO::NetAccess::download(url, temporaryFileName, 0)) { + return 0; + } + + QFile temporaryFile(temporaryFileName); + temporaryFile.open(QIODevice::ReadOnly | QIODevice::Text); + + QString data; + QTextStream in(&temporaryFile); + while (!in.atEnd()) { + data += in.readAll(); + } + temporaryFile.close(); + + return TutorialReader().readTutorial(data); +} + +bool Serialization::saveTutorial(Tutorial* tutorial, const KUrl& url) { + Q_ASSERT(tutorial); + Q_ASSERT(url.isValid()); + + QString serializedTutorial = TutorialWriter().writeTutorial(tutorial); + return writeFile(serializedTutorial, url); +} + QString Serialization::availableExporterTypes() { QStringList typeList = availableExporterTypeList(); @@ -51,14 +83,7 @@ Q_ASSERT(false); } - KTemporaryFile temporaryFile; - temporaryFile.open(); - QTextStream out(&temporaryFile); - out << exportedCode; - out.flush(); - temporaryFile.close(); - - return KIO::NetAccess::upload(temporaryFile.fileName(), url, 0); + return writeFile(exportedCode, url); } //private: @@ -69,3 +94,14 @@ "*.js|Javascript file"); return types; } + +bool Serialization::writeFile(const QString& data, const KUrl& url) { + KTemporaryFile temporaryFile; + temporaryFile.open(); + QTextStream out(&temporaryFile); + out << data; + out.flush(); + temporaryFile.close(); + + return KIO::NetAccess::upload(temporaryFile.fileName(), url, 0); +} Modified: trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h 2010-03-26 19:34:21 UTC (rev 196) +++ trunk/ktutorial/ktutorial-editor/src/serialization/Serialization.h 2010-03-26 19:40:54 UTC (rev 197) @@ -21,18 +21,55 @@ #include <QStringList> +#include "DeserializationException.h" + class KUrl; class Tutorial; /** * Facade for serialization system. - * It provides the methods needed to know the available exporters and export a - * tutorial using one of them. + * It provides the methods needed to save and load a tutorial to a XML file, and + * to know the available exporters and export a tutorial to a script file using + * one of them. */ class Serialization { public: /** + * Loads a tutorial from the file specified by the given url. + * The file must be a XML file that validates against the W3C Schema in + * Tutorial.xsd. + * + * The url can be local or remote. If the file can't be saved, null is + * returned. In that case, KIO::NetAccess can be asked for the error code + * and string. + * + * @param url The url to load the tutorial from. + * @return The loaded tutorial. + * @throw DeserializationException If there was a problem deserializing the + * tutorial. + * @see TutorialReader + */ + static Tutorial* loadTutorial(const KUrl& url) + throw (DeserializationException); + + /** + * Saves the tutorial to the file specified by the given url. + * The file will be a XML file that validates against the W3C Schema in + * Tutorial.xsd. + * + * The url can be local or remote. If the file can't be saved, false is + * returned. In that case, KIO::NetAccess can be asked for the error code + * and string. + * + * @param tutorial The tutorial to save. + * @param url The url to save the tutorial to. + * @return True if the exported tutorial was saved, false otherwise. + * @see TutorialWriter + */ + static bool saveTutorial(Tutorial* tutorial, const KUrl& url); + + /** * Returns the available exporter types. * The string has the format expected by KFileDialog setFilter method, that * is, "*.fileExtension1|Human readable name1\n*.fileExtension2|Human @@ -71,6 +108,17 @@ */ static QStringList availableExporterTypeList(); + /** + * Writes the data to the file specified by the given url. + * The url can be local or remote. If the file can't be saved, false is + * returned. In that case, KIO::NetAccess can be asked for the error code + * and string. + * + * @param data The data to write to the file. + * @return True if the data was saved, false otherwise. + */ + static bool writeFile(const QString& data, const KUrl& url); + }; #endif Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp 2010-03-26 19:34:21 UTC (rev 196) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/SerializationTest.cpp 2010-03-26 19:40:54 UTC (rev 197) @@ -36,6 +36,16 @@ void init(); void cleanup(); + void testSaveAndLoad(); + + void testLoadFromUnreadableUrl(); + void testLoadNotAnXmlFile(); + void testLoadXmlNotWellFormed(); + void testLoadXmlWithoutRootTutorialElement(); + + void testSaveToExistingUrl(); + void testSaveToUnwritableUrl(); + void testAvailableExporterTypes(); void testExportJavascript(); @@ -45,7 +55,7 @@ private: - QFile* mExportedFile; + QFile* mFile; QString readFile(QFile* file); void writeFile(QFile* file, const QString& contents); @@ -53,16 +63,120 @@ }; void SerializationTest::init() { - mExportedFile = 0; + mFile = 0; } void SerializationTest::cleanup() { - if (mExportedFile) { - mExportedFile->remove(); + if (mFile) { + mFile->remove(); } - delete mExportedFile; + delete mFile; } +void SerializationTest::testSaveAndLoad() { + Tutorial tutorial; + tutorial.setName("The name"); + tutorial.setDescription("The description"); + + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; + + QVERIFY(Serialization::saveTutorial(&tutorial, url)); + + QScopedPointer<Tutorial> loadedTutorial(Serialization::loadTutorial(url)); + + QVERIFY(loadedTutorial); + QCOMPARE(loadedTutorial->name(), tutorial.name()); + QCOMPARE(loadedTutorial->description(), tutorial.description()); +} + +void SerializationTest::testLoadFromUnreadableUrl() { + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "<tutorial name=\"The name\"></tutorial>"); + QVERIFY(QFile::setPermissions(mFile->fileName(), 0)); + + QVERIFY(!Serialization::loadTutorial(url)); +} + +void SerializationTest::testLoadNotAnXmlFile() { + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.txt"; + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "Not an XML file"); + + try { + QScopedPointer<Tutorial> tutorial(Serialization::loadTutorial(url)); + QFAIL("Expected DeserializationException not thrown"); + } catch (DeserializationException e) { + } +} + +void SerializationTest::testLoadXmlNotWellFormed() { + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "<tutorial><step></invalidEndElement></tutorial>"); + + try { + QScopedPointer<Tutorial> tutorial(Serialization::loadTutorial(url)); + QFAIL("Expected DeserializationException not thrown"); + } catch (DeserializationException e) { + } +} + +void SerializationTest::testLoadXmlWithoutRootTutorialElement() { + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "<unknownRootElement></unknownRootElement>"); + + try { + QScopedPointer<Tutorial> tutorial(Serialization::loadTutorial(url)); + QFAIL("Expected DeserializationException not thrown"); + } catch (DeserializationException e) { + } +} + +void SerializationTest::testSaveToExistingUrl() { + Tutorial tutorial; + tutorial.setName("The name"); + tutorial.setDescription("The description"); + + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "Hello world!"); + + QVERIFY(Serialization::saveTutorial(&tutorial, url)); + + QVERIFY(mFile->exists()); + QVERIFY(mFile->open(QIODevice::ReadOnly | QIODevice::Text)); + + QString actualContents = readFile(mFile); + QString expectedContents = +"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +"<tutorial name=\"The name\">\n" +" <description>The description</description>\n" +"</tutorial>\n"; + + QCOMPARE(actualContents, expectedContents); +} + +void SerializationTest::testSaveToUnwritableUrl() { + Tutorial tutorial; + tutorial.setName("The name"); + tutorial.setDescription("The description"); + + KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.xml"; + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "Hello world!"); + QVERIFY(QFile::setPermissions(mFile->fileName(), 0)); + + QVERIFY(!Serialization::saveTutorial(&tutorial, url)); +} + void SerializationTest::testAvailableExporterTypes() { QString types = Serialization::availableExporterTypes(); @@ -79,11 +193,11 @@ QVERIFY(Serialization::exportTutorial(&tutorial, "*.js", url)); - mExportedFile = new QFile(url.toLocalFile()); - QVERIFY(mExportedFile->exists()); - QVERIFY(mExportedFile->open(QIODevice::ReadOnly | QIODevice::Text)); + mFile = new QFile(url.toLocalFile()); + QVERIFY(mFile->exists()); + QVERIFY(mFile->open(QIODevice::ReadOnly | QIODevice::Text)); - QString actualContents = readFile(mExportedFile); + QString actualContents = readFile(mFile); QString expectedContents = "t = Kross.module(\"kdetranslation\");\n" "\n" @@ -101,16 +215,16 @@ tutorial.setDescription("The description"); KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.js"; - mExportedFile = new QFile(url.toLocalFile()); - mExportedFile->open(QIODevice::WriteOnly | QIODevice::Text); - writeFile(mExportedFile, "Hello world!"); + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "Hello world!"); QVERIFY(Serialization::exportTutorial(&tutorial, "*.js", url)); - QVERIFY(mExportedFile->exists()); - QVERIFY(mExportedFile->open(QIODevice::ReadOnly | QIODevice::Text)); + QVERIFY(mFile->exists()); + QVERIFY(mFile->open(QIODevice::ReadOnly | QIODevice::Text)); - QString actualContents = readFile(mExportedFile); + QString actualContents = readFile(mFile); QString expectedContents = "t = Kross.module(\"kdetranslation\");\n" "\n" @@ -128,10 +242,10 @@ tutorial.setDescription("The description"); KUrl url = KGlobal::dirs()->saveLocation("tmp") + "/SerializationTest.js"; - mExportedFile = new QFile(url.toLocalFile()); - mExportedFile->open(QIODevice::WriteOnly | QIODevice::Text); - writeFile(mExportedFile, "Hello world!"); - QVERIFY(QFile::setPermissions(mExportedFile->fileName(), 0)); + mFile = new QFile(url.toLocalFile()); + mFile->open(QIODevice::WriteOnly | QIODevice::Text); + writeFile(mFile, "Hello world!"); + QVERIFY(QFile::setPermissions(mFile->fileName(), 0)); QVERIFY(!Serialization::exportTutorial(&tutorial, "*.js", url)); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-26 19:34:28
|
Revision: 196 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=196&view=rev Author: danxuliu Date: 2010-03-26 19:34:21 +0000 (Fri, 26 Mar 2010) Log Message: ----------- Fix message of DeserializationException thrown by TutorialReader Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp 2010-03-26 08:49:10 UTC (rev 195) +++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp 2010-03-26 19:34:21 UTC (rev 196) @@ -31,3 +31,7 @@ const char* DeserializationException::what() const throw() { return mMessage.toUtf8(); } + +QString DeserializationException::message() const throw() { + return mMessage; +} Modified: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h 2010-03-26 08:49:10 UTC (rev 195) +++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h 2010-03-26 19:34:21 UTC (rev 196) @@ -39,6 +39,13 @@ */ virtual const char* what() const throw(); + /** + * Returns the exception message. + * + * @return The exception message. + */ + QString message() const throw(); + private: QString mMessage; Modified: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp 2010-03-26 08:49:10 UTC (rev 195) +++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp 2010-03-26 19:34:21 UTC (rev 196) @@ -20,6 +20,8 @@ #include <QDomDocument> +#include <KLocalizedString> + #include "../Reaction.h" #include "../Step.h" #include "../Tutorial.h" @@ -41,11 +43,17 @@ int errorLine; int errorColumn; - if (!document.setContent(data, &errorMessage, &errorLine, &errorColumn) || - document.documentElement().tagName() != "tutorial") { - throw DeserializationException(errorMessage); + if (!document.setContent(data, &errorMessage, &errorLine, &errorColumn)) { + throw DeserializationException(i18n("XML document is not well formed: " +"%1, line %2, column %3", errorMessage, errorLine, errorColumn)); } + if (document.documentElement().tagName() != "tutorial") { + throw DeserializationException(i18n("Unknown root element, " +"<emphasis>tutorial</emphasis> expected, got: %1", +document.documentElement().tagName())); + } + return readTutorial(document.documentElement()); } Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp 2010-03-26 08:49:10 UTC (rev 195) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp 2010-03-26 19:34:21 UTC (rev 196) @@ -34,12 +34,14 @@ DeserializationException exception(QString("The message")); QCOMPARE(exception.what(), "The message"); + QCOMPARE(exception.message(), QString("The message")); } void DeserializationExceptionTest::testConstructorEmpty() { DeserializationException exception; QCOMPARE(exception.what(), ""); + QCOMPARE(exception.message(), QString("")); } QTEST_MAIN(DeserializationExceptionTest) Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp 2010-03-26 08:49:10 UTC (rev 195) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp 2010-03-26 19:34:21 UTC (rev 196) @@ -20,6 +20,8 @@ #include "TutorialReader.h" +#include <KLocalizedString> + #include "../Reaction.h" #include "../Step.h" #include "../Tutorial.h" @@ -515,6 +517,7 @@ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); QFAIL("Expected DeserializationException not thrown"); } catch (DeserializationException e) { + QVERIFY(e.message().contains(i18n("XML document is not well formed"))); } } @@ -529,6 +532,7 @@ QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); QFAIL("Expected DeserializationException not thrown"); } catch (DeserializationException e) { + QVERIFY(e.message().contains(i18n("Unknown root element"))); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-26 08:49:20
|
Revision: 195 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=195&view=rev Author: danxuliu Date: 2010-03-26 08:49:10 +0000 (Fri, 26 Mar 2010) Log Message: ----------- -Add TutorialReader class to deserialize a Tutorial in XML. -Enable exceptions. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp Modified: trunk/ktutorial/ktutorial-editor/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194) +++ trunk/ktutorial/ktutorial-editor/CMakeLists.txt 2010-03-26 08:49:10 UTC (rev 195) @@ -3,6 +3,7 @@ find_package(KDE4 REQUIRED) include(KDE4Defaults) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") add_subdirectory(doc) add_subdirectory(po) Modified: trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194) +++ trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-26 08:49:10 UTC (rev 195) @@ -1,8 +1,10 @@ include_directories(${KDE4_INCLUDES}) set(ktutorial_editor_serialization_SRCS + DeserializationException.cpp JavascriptExporter.cpp Serialization.cpp + TutorialReader.cpp TutorialWriter.cpp ) Added: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp 2010-03-26 08:49:10 UTC (rev 195) @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "DeserializationException.h" + +//public: + +DeserializationException::DeserializationException(const QString& message): + std::exception(), + mMessage(message) { +} + +DeserializationException::~DeserializationException() throw() { +} + +const char* DeserializationException::what() const throw() { + return mMessage.toUtf8(); +} Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h 2010-03-26 08:49:10 UTC (rev 195) @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef DESERIALIZATIONEXCEPTION_H +#define DESERIALIZATIONEXCEPTION_H + +#include <exception> +#include <QString> + +/** + * Thrown when the XML can't be deserialized (for example, when it isn't well + * formed). + */ +class DeserializationException: public std::exception { +public: + + explicit DeserializationException(const QString& message = QString()); + virtual ~DeserializationException() throw(); + + /** + * Returns the exception message. + * + * @return The exception message. + */ + virtual const char* what() const throw(); + +private: + + QString mMessage; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/DeserializationException.h ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp 2010-03-26 08:49:10 UTC (rev 195) @@ -0,0 +1,242 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "TutorialReader.h" + +#include <QDomDocument> + +#include "../Reaction.h" +#include "../Step.h" +#include "../Tutorial.h" +#include "../WaitForComposed.h" +#include "../WaitForEvent.h" +#include "../WaitForNot.h" +#include "../WaitForSignal.h" + +//public: + +TutorialReader::TutorialReader() { +} + +Tutorial* TutorialReader::readTutorial(const QString& data) +throw (DeserializationException) { + QDomDocument document; + + QString errorMessage; + int errorLine; + int errorColumn; + + if (!document.setContent(data, &errorMessage, &errorLine, &errorColumn) || + document.documentElement().tagName() != "tutorial") { + throw DeserializationException(errorMessage); + } + + return readTutorial(document.documentElement()); +} + +//private: + +Tutorial* TutorialReader::readTutorial(const QDomElement& element) { + Tutorial* tutorial = new Tutorial(); + + if (element.hasAttribute("name")) { + tutorial->setName(element.attribute("name")); + } + + QDomElement childElement = element.firstChildElement(); + while (!childElement.isNull()) { + if (childElement.tagName() == "description") { + tutorial->setDescription(childElement.text()); + } else if (childElement.tagName() == "license") { + tutorial->setLicenseText(childElement.text()); + } else if (childElement.tagName() == "setup") { + tutorial->setCustomSetupCode(childElement.text()); + } else if (childElement.tagName() == "tearDown") { + tutorial->setCustomTearDownCode(childElement.text()); + } else if (childElement.tagName() == "step") { + tutorial->addStep(readStep(childElement)); + } + + childElement = childElement.nextSiblingElement(); + } + + return tutorial; +} + +Step* TutorialReader::readStep(const QDomElement& element) { + Step* step = new Step; + + if (element.hasAttribute("id")) { + step->setId(element.attribute("id")); + } + + QDomElement childElement = element.firstChildElement(); + while (!childElement.isNull()) { + if (childElement.tagName() == "text") { + step->setText(childElement.text()); + } else if (childElement.tagName() == "setup") { + step->setCustomSetupCode(childElement.text()); + } else if (childElement.tagName() == "tearDown") { + step->setCustomTearDownCode(childElement.text()); + } else if (childElement.tagName() == "reaction") { + step->addReaction(readReaction(childElement)); + } + + childElement = childElement.nextSiblingElement(); + } + + return step; +} + +Reaction* TutorialReader::readReaction(const QDomElement& element) { + Reaction* reaction = new Reaction(); + + if (element.hasAttribute("triggerType")) { + Reaction::TriggerType triggerType = Reaction::OptionSelected; + if (element.attribute("triggerType") == "ConditionMet") { + triggerType = Reaction::ConditionMet; + } + + reaction->setTriggerType(triggerType); + } + + if (element.hasAttribute("responseType")) { + Reaction::ResponseType responseType = Reaction::NextStep; + if (element.attribute("responseType") == "CustomCode") { + responseType = Reaction::CustomCode; + } + + reaction->setResponseType(responseType); + } + + QDomElement childElement = element.firstChildElement(); + while (!childElement.isNull()) { + if (childElement.tagName() == "option") { + if (childElement.hasAttribute("name")) { + reaction->setOptionName(childElement.attribute("name")); + } + } else if (isWaitForElement(childElement)) { + reaction->setWaitFor(readWaitFor(childElement)); + } else if (childElement.tagName() == "customCode") { + reaction->setCustomCode(childElement.text()); + } else if (childElement.tagName() == "nextStep") { + if (childElement.hasAttribute("id")) { + reaction->setNextStepId(childElement.attribute("id")); + } + } + + childElement = childElement.nextSiblingElement(); + } + + return reaction; +} + +WaitFor* TutorialReader::readWaitFor(const QDomElement& element) { + if (element.tagName() == "waitForComposed") { + return readWaitForComposed(element); + } + if (element.tagName() == "waitForEvent") { + return readWaitForEvent(element); + } + if (element.tagName() == "waitForNot") { + return readWaitForNot(element); + } + if (element.tagName() == "waitForSignal") { + return readWaitForSignal(element); + } + + Q_ASSERT(false); + return 0; +} + +WaitFor* TutorialReader::readWaitForComposed(const QDomElement& element) { + WaitForComposed* waitForComposed = new WaitForComposed(); + + if (element.hasAttribute("compositionType")) { + WaitForComposed::CompositionType compositionType = WaitForComposed::And; + if (element.attribute("compositionType") == "Or") { + compositionType = WaitForComposed::Or; + } + + waitForComposed->setCompositionType(compositionType); + } + + QDomElement childElement = element.firstChildElement(); + while (!childElement.isNull()) { + if (isWaitForElement(childElement)) { + waitForComposed->addWaitFor(readWaitFor(childElement)); + } + + childElement = childElement.nextSiblingElement(); + } + + return waitForComposed; +} + +WaitFor* TutorialReader::readWaitForEvent(const QDomElement& element) { + WaitForEvent* waitForEvent = new WaitForEvent(); + + if (element.hasAttribute("receiverName")) { + waitForEvent->setReceiverName(element.attribute("receiverName")); + } + if (element.hasAttribute("eventName")) { + waitForEvent->setEventName(element.attribute("eventName")); + } + + return waitForEvent; +} + +WaitFor* TutorialReader::readWaitForNot(const QDomElement& element) { + WaitForNot* waitForNot = new WaitForNot(); + + QDomElement childElement = element.firstChildElement(); + while (!childElement.isNull()) { + if (isWaitForElement(childElement)) { + delete waitForNot->negatedWaitFor(); + waitForNot->setNegatedWaitFor(readWaitFor(childElement)); + } + + childElement = childElement.nextSiblingElement(); + } + + return waitForNot; +} + +WaitFor* TutorialReader::readWaitForSignal(const QDomElement& element) { + WaitForSignal* waitForSignal = new WaitForSignal(); + + if (element.hasAttribute("emitterName")) { + waitForSignal->setEmitterName(element.attribute("emitterName")); + } + if (element.hasAttribute("signalName")) { + waitForSignal->setSignalName(element.attribute("signalName")); + } + + return waitForSignal; +} + +bool TutorialReader::isWaitForElement(const QDomElement& element) { + if (element.tagName() != "waitForComposed" && + element.tagName() != "waitForEvent" && + element.tagName() != "waitForNot" && + element.tagName() != "waitForSignal") { + return false; + } + + return true; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h 2010-03-26 08:49:10 UTC (rev 195) @@ -0,0 +1,147 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TUTORIALREADER_H +#define TUTORIALREADER_H + +#include <QXmlStreamWriter> + +#include "DeserializationException.h" + +class QDomElement; +class Reaction; +class Step; +class Tutorial; +class WaitFor; +class WaitForComposed; +class WaitForEvent; +class WaitForNot; +class WaitForSignal; + +/** + * Deserializer for tutorials stored in XML. + * Creates a new Tutorial from the XML data generated by TutorialWriter. Anyway, + * if the XML data is not valid (see Tutorial.xsd for the W3C Schema), it + * ignores unknown attributes and elements, and uses those known to create the + * tutorial. + * + * @see TutorialWriter + */ +class TutorialReader { +public: + + /** + * Creates a new TutorialReader. + */ + TutorialReader(); + + /** + * Returns the Tutorial stored in the given XML serialization. + * The tutorial must be deleted explicitly. + * + * If the XML is not well formed or its root element is not a "tutorial" + * element, a DeserializationException is thrown. In any other case, even if + * the XML is not valid, the deserializer tries to do its best: it ignores + * unknown attributes and elements and deserializes all the attributes and + * elements it knows. + * + * @param data The XML serialization. + * @return The Tutorial stored in the given XML serialization. + * @throw DeserializationException If there was a problem deserializing the + * tutorial. + */ + Tutorial* readTutorial(const QString& data) + throw (DeserializationException); + +private: + + /** + * Reads a new Tutorial from the "tutorial" XML element. + * + * @param element The element to read the Tutorial from. + * @return The new Tutorial. + */ + Tutorial* readTutorial(const QDomElement& element); + + /** + * Reads a new Step from the "step" XML element. + * + * @param element The element to read the Step from. + * @return The new Step. + */ + Step* readStep(const QDomElement& element); + + /** + * Reads a new Reaction from the "reaction" XML element. + * + * @param element The element to read the Reaction from. + * @return The new Reaction. + */ + Reaction* readReaction(const QDomElement& element); + + /** + * Returns a new WaitFor object from the appropriate subclass. + * + * @param element The element to read the WaitFor from. + * @return The new WaitFor. + */ + WaitFor* readWaitFor(const QDomElement& element); + + /** + * Reads a new WaitForComposed from the "waitForComposed" XML element. + * + * @param element The element to read the WaitForComposed from. + * @return The new WaitForComposed. + */ + WaitFor* readWaitForComposed(const QDomElement& element); + + /** + * Reads a new WaitForEvent from the "waitForEvent" XML element. + * + * @param element The element to read the WaitForEvent from. + * @return The new WaitForEvent. + */ + WaitFor* readWaitForEvent(const QDomElement& element); + + /** + * Reads a new WaitForNot from the "waitForNot" XML element. + * + * @param element The element to read the WaitForNot from. + * @return The new WaitForNot. + */ + WaitFor* readWaitForNot(const QDomElement& element); + + /** + * Reads a new WaitForSignal from the "waitForSignal" XML element. + * + * @param element The element to read the WaitForSignal from. + * @return The new WaitForSignal. + */ + WaitFor* readWaitForSignal(const QDomElement& element); + + /** + * Returns whether the given element is one of the WaitFor elements or not. + * + * @param element The element to check. + * @return Whether the given element is one of the WaitFor elements or not. + */ + bool isWaitForElement(const QDomElement& element); + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialReader.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 08:49:10 UTC (rev 195) @@ -12,6 +12,7 @@ ENDMACRO(UNIT_TESTS) unit_tests( + DeserializationException JavascriptExporter Serialization TutorialReader @@ -25,6 +26,7 @@ ENDMACRO(MEM_TESTS) mem_tests( + DeserializationException JavascriptExporter Serialization TutorialReader Added: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp 2010-03-26 08:49:10 UTC (rev 195) @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "DeserializationException.h" + +class DeserializationExceptionTest: public QObject { +Q_OBJECT + +private slots: + + void testConstructor(); + void testConstructorEmpty(); + +}; + +void DeserializationExceptionTest::testConstructor() { + DeserializationException exception(QString("The message")); + + QCOMPARE(exception.what(), "The message"); +} + +void DeserializationExceptionTest::testConstructorEmpty() { + DeserializationException exception; + + QCOMPARE(exception.what(), ""); +} + +QTEST_MAIN(DeserializationExceptionTest) + +#include "DeserializationExceptionTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/DeserializationExceptionTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp 2010-03-26 08:49:10 UTC (rev 195) @@ -0,0 +1,658 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "TutorialReader.h" + +#include "../Reaction.h" +#include "../Step.h" +#include "../Tutorial.h" +#include "../WaitForComposed.h" +#include "../WaitForEvent.h" +#include "../WaitForNot.h" +#include "../WaitForSignal.h" + +#define HEADER_XML \ + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + +#define TUTORIAL_ELEMENTS \ +" <description>The description,\nwith < and >\n</description>\n" \ +" <license>The license text,\nwith < and >\n</license>\n" \ +" <setup>The setup code,\nwith < and >\n</setup>\n" \ +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" + +#define STEP_PARENT_START \ +HEADER_XML \ +"<tutorial>\n" + +#define STEP_PARENT_END \ +"</tutorial>\n" + +#define STEP_ELEMENTS \ +" <text>The text,\nwith < and >\n</text>\n" \ +" <setup>The setup code,\nwith < and >\n</setup>\n" \ +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" + +#define REACTION_PARENT_START \ +STEP_PARENT_START \ +" <step>\n" + +#define REACTION_PARENT_END \ +" </step>\n" \ +STEP_PARENT_END + +#define WAITFOR_PARENT_START \ +REACTION_PARENT_START \ +" <reaction triggerType=\"ConditionMet\" responseType=\"NextStep\">\n" + +#define WAITFOR_PARENT_END \ +" </reaction>\n" \ +REACTION_PARENT_END + +class TutorialReaderTest: public QObject { +Q_OBJECT + +private slots: + + void testTutorial(); + void testTutorialEmpty(); + void testTutorialWithSeveralSteps(); + + void testStep(); + void testStepEmpty(); + void testStepWithSeveralReactions(); + + void testReactionConditionCustomCode(); + void testReactionOptionNextStep(); + void testReactionEmpty(); + + void testWaitForEvent(); + void testWaitForEventEmpty(); + void testWaitForSignal(); + void testWaitForSignalEmpty(); + void testWaitForComposed(); + void testWaitForComposedEmpty(); + void testWaitForNot(); + void testWaitForNotWithoutNegatedWaitFor(); + + void testXmlNotWellFormed(); + void testXmlWithoutRootTutorialElement(); + void testXmlWithGarbageElementsAndAttributes(); + +private: + + void assertWaitForSignal(WaitFor* waitFor, const QString& emitterName, + const QString& signalName) const; + + QString addGarbageToXmlData(const QString& data) const; + +}; + +void TutorialReaderTest::testTutorial() { + QString data = +HEADER_XML +"<tutorial name=\"The "name"\">\n" +" <description>The description,\nwith < and >\n</description>\n" +" <license>The license text,\nwith < and >\n</license>\n" +" <setup>The setup code,\nwith < and >\n</setup>\n" +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" +"</tutorial>\n"; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + + QVERIFY(tutorial); + QCOMPARE(tutorial->name(), QString("The \"name\"")); + QCOMPARE(tutorial->description(), + QString("The description,\nwith < and >\n")); + QCOMPARE(tutorial->licenseText(), + QString("The license text,\nwith < and >\n")); + QCOMPARE(tutorial->customSetupCode(), + QString("The setup code,\nwith < and >\n")); + QCOMPARE(tutorial->customTearDownCode(), + QString("The tear down code,\nwith < and >\n")); + QCOMPARE(tutorial->steps().count(), 0); +} + +void TutorialReaderTest::testTutorialEmpty() { + QString data = +HEADER_XML +"<tutorial/>\n"; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + + QVERIFY(tutorial); + QCOMPARE(tutorial->name(), QString("")); + QCOMPARE(tutorial->description(), QString("")); + QCOMPARE(tutorial->licenseText(), QString("")); + QCOMPARE(tutorial->customSetupCode(), QString("")); + QCOMPARE(tutorial->customTearDownCode(), QString("")); + QCOMPARE(tutorial->steps().count(), 0); +} + +void TutorialReaderTest::testTutorialWithSeveralSteps() { + QString data = +HEADER_XML +"<tutorial name=\"The "name"\">\n" +TUTORIAL_ELEMENTS +" <step id=\"The id1\">\n" +" <text>The text1</text>\n" +" </step>\n" +" <step id=\"The id2\">\n" +" <text>The text2</text>\n" +" </step>\n" +"</tutorial>\n"; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + + QVERIFY(tutorial); + QCOMPARE(tutorial->name(), QString("The \"name\"")); + QCOMPARE(tutorial->description(), + QString("The description,\nwith < and >\n")); + QCOMPARE(tutorial->licenseText(), + QString("The license text,\nwith < and >\n")); + QCOMPARE(tutorial->customSetupCode(), + QString("The setup code,\nwith < and >\n")); + QCOMPARE(tutorial->customTearDownCode(), + QString("The tear down code,\nwith < and >\n")); + QCOMPARE(tutorial->steps().count(), 2); + Step* step = tutorial->steps()[0]; + QVERIFY(step); + QCOMPARE(step->id(), QString("The id1")); + QCOMPARE(step->text(), QString("The text1")); + step = tutorial->steps()[1]; + QVERIFY(step); + QCOMPARE(step->id(), QString("The id2")); + QCOMPARE(step->text(), QString("The text2")); +} + +void TutorialReaderTest::testStep() { + QString data = +STEP_PARENT_START +" <step id=\"The "id"\">\n" +" <text>The text,\nwith < and >\n</text>\n" +" <setup>The setup code,\nwith < and >\n</setup>\n" +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" +" </step>\n" +STEP_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + Step* step = tutorial->steps()[0]; + + QVERIFY(step); + QCOMPARE(step->id(), QString("The \"id\"")); + QCOMPARE(step->text(), QString("The text,\nwith < and >\n")); + QCOMPARE(step->customSetupCode(), + QString("The setup code,\nwith < and >\n")); + QCOMPARE(step->customTearDownCode(), + QString("The tear down code,\nwith < and >\n")); + QCOMPARE(step->reactions().count(), 0); +} + +void TutorialReaderTest::testStepEmpty() { + QString data = +STEP_PARENT_START +" <step/>\n" +STEP_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + Step* step = tutorial->steps()[0]; + + QVERIFY(step); + QCOMPARE(step->id(), QString("")); + QCOMPARE(step->text(), QString("")); + QCOMPARE(step->customSetupCode(), QString("")); + QCOMPARE(step->customTearDownCode(), QString("")); + QCOMPARE(step->reactions().count(), 0); +} + +void TutorialReaderTest::testStepWithSeveralReactions() { + QString data = +STEP_PARENT_START +" <step id=\"The "id"\">\n" +STEP_ELEMENTS +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\"/>\n" +" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n" +" <option name=\"The option name\"/>\n" +" <nextStep id=\"Another id\"/>\n" +" </reaction>\n" +" </step>\n" +STEP_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + Step* step = tutorial->steps()[0]; + + QVERIFY(step); + QCOMPARE(step->id(), QString("The \"id\"")); + QCOMPARE(step->text(), QString("The text,\nwith < and >\n")); + QCOMPARE(step->customSetupCode(), + QString("The setup code,\nwith < and >\n")); + QCOMPARE(step->customTearDownCode(), + QString("The tear down code,\nwith < and >\n")); + QCOMPARE(step->reactions().count(), 2); + Reaction* reaction = step->reactions()[0]; + QVERIFY(reaction); + QCOMPARE(reaction->triggerType(), Reaction::ConditionMet); + QCOMPARE(reaction->responseType(), Reaction::CustomCode); + reaction = step->reactions()[1]; + QVERIFY(reaction); + QCOMPARE(reaction->triggerType(), Reaction::OptionSelected); + QCOMPARE(reaction->optionName(), QString("The option name")); + QCOMPARE(reaction->responseType(), Reaction::NextStep); + QCOMPARE(reaction->nextStepId(), QString("Another id")); +} + +void TutorialReaderTest::testReactionConditionCustomCode() { + QString data = +REACTION_PARENT_START +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\">\n" +" <option name=\"The "option" name\"/>\n" +" <waitForSignal emitterName=\"The emitter name\" \ +signalName=\"theSignalName(Argument1Type, Argument2Type)\"/>\n" +" <customCode>The custom code,\nwith < and >\n</customCode>\n" +" <nextStep id=\"Another "id"\"/>\n" +" </reaction>\n" +REACTION_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + Reaction* reaction = tutorial->steps()[0]->reactions()[0]; + + QVERIFY(reaction); + QCOMPARE(reaction->triggerType(), Reaction::ConditionMet); + QCOMPARE(reaction->optionName(), QString("The \"option\" name")); + assertWaitForSignal(reaction->waitFor(), "The emitter name", + "theSignalName(Argument1Type, Argument2Type)"); + QCOMPARE(reaction->responseType(), Reaction::CustomCode); + QCOMPARE(reaction->customCode(), + QString("The custom code,\nwith < and >\n")); + QCOMPARE(reaction->nextStepId(), QString("Another \"id\"")); +} + +void TutorialReaderTest::testReactionOptionNextStep() { + QString data = +REACTION_PARENT_START +" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n" +" <option name=\"The "option" name\"/>\n" +" <waitForSignal emitterName=\"The emitter name\" \ +signalName=\"theSignalName(Argument1Type, Argument2Type)\"/>\n" +" <customCode>The custom code,\nwith < and >\n</customCode>\n" +" <nextStep id=\"Another "id"\"/>\n" +" </reaction>\n" +REACTION_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + Reaction* reaction = tutorial->steps()[0]->reactions()[0]; + + QVERIFY(reaction); + QCOMPARE(reaction->triggerType(), Reaction::OptionSelected); + QCOMPARE(reaction->optionName(), QString("The \"option\" name")); + assertWaitForSignal(reaction->waitFor(), "The emitter name", + "theSignalName(Argument1Type, Argument2Type)"); + QCOMPARE(reaction->responseType(), Reaction::NextStep); + QCOMPARE(reaction->customCode(), + QString("The custom code,\nwith < and >\n")); + QCOMPARE(reaction->nextStepId(), QString("Another \"id\"")); +} + +void TutorialReaderTest::testReactionEmpty() { + QString data = +REACTION_PARENT_START +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\"/>\n" +REACTION_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + Reaction* reaction = tutorial->steps()[0]->reactions()[0]; + + QVERIFY(reaction); + QCOMPARE(reaction->triggerType(), Reaction::ConditionMet); + QCOMPARE(reaction->optionName(), QString("")); + QCOMPARE(reaction->waitFor(), (WaitFor*)0); + QCOMPARE(reaction->responseType(), Reaction::CustomCode); + QCOMPARE(reaction->customCode(), QString("")); + QCOMPARE(reaction->nextStepId(), QString("")); +} + +void TutorialReaderTest::testWaitForEvent() { + QString data = +WAITFOR_PARENT_START +" <waitForEvent receiverName=\"The "receiver" name\" \ +eventName=\"The"Event"Name\"/>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + WaitForEvent* waitForEvent = qobject_cast<WaitForEvent*>(waitFor); + QVERIFY(waitForEvent); + QCOMPARE(waitForEvent->receiverName(), QString("The \"receiver\" name")); + QCOMPARE(waitForEvent->eventName(), QString("The\"Event\"Name")); +} + +void TutorialReaderTest::testWaitForEventEmpty() { + QString data = +WAITFOR_PARENT_START +" <waitForEvent/>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + WaitForEvent* waitForEvent = qobject_cast<WaitForEvent*>(waitFor); + QVERIFY(waitForEvent); + QCOMPARE(waitForEvent->receiverName(), QString("")); + QCOMPARE(waitForEvent->eventName(), QString("")); +} + +void TutorialReaderTest::testWaitForSignal() { + QString data = +WAITFOR_PARENT_START +" <waitForSignal emitterName=\"The "emitter" name\" \ +signalName=\"theSignalName("Argument1Type")\"/>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + assertWaitForSignal(waitFor, "The \"emitter\" name", + "theSignalName(\"Argument1Type\")"); +} + +void TutorialReaderTest::testWaitForSignalEmpty() { + QString data = +WAITFOR_PARENT_START +" <waitForSignal/>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + assertWaitForSignal(waitFor, "", ""); +} + +void TutorialReaderTest::testWaitForComposed() { + QString data = +WAITFOR_PARENT_START +" <waitForComposed compositionType=\"And\">\n" +" <waitForSignal emitterName=\"The emitter name1\" \ +signalName=\"theSignalName1()\"/>\n" +" <waitForComposed compositionType=\"Or\">\n" +" <waitForSignal emitterName=\"The emitter name2\" \ +signalName=\"theSignalName2()\"/>\n" +" <waitForSignal emitterName=\"The emitter name3\" \ +signalName=\"theSignalName3()\"/>\n" +" </waitForComposed>\n" +" </waitForComposed>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + WaitForComposed* waitForAnd = qobject_cast<WaitForComposed*>(waitFor); + QVERIFY(waitForAnd); + QCOMPARE(waitForAnd->compositionType(), WaitForComposed::And); + QCOMPARE(waitForAnd->waitFors().count(), 2); + assertWaitForSignal(waitForAnd->waitFors()[0], "The emitter name1", + "theSignalName1()"); + + WaitForComposed* waitForOr = + qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[1]); + QVERIFY(waitForOr); + QCOMPARE(waitForOr->compositionType(), WaitForComposed::Or); + QCOMPARE(waitForOr->waitFors().count(), 2); + assertWaitForSignal(waitForOr->waitFors()[0], "The emitter name2", + "theSignalName2()"); + assertWaitForSignal(waitForOr->waitFors()[1], "The emitter name3", + "theSignalName3()"); +} + +void TutorialReaderTest::testWaitForComposedEmpty() { + QString data = +WAITFOR_PARENT_START +" <waitForComposed compositionType=\"And\">\n" +" <waitForComposed compositionType=\"And\"/>\n" +" <waitForComposed compositionType=\"Or\"/>\n" +" </waitForComposed>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + WaitForComposed* waitForAnd = qobject_cast<WaitForComposed*>(waitFor); + QVERIFY(waitForAnd); + QCOMPARE(waitForAnd->compositionType(), WaitForComposed::And); + QCOMPARE(waitForAnd->waitFors().count(), 2); + + WaitForComposed* waitForAndChild = + qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[0]); + QVERIFY(waitForAndChild); + QCOMPARE(waitForAndChild->compositionType(), WaitForComposed::And); + QCOMPARE(waitForAndChild->waitFors().count(), 0); + + WaitForComposed* waitForOrChild = + qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[1]); + QVERIFY(waitForOrChild); + QCOMPARE(waitForOrChild->compositionType(), WaitForComposed::Or); + QCOMPARE(waitForOrChild->waitFors().count(), 0); +} + +void TutorialReaderTest::testWaitForNot() { + QString data = +WAITFOR_PARENT_START +" <waitForNot>\n" +" <waitForSignal emitterName=\"The emitter name\" \ +signalName=\"theSignalName()\"/>\n" +" </waitForNot>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + WaitForNot* waitForNot = qobject_cast<WaitForNot*>(waitFor); + QVERIFY(waitForNot); + WaitForSignal* waitForSignal = + qobject_cast<WaitForSignal*>(waitForNot->negatedWaitFor()); + QVERIFY(waitForSignal); + QCOMPARE(waitForSignal->emitterName(), QString("The emitter name")); + QCOMPARE(waitForSignal->signalName(), QString("theSignalName()")); +} + +void TutorialReaderTest::testWaitForNotWithoutNegatedWaitFor() { + QString data = +WAITFOR_PARENT_START +" <waitForNot/>\n" +WAITFOR_PARENT_END; + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + WaitFor* waitFor = tutorial->steps()[0]->reactions()[0]->waitFor(); + + WaitForNot* waitForNot = qobject_cast<WaitForNot*>(waitFor); + QVERIFY(waitForNot); + QCOMPARE(waitForNot->negatedWaitFor(), (WaitFor*)0); +} + +void TutorialReaderTest::testXmlNotWellFormed() { + QString data = +HEADER_XML +"<tutorial>\n" +" <step>\n" +" </invalidEndElement>\n" +"</tutorial>\n"; + + TutorialReader reader; + try { + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + QFAIL("Expected DeserializationException not thrown"); + } catch (DeserializationException e) { + } +} + +void TutorialReaderTest::testXmlWithoutRootTutorialElement() { + QString data = +HEADER_XML +"<unknownRootElement>\n" +"</unknownRootElement>\n"; + + TutorialReader reader; + try { + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + QFAIL("Expected DeserializationException not thrown"); + } catch (DeserializationException e) { + } +} + +void TutorialReaderTest::testXmlWithGarbageElementsAndAttributes() { + QString data = +HEADER_XML +"<tutorial name=\"The "name"\">\n" +TUTORIAL_ELEMENTS +" <step id=\"The id1\">\n" +STEP_ELEMENTS +" </step>\n" +" <step id=\"The id2\">\n" +" <text>The text2</text>\n" +" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n" +" <option name=\"The "option" name\"/>\n" +" <customCode>The custom code,\nwith < and >\n</customCode>\n" +" <nextStep id=\"Another "id"\"/>\n" +" </reaction>\n" +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\">\n" +" <waitForComposed compositionType=\"And\">\n" +" <waitForSignal emitterName=\"The emitter name1\" \ +signalName=\"theSignalName1()\"/>\n" +" <waitForComposed compositionType=\"Or\">\n" +" <waitForSignal emitterName=\"The emitter name2\" \ +signalName=\"theSignalName2()\"/>\n" +" <waitForSignal emitterName=\"The emitter name3\" \ +signalName=\"theSignalName3()\"/>\n" +" </waitForComposed>\n" +" </waitForComposed>\n" +" </reaction>\n" +" </step>\n" +"</tutorial>\n"; + + data = addGarbageToXmlData(data); + + TutorialReader reader; + QScopedPointer<Tutorial> tutorial(reader.readTutorial(data)); + + QVERIFY(tutorial); + QCOMPARE(tutorial->name(), QString("The \"name\"")); + QCOMPARE(tutorial->description(), + QString("The description,\nwith < and >\n")); + QCOMPARE(tutorial->licenseText(), + QString("The license text,\nwith < and >\n")); + QCOMPARE(tutorial->customSetupCode(), + QString("The setup code,\nwith < and >\n")); + QCOMPARE(tutorial->customTearDownCode(), + QString("The tear down code,\nwith < and >\n")); + QCOMPARE(tutorial->steps().count(), 2); + + Step* step = tutorial->steps()[0]; + QVERIFY(step); + QCOMPARE(step->id(), QString("The id1")); + QCOMPARE(step->text(), QString("The text,\nwith < and >\n")); + QCOMPARE(step->customSetupCode(), + QString("The setup code,\nwith < and >\n")); + QCOMPARE(step->customTearDownCode(), + QString("The tear down code,\nwith < and >\n")); + QCOMPARE(step->reactions().count(), 0); + + step = tutorial->steps()[1]; + QVERIFY(step); + QCOMPARE(step->id(), QString("The id2")); + QCOMPARE(step->text(), QString("The text2")); + QCOMPARE(step->reactions().count(), 2); + + Reaction* reaction = step->reactions()[0]; + QCOMPARE(reaction->triggerType(), Reaction::OptionSelected); + QCOMPARE(reaction->optionName(), QString("The \"option\" name")); + QCOMPARE(reaction->waitFor(), (WaitFor*)0); + QCOMPARE(reaction->responseType(), Reaction::NextStep); + QCOMPARE(reaction->customCode(), + QString("The custom code,\nwith < and >\n")); + QCOMPARE(reaction->nextStepId(), QString("Another \"id\"")); + + reaction = step->reactions()[1]; + QCOMPARE(reaction->triggerType(), Reaction::ConditionMet); + QCOMPARE(reaction->optionName(), QString("")); + QCOMPARE(reaction->responseType(), Reaction::CustomCode); + QCOMPARE(reaction->customCode(), QString("")); + QCOMPARE(reaction->nextStepId(), QString("")); + WaitFor* waitFor = reaction->waitFor(); + + WaitForComposed* waitForAnd = qobject_cast<WaitForComposed*>(waitFor); + QVERIFY(waitForAnd); + QCOMPARE(waitForAnd->compositionType(), WaitForComposed::And); + QCOMPARE(waitForAnd->waitFors().count(), 2); + assertWaitForSignal(waitForAnd->waitFors()[0], "The emitter name1", + "theSignalName1()"); + + WaitForComposed* waitForOr = + qobject_cast<WaitForComposed*>(waitForAnd->waitFors()[1]); + QVERIFY(waitForOr); + QCOMPARE(waitForOr->compositionType(), WaitForComposed::Or); + QCOMPARE(waitForOr->waitFors().count(), 2); + assertWaitForSignal(waitForOr->waitFors()[0], "The emitter name2", + "theSignalName2()"); + assertWaitForSignal(waitForOr->waitFors()[1], "The emitter name3", + "theSignalName3()"); +} + +/////////////////////////////////// Helpers //////////////////////////////////// + +void TutorialReaderTest::assertWaitForSignal(WaitFor* waitFor, + const QString& emitterName, + const QString& signalName) const { + WaitForSignal* waitForSignal = qobject_cast<WaitForSignal*>(waitFor); + QVERIFY(waitForSignal); + QCOMPARE(waitForSignal->emitterName(), emitterName); + QCOMPARE(waitForSignal->signalName(), signalName); +} + +QString TutorialReaderTest::addGarbageToXmlData(const QString& data) const { + QString garbagedData = data; + //Add a " garbage=\"trash\"" attribute to every element + garbagedData.replace(QRegExp("(<\\w+( \\w+=\"[ &;\"\\w]*\")*)(>|/>)"), + "\\1 garbage=\"trash\"\\3"); + //Add a "<garbage/>" element after each start element (even for text + //elements) + garbagedData.replace(QRegExp("(<\\w+( \\w+=\"[ &;\"\\w]*\")*>)"), + "\\1<garbage/>"); + return garbagedData; +} + +QTEST_MAIN(TutorialReaderTest) + +#include "TutorialReaderTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialReaderTest.cpp ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-26 01:10:30
|
Revision: 194 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=194&view=rev Author: danxuliu Date: 2010-03-26 01:10:24 +0000 (Fri, 26 Mar 2010) Log Message: ----------- Files missed in commit 192 Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt Added Paths: ----------- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialWriterTest.cpp Modified: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 01:09:26 UTC (rev 193) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/CMakeLists.txt 2010-03-26 01:10:24 UTC (rev 194) @@ -14,6 +14,8 @@ unit_tests( JavascriptExporter Serialization + TutorialReader + TutorialWriter ) MACRO(MEM_TESTS) @@ -25,4 +27,6 @@ mem_tests( JavascriptExporter Serialization + TutorialReader + TutorialWriter ) Added: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialWriterTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialWriterTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialWriterTest.cpp 2010-03-26 01:10:24 UTC (rev 194) @@ -0,0 +1,590 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "TutorialWriter.h" + +#include "../Reaction.h" +#include "../Step.h" +#include "../Tutorial.h" +#include "../WaitForComposed.h" +#include "../WaitForEvent.h" +#include "../WaitForNot.h" +#include "../WaitForSignal.h" + +#define HEADER_XML \ + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + +#define TUTORIAL_ELEMENTS \ +" <description>The description,\nwith < and >\n</description>\n" \ +" <license>The license text,\nwith < and >\n</license>\n" \ +" <setup>The setup code,\nwith < and >\n</setup>\n" \ +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" + +#define STEP_PARENT_START \ +HEADER_XML \ +"<tutorial>\n" + +#define STEP_PARENT_END \ +"</tutorial>\n" + +#define STEP_ELEMENTS \ +" <text>The text,\nwith < and >\n</text>\n" \ +" <setup>The setup code,\nwith < and >\n</setup>\n" \ +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" + +#define REACTION_PARENT_START \ +STEP_PARENT_START \ +" <step>\n" + +#define REACTION_PARENT_END \ +" </step>\n" \ +STEP_PARENT_END + +#define WAITFOR_PARENT_START \ +REACTION_PARENT_START \ +" <reaction triggerType=\"ConditionMet\" responseType=\"NextStep\">\n" + +#define WAITFOR_PARENT_END \ +" </reaction>\n" \ +REACTION_PARENT_END + +class TutorialWriterTest: public QObject { +Q_OBJECT + +private slots: + + void testTutorial(); + void testTutorialEmpty(); + void testTutorialWithSeveralSteps(); + + void testStep(); + void testStepEmpty(); + void testStepWithSeveralReactions(); + + void testReactionConditionCustomCode(); + void testReactionOptionNextStep(); + void testReactionEmpty(); + + void testWaitForEvent(); + void testWaitForEventEmpty(); + void testWaitForSignal(); + void testWaitForSignalEmpty(); + void testWaitForComposed(); + void testWaitForComposedEmpty(); + void testWaitForNot(); + void testWaitForNotWithoutNegatedWaitFor(); + +}; + +void TutorialWriterTest::testTutorial() { + Tutorial tutorial; + tutorial.setName("The \"name\""); + tutorial.setDescription("The description,\nwith < and >\n"); + tutorial.setLicenseText("The license text,\nwith < and >\n"); + tutorial.setCustomSetupCode("The setup code,\nwith < and >\n"); + tutorial.setCustomTearDownCode("The tear down code,\nwith < and >\n"); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +HEADER_XML +"<tutorial name=\"The "name"\">\n" +" <description>The description,\nwith < and >\n</description>\n" +" <license>The license text,\nwith < and >\n</license>\n" +" <setup>The setup code,\nwith < and >\n</setup>\n" +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" +"</tutorial>\n"; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testTutorialEmpty() { + Tutorial tutorial; + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +HEADER_XML +"<tutorial/>\n"; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testTutorialWithSeveralSteps() { + Tutorial tutorial; + tutorial.setName("The \"name\""); + tutorial.setDescription("The description,\nwith < and >\n"); + tutorial.setLicenseText("The license text,\nwith < and >\n"); + tutorial.setCustomSetupCode("The setup code,\nwith < and >\n"); + tutorial.setCustomTearDownCode("The tear down code,\nwith < and >\n"); + + Step* step1 = new Step(); + step1->setId("The id1"); + step1->setText("The text1"); + tutorial.addStep(step1); + + Step* step2 = new Step(); + step2->setId("The id2"); + step2->setText("The text2"); + tutorial.addStep(step2); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +HEADER_XML +"<tutorial name=\"The "name"\">\n" +TUTORIAL_ELEMENTS +" <step id=\"The id1\">\n" +" <text>The text1</text>\n" +" </step>\n" +" <step id=\"The id2\">\n" +" <text>The text2</text>\n" +" </step>\n" +"</tutorial>\n"; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testStep() { + Tutorial tutorial; + + Step* step = new Step(); + step->setId("The \"id\""); + step->setText("The text,\nwith < and >\n"); + step->setCustomSetupCode("The setup code,\nwith < and >\n"); + step->setCustomTearDownCode("The tear down code,\nwith < and >\n"); + tutorial.addStep(step); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +STEP_PARENT_START +" <step id=\"The "id"\">\n" +" <text>The text,\nwith < and >\n</text>\n" +" <setup>The setup code,\nwith < and >\n</setup>\n" +" <tearDown>The tear down code,\nwith < and >\n</tearDown>\n" +" </step>\n" +STEP_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testStepEmpty() { + Tutorial tutorial; + + Step* step = new Step(); + tutorial.addStep(step); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +STEP_PARENT_START +" <step/>\n" +STEP_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testStepWithSeveralReactions() { + Tutorial tutorial; + + Step* step = new Step(); + step->setId("The \"id\""); + step->setText("The text,\nwith < and >\n"); + step->setCustomSetupCode("The setup code,\nwith < and >\n"); + step->setCustomTearDownCode("The tear down code,\nwith < and >\n"); + tutorial.addStep(step); + + Reaction* reaction1 = new Reaction(); + reaction1->setTriggerType(Reaction::ConditionMet); + reaction1->setResponseType(Reaction::CustomCode); + step->addReaction(reaction1); + + Reaction* reaction2 = new Reaction(); + reaction2->setTriggerType(Reaction::OptionSelected); + reaction2->setOptionName("The option name"); + reaction2->setResponseType(Reaction::NextStep); + reaction2->setNextStepId("Another id"); + step->addReaction(reaction2); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +STEP_PARENT_START +" <step id=\"The "id"\">\n" +STEP_ELEMENTS +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\"/>\n" +" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n" +" <option name=\"The option name\"/>\n" +" <nextStep id=\"Another id\"/>\n" +" </reaction>\n" +" </step>\n" +STEP_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testReactionConditionCustomCode() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForSignal* waitForSignal = new WaitForSignal(); + waitForSignal->setEmitterName("The emitter name"); + waitForSignal->setSignalName("theSignalName(Argument1Type, Argument2Type)"); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForSignal); + reaction->setOptionName("The \"option\" name"); + reaction->setResponseType(Reaction::CustomCode); + reaction->setCustomCode("The custom code,\nwith < and >\n"); + reaction->setNextStepId("Another \"id\""); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +REACTION_PARENT_START +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\">\n" +" <option name=\"The "option" name\"/>\n" +" <waitForSignal emitterName=\"The emitter name\" \ +signalName=\"theSignalName(Argument1Type, Argument2Type)\"/>\n" +" <customCode>The custom code,\nwith < and >\n</customCode>\n" +" <nextStep id=\"Another "id"\"/>\n" +" </reaction>\n" +REACTION_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testReactionOptionNextStep() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForSignal* waitForSignal = new WaitForSignal(); + waitForSignal->setEmitterName("The emitter name"); + waitForSignal->setSignalName("theSignalName(Argument1Type, Argument2Type)"); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::OptionSelected); + reaction->setOptionName("The \"option\" name"); + reaction->setWaitFor(waitForSignal); + reaction->setResponseType(Reaction::NextStep); + reaction->setNextStepId("Another \"id\""); + reaction->setCustomCode("The custom code,\nwith < and >\n"); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +REACTION_PARENT_START +" <reaction triggerType=\"OptionSelected\" responseType=\"NextStep\">\n" +" <option name=\"The "option" name\"/>\n" +" <waitForSignal emitterName=\"The emitter name\" \ +signalName=\"theSignalName(Argument1Type, Argument2Type)\"/>\n" +" <customCode>The custom code,\nwith < and >\n</customCode>\n" +" <nextStep id=\"Another "id"\"/>\n" +" </reaction>\n" +REACTION_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testReactionEmpty() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setResponseType(Reaction::CustomCode); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +REACTION_PARENT_START +" <reaction triggerType=\"ConditionMet\" responseType=\"CustomCode\"/>\n" +REACTION_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForEvent() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForEvent* waitForEvent = new WaitForEvent(); + waitForEvent->setReceiverName("The \"receiver\" name"); + waitForEvent->setEventName("The\"Event\"Name"); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForEvent); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForEvent receiverName=\"The "receiver" name\" \ +eventName=\"The"Event"Name\"/>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForEventEmpty() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForEvent* waitForEvent = new WaitForEvent(); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForEvent); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForEvent/>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForSignal() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForSignal* waitForSignal = new WaitForSignal(); + waitForSignal->setEmitterName("The \"emitter\" name"); + waitForSignal->setSignalName("theSignalName(\"Argument1Type\")"); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForSignal); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForSignal emitterName=\"The "emitter" name\" \ +signalName=\"theSignalName("Argument1Type")\"/>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForSignalEmpty() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForSignal* waitForSignal = new WaitForSignal(); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForSignal); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForSignal/>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForComposed() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForSignal* waitForSignalChild = new WaitForSignal(); + waitForSignalChild->setEmitterName("The emitter name1"); + waitForSignalChild->setSignalName("theSignalName1()"); + + WaitForSignal* waitForSignalGrandChild1 = new WaitForSignal(); + waitForSignalGrandChild1->setEmitterName("The emitter name2"); + waitForSignalGrandChild1->setSignalName("theSignalName2()"); + + WaitForSignal* waitForSignalGrandChild2 = new WaitForSignal(); + waitForSignalGrandChild2->setEmitterName("The emitter name3"); + waitForSignalGrandChild2->setSignalName("theSignalName3()"); + + WaitForComposed* waitForOrChild = new WaitForComposed(); + waitForOrChild->setCompositionType(WaitForComposed::Or); + waitForOrChild->addWaitFor(waitForSignalGrandChild1); + waitForOrChild->addWaitFor(waitForSignalGrandChild2); + + WaitForComposed* waitForAnd = new WaitForComposed(); + waitForAnd->setCompositionType(WaitForComposed::And); + waitForAnd->addWaitFor(waitForSignalChild); + waitForAnd->addWaitFor(waitForOrChild); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForAnd); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForComposed compositionType=\"And\">\n" +" <waitForSignal emitterName=\"The emitter name1\" \ +signalName=\"theSignalName1()\"/>\n" +" <waitForComposed compositionType=\"Or\">\n" +" <waitForSignal emitterName=\"The emitter name2\" \ +signalName=\"theSignalName2()\"/>\n" +" <waitForSignal emitterName=\"The emitter name3\" \ +signalName=\"theSignalName3()\"/>\n" +" </waitForComposed>\n" +" </waitForComposed>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForComposedEmpty() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForComposed* waitForAndChild = new WaitForComposed(); + waitForAndChild->setCompositionType(WaitForComposed::And); + + WaitForComposed* waitForOrChild = new WaitForComposed(); + waitForOrChild->setCompositionType(WaitForComposed::Or); + + WaitForComposed* waitForAnd = new WaitForComposed(); + waitForAnd->setCompositionType(WaitForComposed::And); + waitForAnd->addWaitFor(waitForAndChild); + waitForAnd->addWaitFor(waitForOrChild); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForAnd); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForComposed compositionType=\"And\">\n" +" <waitForComposed compositionType=\"And\"/>\n" +" <waitForComposed compositionType=\"Or\"/>\n" +" </waitForComposed>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForNot() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForSignal* waitForSignal = new WaitForSignal(); + waitForSignal->setEmitterName("The emitter name"); + waitForSignal->setSignalName("theSignalName()"); + + WaitForNot* waitForNot = new WaitForNot(); + waitForNot->setNegatedWaitFor(waitForSignal); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForNot); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForNot>\n" +" <waitForSignal emitterName=\"The emitter name\" \ +signalName=\"theSignalName()\"/>\n" +" </waitForNot>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +void TutorialWriterTest::testWaitForNotWithoutNegatedWaitFor() { + Tutorial tutorial; + Step* step = new Step(); + tutorial.addStep(step); + + WaitForNot* waitForNot = new WaitForNot(); + + Reaction* reaction = new Reaction(); + reaction->setTriggerType(Reaction::ConditionMet); + reaction->setWaitFor(waitForNot); + reaction->setResponseType(Reaction::NextStep); + step->addReaction(reaction); + + TutorialWriter saver; + QString savedTutorial = saver.writeTutorial(&tutorial); + + QString expected = +WAITFOR_PARENT_START +" <waitForNot/>\n" +WAITFOR_PARENT_END; + + QCOMPARE(savedTutorial, expected); +} + +QTEST_MAIN(TutorialWriterTest) + +#include "TutorialWriterTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/serialization/TutorialWriterTest.cpp ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-26 01:09:32
|
Revision: 193 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=193&view=rev Author: danxuliu Date: 2010-03-26 01:09:26 +0000 (Fri, 26 Mar 2010) Log Message: ----------- Fix typo Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp Modified: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp 2010-03-25 23:45:18 UTC (rev 192) +++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp 2010-03-26 01:09:26 UTC (rev 193) @@ -67,8 +67,8 @@ delete mXmlWriter; mXmlWriter = 0; - //QXm lStreamWriter doesn't write the encoding information when a string - //is used instead of a QIODevice + //QXmlStreamWriter doesn't write the encoding information when a string is + //used instead of a QIODevice serializedTutorial.replace("<?xml version=\"1.0\"?>\n", "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); return serializedTutorial; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-25 23:45:25
|
Revision: 192 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=192&view=rev Author: danxuliu Date: 2010-03-25 23:45:18 +0000 (Thu, 25 Mar 2010) Log Message: ----------- Add TutorialWriter class to serialize a Tutorial in XML. A W3C Schema for XML serialized tutorials is also included. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/serialization/Tutorial.xsd trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.h Modified: trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-24 21:08:50 UTC (rev 191) +++ trunk/ktutorial/ktutorial-editor/src/serialization/CMakeLists.txt 2010-03-25 23:45:18 UTC (rev 192) @@ -3,6 +3,7 @@ set(ktutorial_editor_serialization_SRCS JavascriptExporter.cpp Serialization.cpp + TutorialWriter.cpp ) kde4_add_library(ktutorial_editor_serialization ${ktutorial_editor_serialization_SRCS}) Added: trunk/ktutorial/ktutorial-editor/src/serialization/Tutorial.xsd =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/Tutorial.xsd (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/Tutorial.xsd 2010-03-25 23:45:18 UTC (rev 192) @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + + <xsd:element name="tutorial" type="TutorialType"/> + + <xsd:complexType name="TutorialType"> + <xsd:sequence> + <xsd:element name="description" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="license" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="setup" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tearDown" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="step" type="StepType" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="optional"/> + </xsd:complexType> + + <xsd:complexType name="StepType"> + <xsd:sequence> + <xsd:element name="text" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="setup" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="tearDown" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="reaction" type="ReactionType" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="id" type="xsd:string" use="optional"/> + </xsd:complexType> + + <xsd:complexType name="ReactionType"> + <xsd:sequence> + <xsd:element name="option" type="OptionType" minOccurs="0" maxOccurs="1"/> + <xsd:group ref="waitFor" minOccurs="0" maxOccurs="1"/> + <xsd:element name="customCode" type="xsd:string" minOccurs="0" maxOccurs="1"/> + <xsd:element name="nextStep" type="NextStepType" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + <xsd:attribute name="triggerType" type="TriggerTypeType" use="optional"/> + <xsd:attribute name="responseType" type="ResponseTypeType" use="optional"/> + </xsd:complexType> + + <xsd:complexType name="OptionType"> + <xsd:attribute name="name" type="xsd:string" use="optional"/> + </xsd:complexType> + + <xsd:group name="waitFor"> + <xsd:choice> + <xsd:element name="waitForComposed" type="WaitForComposedType"/> + <xsd:element name="waitForEvent" type="WaitForEventType"/> + <xsd:element name="waitForNot" type="WaitForNotType"/> + <xsd:element name="waitForSignal" type="WaitForSignalType"/> + </xsd:choice> + </xsd:group> + + <xsd:complexType name="NextStepType"> + <xsd:attribute name="id" type="xsd:string" use="optional"/> + </xsd:complexType> + + <xsd:simpleType name="TriggerTypeType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="ConditionMet"/> + <xsd:enumeration value="OptionSelected"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:simpleType name="ResponseTypeType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="CustomCode"/> + <xsd:enumeration value="NextStep"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="WaitForComposedType"> + <xsd:sequence> + <xsd:group ref="waitFor" minOccurs="0" maxOccurs="unbounded"/> + </xsd:sequence> + <xsd:attribute name="compositionType" type="CompositionTypeType" use="optional"/> + </xsd:complexType> + + <xsd:simpleType name="CompositionTypeType"> + <xsd:restriction base="xsd:string"> + <xsd:enumeration value="And"/> + <xsd:enumeration value="Or"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="WaitForEventType"> + <xsd:attribute name="receiverName" type="xsd:string" use="optional"/> + <xsd:attribute name="eventName" type="xsd:string" use="optional"/> + </xsd:complexType> + + <xsd:complexType name="WaitForNotType"> + <xsd:sequence> + <xsd:group ref="waitFor" minOccurs="0" maxOccurs="1"/> + </xsd:sequence> + </xsd:complexType> + + <xsd:complexType name="WaitForSignalType"> + <xsd:attribute name="emitterName" type="xsd:string" use="optional"/> + <xsd:attribute name="signalName" type="xsd:string" use="optional"/> + </xsd:complexType> + +</xsd:schema> Added: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp 2010-03-25 23:45:18 UTC (rev 192) @@ -0,0 +1,206 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "TutorialWriter.h" + +#include "../Reaction.h" +#include "../Step.h" +#include "../Tutorial.h" +#include "../WaitForComposed.h" +#include "../WaitForEvent.h" +#include "../WaitForNot.h" +#include "../WaitForSignal.h" + +//public: + +TutorialWriter::TutorialWriter(): mXmlWriter(0) { +} + +QString TutorialWriter::writeTutorial(const Tutorial* tutorial) { + QString serializedTutorial; + + mXmlWriter = new QXmlStreamWriter(&serializedTutorial); + mXmlWriter->setAutoFormatting(true); + mXmlWriter->setAutoFormattingIndent(4); + + mXmlWriter->writeStartDocument(); + mXmlWriter->writeStartElement("tutorial"); + + if (!tutorial->name().isEmpty()) { + mXmlWriter->writeAttribute("name", tutorial->name()); + } + if (!tutorial->description().isEmpty()) { + mXmlWriter->writeTextElement("description", tutorial->description()); + } + if (!tutorial->licenseText().isEmpty()) { + mXmlWriter->writeTextElement("license", tutorial->licenseText()); + } + if (!tutorial->customSetupCode().isEmpty()) { + mXmlWriter->writeTextElement("setup", tutorial->customSetupCode()); + } + if (!tutorial->customTearDownCode().isEmpty()) { + mXmlWriter->writeTextElement("tearDown", + tutorial->customTearDownCode()); + } + foreach (const Step* step, tutorial->steps()) { + write(step); + } + + mXmlWriter->writeEndElement(); + mXmlWriter->writeEndDocument(); + + delete mXmlWriter; + mXmlWriter = 0; + + //QXm lStreamWriter doesn't write the encoding information when a string + //is used instead of a QIODevice + serializedTutorial.replace("<?xml version=\"1.0\"?>\n", + "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); + return serializedTutorial; +} + +//private: + +void TutorialWriter::write(const Step* step) { + mXmlWriter->writeStartElement("step"); + + if (!step->id().isEmpty()) { + mXmlWriter->writeAttribute("id", step->id()); + } + if (!step->text().isEmpty()) { + mXmlWriter->writeTextElement("text", step->text()); + } + if (!step->customSetupCode().isEmpty()) { + mXmlWriter->writeTextElement("setup", step->customSetupCode()); + } + if (!step->customTearDownCode().isEmpty()) { + mXmlWriter->writeTextElement("tearDown", step->customTearDownCode()); + } + foreach (const Reaction* reaction, step->reactions()) { + write(reaction); + } + + mXmlWriter->writeEndElement(); +} + +void TutorialWriter::write(const Reaction* reaction) { + mXmlWriter->writeStartElement("reaction"); + + QString triggerTypeValue; + if (reaction->triggerType() == Reaction::ConditionMet) { + triggerTypeValue = "ConditionMet"; + } else { + triggerTypeValue = "OptionSelected"; + } + mXmlWriter->writeAttribute("triggerType", triggerTypeValue); + + QString responseTypeValue; + if (reaction->responseType() == Reaction::CustomCode) { + responseTypeValue = "CustomCode"; + } else { + responseTypeValue = "NextStep"; + } + mXmlWriter->writeAttribute("responseType", responseTypeValue); + + if (!reaction->optionName().isEmpty()) { + mXmlWriter->writeEmptyElement("option"); + mXmlWriter->writeAttribute("name", reaction->optionName()); + } + if (reaction->waitFor()) { + write(reaction->waitFor()); + } + if (!reaction->customCode().isEmpty()) { + mXmlWriter->writeTextElement("customCode", reaction->customCode()); + } + if (!reaction->nextStepId().isEmpty()) { + mXmlWriter->writeEmptyElement("nextStep"); + mXmlWriter->writeAttribute("id", reaction->nextStepId()); + } + + mXmlWriter->writeEndElement(); +} + +void TutorialWriter::write(const WaitFor* waitFor) { + if (qobject_cast<const WaitForComposed*>(waitFor)) { + write(static_cast<const WaitForComposed*>(waitFor)); + return; + } + if (qobject_cast<const WaitForEvent*>(waitFor)) { + write(static_cast<const WaitForEvent*>(waitFor)); + return; + } + if (qobject_cast<const WaitForNot*>(waitFor)) { + write(static_cast<const WaitForNot*>(waitFor)); + return; + } + if (qobject_cast<const WaitForSignal*>(waitFor)) { + write(static_cast<const WaitForSignal*>(waitFor)); + return; + } +} + +void TutorialWriter::write(const WaitForComposed* waitForComposed) { + mXmlWriter->writeStartElement("waitForComposed"); + + QString compositionTypeValue; + if (waitForComposed->compositionType() == WaitForComposed::And) { + compositionTypeValue = "And"; + } else { + compositionTypeValue = "Or"; + } + mXmlWriter->writeAttribute("compositionType", compositionTypeValue); + + foreach (const WaitFor* waitFor, waitForComposed->waitFors()) { + write(waitFor); + } + + mXmlWriter->writeEndElement(); +} + +void TutorialWriter::write(const WaitForEvent* waitForEvent) { + mXmlWriter->writeEmptyElement("waitForEvent"); + + if (!waitForEvent->receiverName().isEmpty()) { + mXmlWriter->writeAttribute("receiverName", + waitForEvent->receiverName()); + } + if (!waitForEvent->eventName().isEmpty()) { + mXmlWriter->writeAttribute("eventName", waitForEvent->eventName()); + } +} + +void TutorialWriter::write(const WaitForNot* waitForNot) { + mXmlWriter->writeStartElement("waitForNot"); + + if (waitForNot->negatedWaitFor()) { + write(waitForNot->negatedWaitFor()); + } + + mXmlWriter->writeEndElement(); +} + +void TutorialWriter::write(const WaitForSignal* waitForSignal) { + mXmlWriter->writeEmptyElement("waitForSignal"); + + if (!waitForSignal->emitterName().isEmpty()) { + mXmlWriter->writeAttribute("emitterName", waitForSignal->emitterName()); + } + if (!waitForSignal->signalName().isEmpty()) { + mXmlWriter->writeAttribute("signalName", waitForSignal->signalName()); + } +} Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.h 2010-03-25 23:45:18 UTC (rev 192) @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TUTORIALWRITER_H +#define TUTORIALWRITER_H + +#include <QXmlStreamWriter> + +class Reaction; +class Step; +class Tutorial; +class WaitFor; +class WaitForComposed; +class WaitForEvent; +class WaitForNot; +class WaitForSignal; + +/** + * Serializes a Tutorial in XML. + * Each data class has its own XML element (Tutorial, Step...). Objects that + * contain objects from other classes (for example, a Tutorial contains Steps) + * follow a hierarchical XML structure (the Step XML element is child of + * Tutorial XML element). + * + * Most object attributes are written as XML text elements (like the custom + * code in a Tutorial). Some of them, which by their very own nature are small + * strings, are written as XML attributes instead (like the id of a Step). + * + * When an object doesn't have some attribute set, be it a string or another + * object, their XML attribute or XML element isn't written at all. + * + * For further details, a W3C XML Schema is provided in Tutorial.xsd file + * (ktutorial/ktutorial-editor/src/serialization/Tutorial.xsd). + */ +class TutorialWriter { +public: + + /** + * Creates a new TutorialWriter. + */ + TutorialWriter(); + + /** + * Returns the XML serialization of the given tutorial. + * + * @param tutorial The tutorial to get its XML serialization. + * @return The XML serialization of the given tutorial. + */ + QString writeTutorial(const Tutorial* tutorial); + +private: + + /** + * The XML writer to use. + */ + QXmlStreamWriter* mXmlWriter; + + /** + * Writes the XML serialization of the given step. + * + * @param step The Step to get its XML serialization. + */ + void write(const Step* step); + + /** + * Writes the XML serialization of the given reaction. + * + * @param reaction The Reaction to get its XML serialization. + */ + void write(const Reaction* reaction); + + /** + * Writes the XML serialization of the given WaitFor. + * It calls the appropriate write(const WaitForXXX*) method, depending on + * the WaitFor subclass. + * + * @param waitFor The WaitFor to get its XML serialization. + */ + void write(const WaitFor* waitFor); + + /** + * Writes the XML serialization of the given WaitForComposed. + * + * @param waitForComposed The WaitForComposed to get its XML serialization. + */ + void write(const WaitForComposed* waitForComposed); + + /** + * Writes the XML serialization of the given WaitForEvent. + * + * @param waitForEvent The WaitForEvent to get its XML serialization. + */ + void write(const WaitForEvent* waitForEvent); + + /** + * Writes the XML serialization of the given WaitForNot. + * + * @param waitForNot The WaitForNot to get its XML serialization. + */ + void write(const WaitForNot* waitForNot); + + /** + * Writes the XML serialization of the given WaitForComposed. + * + * @param waitForSignal The WaitForSignal to get its XML serialization. + */ + void write(const WaitForSignal* waitForSignal); + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/serialization/TutorialWriter.h ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-24 21:08:56
|
Revision: 191 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=191&view=rev Author: danxuliu Date: 2010-03-24 21:08:50 +0000 (Wed, 24 Mar 2010) Log Message: ----------- Add release 0.3 new, and update development, documentation and download pages Modified Paths: -------------- trunk/web-src/newsList.xml trunk/web-src/pages/development.xml trunk/web-src/pages/documentation.xml trunk/web-src/pages/download.xml trunk/web-src/pages/index.xml trunk/web-src/pages/news.xml Modified: trunk/web-src/newsList.xml =================================================================== --- trunk/web-src/newsList.xml 2010-03-24 21:03:40 UTC (rev 190) +++ trunk/web-src/newsList.xml 2010-03-24 21:08:50 UTC (rev 191) @@ -24,4 +24,18 @@ <date>2010-02-06</date> </fullDate> </new> -</news> \ No newline at end of file + + <new> + <title>KTutorial 0.3 released!</title> + <summary> + <div xmlns="http://www.w3.org/1999/xhtml"> + <p>The main feature introduced in this release is KTutorial editor, a graphical editor to ease tutorial authoring. It is still in an early stage of development (you can't even save and load a tutorial to continue working on it later), but it will be improved in the next releases.</p> + <p>The <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.3/Release notes/view" title="KTutorial 0.3 release notes">release notes</a> contain more information about the changes from 0.2 release.</p> + <p>Check the <a href="download.html" title="Download page in KTutorial web">download page</a> for information about downloading and building KTutorial.</p> + </div> + </summary> + <fullDate> + <date>2010-03-24</date> + </fullDate> + </new> +</news> Modified: trunk/web-src/pages/development.xml =================================================================== --- trunk/web-src/pages/development.xml 2010-03-24 21:03:40 UTC (rev 190) +++ trunk/web-src/pages/development.xml 2010-03-24 21:08:50 UTC (rev 191) @@ -34,6 +34,7 @@ <h2><a id="status" class="anchorLink">Status</a></h2> </div> <p>Right now, KTutorial is in a prototype state, but it is able to execute tutorials: it works!</p> + <p>As well as the library itself, KTutorial provides a graphical editor for tutorials, not surprisingly named Ktutorial editor.</p> <p>In KTutorial SVN there is also a little test application, KTutorial test app, which shows the different features of KTutorial in a "real" environment.</p> <p>Here it is the current features list:</p> <ul> @@ -55,6 +56,9 @@ <li> <p><em>CMake build system:</em> KTutorial uses KDE 4 CMake build system, and also provides a CMake module to be used from applications using KTutorial to configure them as necessary.</p> </li> + <li> + <p><em>Graphical editor:</em> KTutorial editor is a companion to KTutorial library to ease tutorial authoring. A tutorial can be defined using the editor and then exported to a scripted tutorial that can be understood by KTutorial library. However, the editor is still very basic at this time.</p> + </li> </ul> <div class="h2Rounded"> @@ -63,20 +67,20 @@ <p>Here you can see what (major) features I expect to include in the future.</p> <ul class="foldableList"> <li> - 0.3: + 0.4: <ul> - <li>A graphical editor to create tutorials</li> + <li>Emphasize widgets to help the user finding them (provided it is technically viable)</li> + <li>In KTutorial editor, get the name of the objects that send signals or receive events from the application the tutorial documents, just clicking on the desired widget (provided it is technically viable)</li> </ul> </li> <li> Someday? (these features need further investigation about their technical viability): <ul> - <li>Emphasize widgets to help the user finding them</li> <li>Extended information in step texts (something like "What is this" help on specific words, for example)</li> </ul> </li> </ul> - <p class="lastUpdated">Last updated: 2010-01-30</p> + <p class="lastUpdated">Last updated: 2010-03-24</p> </page:content> </page> Modified: trunk/web-src/pages/documentation.xml =================================================================== --- trunk/web-src/pages/documentation.xml 2010-03-24 21:03:40 UTC (rev 190) +++ trunk/web-src/pages/documentation.xml 2010-03-24 21:08:50 UTC (rev 191) @@ -23,8 +23,8 @@ <div class="h2Rounded"> <h2><a id="finalUsers" class="anchorLink">For final users</a></h2> </div> - <p>There is no specific documentation for KTutorial final users right now.</p> - <p>However, if you have an application that uses KTutorial, it is very easy to execute the tutorials. Just go to <em>Help->Tutorials...</em> and a dialog with all the available tutorials will appear. Select one, click on <em>Start</em> button and now just follow it!</p> + <p>KTutorial provides a tutorial named <em>Using tutorials</em> which purpose is, well, show how to use tutorials ;)</p> + <p>But, how you can start a tutorial? If you have an application that uses KTutorial, just go to <em>Help->Tutorials...</em> and a dialog with all the available tutorials will appear. Select one, click on <em>Start</em> button and now just follow it!</p> <p>If your application doesn't have a <em>Help->Tutorials...</em> menu item, sorry, it doesn't use KTutorial ;)</p> <p>Note, however, that right now only KTutorial test application uses KTutorial :P</p> @@ -40,6 +40,6 @@ </div> <p>Refer to <a href="development.html" title="Development information">development</a> section of the web.</p> - <p class="lastUpdated">Last updated: 2010-01-30</p> + <p class="lastUpdated">Last updated: 2010-03-24</p> </page:content> </page> Modified: trunk/web-src/pages/download.xml =================================================================== --- trunk/web-src/pages/download.xml 2010-03-24 21:03:40 UTC (rev 190) +++ trunk/web-src/pages/download.xml 2010-03-24 21:08:50 UTC (rev 191) @@ -17,8 +17,8 @@ <div class="h2Rounded"> <h2><a id="releases" class="anchorLink">Releases</a></h2> </div> - <p>Current release is 0.2. You can download <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.2/ktutorial-0.2.tar.gz/download" title="KTutorial 0.2 release in tar.gz">ktutorial-0.2.tar.gz</a> from <a href="http://sourceforge.net/projects/ktutorial/files/" title="KTutorial project files">project's file list</a>.</p> - <p>You can also see the <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.2/Release%20notes/view" title="KTutorial 0.2 release notes">release notes</a> (although there isn't much to see ;) ).</p> + <p>Current release is 0.3. You can download <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.3/ktutorial-0.3.tar.gz/download" title="KTutorial 0.3 release in tar.gz">ktutorial-0.3.tar.gz</a> from <a href="http://sourceforge.net/projects/ktutorial/files/" title="KTutorial project files">project's file list</a>.</p> + <p>You can also see the <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.3/Release%20notes/view" title="KTutorial 0.3 release notes">release notes</a> (although there isn't much to see ;) ).</p> <p>See below for build instructions, in <a href="#build" title="Build instructions">building section</a>.</p> <p>If you do know what you are doing ;) , you can also checkout KTutorial sources from <acronym title="Subversion">SVN</acronym> repository. Go on reading to know how to do it.</p> @@ -41,6 +41,6 @@ <p>Create a <em>build</em> subdirectory in <em>ktutorial</em> directory, and change to it. Now, in a terminal, just run <strong>cmake ../ && make</strong> and it will configure and build KTutorial in the <em>build</em> directory. Once built, execute <strong>make install</strong> and you are done (you will likely need to change to root user, as default KDE installation is usually only root writable).</p> <p>If you want to specify a prefix to install KTutorial to, instead of using KDE default installation directory, call CMake using the parameter <strong>-DCMAKE_INSTALL_PREFIX=/installation/prefix</strong>. For debugging purposes, use <strong>-DCMAKE_BUILD_TYPE=debugfull</strong>. To automatically build the unit tests when the library is built, use <strong>-DKDE4_BUILD_TESTS=ON</strong>.</p> - <p class="lastUpdated">Last updated: 2010-02-06</p> + <p class="lastUpdated">Last updated: 2010-03-24</p> </page:content> </page> Modified: trunk/web-src/pages/index.xml =================================================================== --- trunk/web-src/pages/index.xml 2010-03-24 21:03:40 UTC (rev 190) +++ trunk/web-src/pages/index.xml 2010-03-24 21:08:50 UTC (rev 191) @@ -26,6 +26,21 @@ <div id="news"> <div class="new"> <h2 class="newTitle"> + <a id="newId3" class="anchorLink">KTutorial 0.3 released!</a> + </h2> + <div class="newBody"> + <p class="newDate">2010-03-24</p> + <div class="newContent"> + <div> + <p>The main feature introduced in this release is KTutorial editor, a graphical editor to ease tutorial authoring. It is still in an early stage of development (you can't even save and load a tutorial to continue working on it later), but it will be improved in the next releases.</p> + <p>The <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.3/Release notes/view" title="KTutorial 0.3 release notes">release notes</a> contain more information about the changes from 0.2 release.</p> + <p>Check the <a href="download.html" title="Download page in KTutorial web">download page</a> for information about downloading and building KTutorial.</p> + </div> + </div> + </div> + </div> + <div class="new"> + <h2 class="newTitle"> <a id="newId2" class="anchorLink">KTutorial 0.2 released!</a> </h2> <div class="newBody"> Modified: trunk/web-src/pages/news.xml =================================================================== --- trunk/web-src/pages/news.xml 2010-03-24 21:03:40 UTC (rev 190) +++ trunk/web-src/pages/news.xml 2010-03-24 21:08:50 UTC (rev 191) @@ -23,6 +23,21 @@ <div id="news"> <div class="new"> <h2 class="newTitle"> + <a id="newId3" class="anchorLink">KTutorial 0.3 released!</a> + </h2> + <div class="newBody"> + <p class="newDate">2010-03-24</p> + <div class="newContent"> + <div> + <p>The main feature introduced in this release is KTutorial editor, a graphical editor to ease tutorial authoring. It is still in an early stage of development (you can't even save and load a tutorial to continue working on it later), but it will be improved in the next releases.</p> + <p>The <a href="http://sourceforge.net/projects/ktutorial/files/ktutorial-0.3/Release notes/view" title="KTutorial 0.3 release notes">release notes</a> contain more information about the changes from 0.2 release.</p> + <p>Check the <a href="download.html" title="Download page in KTutorial web">download page</a> for information about downloading and building KTutorial.</p> + </div> + </div> + </div> + </div> + <div class="new"> + <h2 class="newTitle"> <a id="newId2" class="anchorLink">KTutorial 0.2 released!</a> </h2> <div class="newBody"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-24 21:03:47
|
Revision: 190 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=190&view=rev Author: danxuliu Date: 2010-03-24 21:03:40 +0000 (Wed, 24 Mar 2010) Log Message: ----------- Add KTutorial editor screenshots Modified Paths: -------------- trunk/web-src/pages/aboutWeb.xml trunk/web-src/pages/screenshotsGallery.xml trunk/web-src/screenshotsList.xml Added Paths: ----------- trunk/web-src/data/images/screenshots/MainWindow-192.png trunk/web-src/data/images/screenshots/MainWindow.png trunk/web-src/data/images/screenshots/NewCondition-192.png trunk/web-src/data/images/screenshots/NewCondition.png trunk/web-src/data/images/screenshots/SetReactionData-192.png trunk/web-src/data/images/screenshots/SetReactionData.png Added: trunk/web-src/data/images/screenshots/MainWindow-192.png =================================================================== (Binary files differ) Property changes on: trunk/web-src/data/images/screenshots/MainWindow-192.png ___________________________________________________________________ Added: svn:mime-type + image/png Added: trunk/web-src/data/images/screenshots/MainWindow.png =================================================================== (Binary files differ) Property changes on: trunk/web-src/data/images/screenshots/MainWindow.png ___________________________________________________________________ Added: svn:mime-type + image/png Added: trunk/web-src/data/images/screenshots/NewCondition-192.png =================================================================== (Binary files differ) Property changes on: trunk/web-src/data/images/screenshots/NewCondition-192.png ___________________________________________________________________ Added: svn:mime-type + image/png Added: trunk/web-src/data/images/screenshots/NewCondition.png =================================================================== (Binary files differ) Property changes on: trunk/web-src/data/images/screenshots/NewCondition.png ___________________________________________________________________ Added: svn:mime-type + image/png Added: trunk/web-src/data/images/screenshots/SetReactionData-192.png =================================================================== (Binary files differ) Property changes on: trunk/web-src/data/images/screenshots/SetReactionData-192.png ___________________________________________________________________ Added: svn:mime-type + image/png Added: trunk/web-src/data/images/screenshots/SetReactionData.png =================================================================== (Binary files differ) Property changes on: trunk/web-src/data/images/screenshots/SetReactionData.png ___________________________________________________________________ Added: svn:mime-type + image/png Modified: trunk/web-src/pages/aboutWeb.xml =================================================================== --- trunk/web-src/pages/aboutWeb.xml 2010-03-24 19:49:06 UTC (rev 189) +++ trunk/web-src/pages/aboutWeb.xml 2010-03-24 21:03:40 UTC (rev 190) @@ -79,6 +79,7 @@ <p>The only known element used which isn't ECMAScript is <em>onresize</em> event handling for the window (used in the gallery generator to resize the screenshots when the window is resized, and also used to load the scripts on window load). As far as I know, it's Javascript, because the <a href="http://www.w3.org/TR/Window/" title="W3C Window Object 1.0 specification">Window Object specification</a> is still a Working draft and doesn't have <a href="http://www.w3.org/TR/Window/#ecmascript-binding" title="ECMAScript binding for Window Object">ECMAScript bindings</a> defined. I haven't found an equivalent way to do it with pure ECMAScript.</p> <p>The four scripts are: <a href="src/data/script/roundedCorners.js" title="Script to round corners">script/roundedCorners.js</a>, <a href="src/data/script/galleryGenerator.js" title="Script to generate a screenshots gallery">script/galleryGenerator.js</a>, <a href="src/data/script/foldableList.js" title="Script to make nested lists foldable">script/foldableList.js</a> and <a href="src/data/script/videoEmbedder.js" title="Script to replace ogg video links with embedded players">script/videoEmbedder.js</a>. Further information about each script can be found in the documentation in their header and functions documentation.</p> <p>Those scripts only adds some optional features. Their lack doesn't ruin the use of the website, and, as desirable, it's perfectly usable in not ECMAScript enabled browsers. Each script is guarded against not conformant browsers using the hasFeature(feature, version) method of the DOMImplementation interface.</p> + <p>In fact, <em>script/galleryGenerator.js</em> is currently disabled until I can get some time to fix it, as the screenshots are resized over their natural size when the page size is too large. Better no gallery than an ugly gallery :P</p> <p>Sadly, the fifth script, the one that contains the true video player, wasn't developed by me and I don't know whether it conforms to ECMAScript or not. I hope that it does, anyway ;)</p> <div class="h2Rounded"> <h2> @@ -114,6 +115,6 @@ <li>Copy source dir: copy all the contents of the <em>src</em> directory to the <em>src</em> subdirectory of the output directory.</li> </ol> - <p class="lastUpdated">Last updated: 2010-01-30</p> + <p class="lastUpdated">Last updated: 2010-03-24</p> </page:content> </page> Modified: trunk/web-src/pages/screenshotsGallery.xml =================================================================== --- trunk/web-src/pages/screenshotsGallery.xml 2010-03-24 19:49:06 UTC (rev 189) +++ trunk/web-src/pages/screenshotsGallery.xml 2010-03-24 21:03:40 UTC (rev 190) @@ -5,10 +5,28 @@ <page:headElements xmlns:page="http://lusi.berlios.de/namespaces/page" xmlns="http://www.w3.org/1999/xhtml"> <script src="script/galleryGenerator.js" type="text/javascript">/*Empty*/</script> </page:headElements> - <scriptOnLoad>generateGallery();</scriptOnLoad> </variables> <page:content xmlns:page="http://lusi.berlios.de/namespaces/page" xmlns="http://www.w3.org/1999/xhtml"> <h1>Gallery</h1> - <p>Nothing to see here. Move along.</p> + <ul id="screenshotsList"> + <li> + <p>KTutorial editor: Main window</p> + <a href="images/screenshots/MainWindow.png" title="Click for full size"> + <img src="images/screenshots/MainWindow-192.png" alt="KTutorial editor main window showing a tutorial being worked on" width="192" height="144"/> + </a> + </li> + <li> + <p>KTutorial editor: New condition to wait for</p> + <a href="images/screenshots/NewCondition.png" title="Click for full size"> + <img src="images/screenshots/NewCondition-192.png" alt="KTutorial editor dialog to add a new condition to wait for" width="192" height="93"/> + </a> + </li> + <li> + <p>KTutorial editor: Set reaction data</p> + <a href="images/screenshots/SetReactionData.png" title="Click for full size"> + <img src="images/screenshots/SetReactionData-192.png" alt="KTutorial editor dialog to set the trigger and response of a reaction" width="192" height="221"/> + </a> + </li> + </ul> </page:content> </page> Modified: trunk/web-src/screenshotsList.xml =================================================================== --- trunk/web-src/screenshotsList.xml 2010-03-24 19:49:06 UTC (rev 189) +++ trunk/web-src/screenshotsList.xml 2010-03-24 21:03:40 UTC (rev 190) @@ -4,6 +4,21 @@ <ul id="screenshotsList" xmlns="http://www.w3.org/1999/xhtml"> <li> - <p>Nothing to see here. Move along.</p> + <p>KTutorial editor: Main window</p> + <a href="images/screenshots/MainWindow.png" title="Click for full size"> + <img src="images/screenshots/MainWindow-192.png" alt="KTutorial editor main window showing a tutorial being worked on" width="192" height="144"/> + </a> </li> + <li> + <p>KTutorial editor: New condition to wait for</p> + <a href="images/screenshots/NewCondition.png" title="Click for full size"> + <img src="images/screenshots/NewCondition-192.png" alt="KTutorial editor dialog to add a new condition to wait for" width="192" height="93"/> + </a> + </li> + <li> + <p>KTutorial editor: Set reaction data</p> + <a href="images/screenshots/SetReactionData.png" title="Click for full size"> + <img src="images/screenshots/SetReactionData-192.png" alt="KTutorial editor dialog to set the trigger and response of a reaction" width="192" height="221"/> + </a> + </li> </ul> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-24 19:49:12
|
Revision: 189 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=189&view=rev Author: danxuliu Date: 2010-03-24 19:49:06 +0000 (Wed, 24 Mar 2010) Log Message: ----------- 0.3 release tagged Added Paths: ----------- tags/ktutorial-0.3/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dan...@us...> - 2010-03-24 19:45:22
|
Revision: 188 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=188&view=rev Author: danxuliu Date: 2010-03-24 19:45:15 +0000 (Wed, 24 Mar 2010) Log Message: ----------- Add i18n infrastructure for handbook and Spanish handbook translation Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/doc/CMakeLists.txt Added Paths: ----------- trunk/ktutorial/ktutorial-editor/doc/Messages.sh trunk/ktutorial/ktutorial-editor/doc/es/ trunk/ktutorial/ktutorial-editor/doc/es/CMakeLists.txt trunk/ktutorial/ktutorial-editor/doc/es/ktutorial-editor-handbook.po trunk/ktutorial/ktutorial-editor/doc/header.pot trunk/ktutorial/ktutorial-editor/doc/ktutorial-editor-handbook.pot Modified: trunk/ktutorial/ktutorial-editor/doc/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/doc/CMakeLists.txt 2010-03-24 19:18:06 UTC (rev 187) +++ trunk/ktutorial/ktutorial-editor/doc/CMakeLists.txt 2010-03-24 19:45:15 UTC (rev 188) @@ -1 +1,52 @@ add_subdirectory(en) + +find_program(PO2XML_EXECUTABLE po2xml) + +if(NOT PO2XML_EXECUTABLE) + message( +"------ + NOTE: po2xml not found. Handbook translations will *not* be installed +------") +else(NOT PO2XML_EXECUTABLE) + + file(GLOB_RECURSE PO_FILES ktutorial-editor-handbook.po) + file(GLOB DOCBOOK_FILES en/*.docbook) + + foreach(poFile ${PO_FILES}) + get_filename_component(poFilePath ${poFile} PATH) + get_filename_component(lang ${poFilePath} NAME) + + # A translated docbook file for each english docbook file is created in + # the directory of each language. The files have to be created in the + # source directory instead of the binary directory as would be desirable + # because kde4_create_handbook searches the docbook files in the source + # directory + foreach(docbookFile ${DOCBOOK_FILES}) + get_filename_component(docbookFileName ${docbookFile} NAME) + set(translatedDocbookFile ${CMAKE_CURRENT_SOURCE_DIR}/${lang}/${docbookFileName}) + list(APPEND allTranslatedDocbookFiles ${translatedDocbookFile}) + + set(po2XmlCommand ${PO2XML_EXECUTABLE} ${docbookFile} ${poFile}) + + add_custom_command(OUTPUT ${translatedDocbookFile} + COMMAND ${po2XmlCommand} > ${translatedDocbookFile} + DEPENDS ${docbookFile} ${poFile}) + + # kde4_create_handbook gets a list of the docbook files that had to + # be copied when the handbook is installed. It creates, when the + # configuration previous to the build is made, the translation for + # each file in order to be found by the macro. + # It does not interfere with the normmal behavior of the build + # system. The translations will be updated as needed when the + # docbook or the po file are modified. + execute_process(COMMAND ${po2XmlCommand} + OUTPUT_FILE ${translatedDocbookFile}) + endforeach(docbookFile ${DOCBOOK_FILES}) + endforeach(poFile ${PO_FILES}) + + add_custom_target(handbook-translations ALL DEPENDS ${allTranslatedDocbookFiles}) + + # Add all the translation directories here + add_subdirectory(es) + +endif(NOT PO2XML_EXECUTABLE) Added: trunk/ktutorial/ktutorial-editor/doc/Messages.sh =================================================================== --- trunk/ktutorial/ktutorial-editor/doc/Messages.sh (rev 0) +++ trunk/ktutorial/ktutorial-editor/doc/Messages.sh 2010-03-24 19:45:15 UTC (rev 188) @@ -0,0 +1,49 @@ +#!/bin/sh + +BASEDIR="en/" # root of translatable sources +PROJECT="ktutorial-editor" # project name +WDIR=`pwd` # working dir + +echo "Extracting messages" +cd ${BASEDIR} +docbookFiles=`find . -name '*.docbook'` +for docbookFile in $docbookFiles; do + xml2pot $docbookFile > ${WDIR}/$docbookFile.pot +done +echo "Done extracting messages" + + +echo "Concatenating pot files" +cd ${WDIR} +temporaryPotFiles=`find . -name '*.docbook.pot'` +msgcat $temporaryPotFiles -o ${PROJECT}-handbook.pot + +# The PO metadata generated by xml2pot contains specific KDE information, like +# mailing list or bugzilla addresses. To avoid KTutorial localization problems +# be sent there, a custom POT file containing only the desired header (one +# generated by gettext utils) is added before the handbook POT file. As the +# header POT file only contains the header, it can be used to replace the one +# generated by xml2pot. +# However, the header POT file has to be updated to keep the POT-Creation-Date +# attribute to the current creation date. +potCreationDate=`sed -nr 's/"(POT-Creation-Date:.*)\\\n"/\1/p' ${PROJECT}-handbook.pot` +sed --in-place "s/^\"POT-Creation-Date:.*\"/\"$potCreationDate\\\n\"/" header.pot +msgcat --use-first header.pot ${PROJECT}-handbook.pot -o ${PROJECT}-handbook.pot +echo "Done concatenating pot files" + + +echo "Merging translations" +cd ${WDIR} +catalogs=`find . -name '*.po'` +for cat in $catalogs; do + echo $cat + msgmerge -o $cat.new $cat ${PROJECT}-handbook.pot + mv $cat.new $cat +done +echo "Done merging translations" + + +echo "Cleaning up" +cd ${WDIR} +rm $temporaryPotFiles +echo "Done" Property changes on: trunk/ktutorial/ktutorial-editor/doc/Messages.sh ___________________________________________________________________ Added: svn:executable + * Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/doc/es/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/doc/es/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/doc/es/CMakeLists.txt 2010-03-24 19:45:15 UTC (rev 188) @@ -0,0 +1,4 @@ +########### install files ################ + +# index.docbook is created when needed by parent CMakeLists.txt +kde4_create_handbook(index.docbook INSTALL_DESTINATION ${HTML_INSTALL_DIR}/es SUBDIR ktutorial-editor) Property changes on: trunk/ktutorial/ktutorial-editor/doc/es/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/doc/es/ktutorial-editor-handbook.po =================================================================== --- trunk/ktutorial/ktutorial-editor/doc/es/ktutorial-editor-handbook.po (rev 0) +++ trunk/ktutorial/ktutorial-editor/doc/es/ktutorial-editor-handbook.po 2010-03-24 19:45:15 UTC (rev 188) @@ -0,0 +1,1754 @@ +# Spanish translations for ktutorial-editor handbook +# Traducciones al español para el manual de ktutorial-editor. +# Copyright (C) 2010 Daniel Calviño Sánchez +# This file is distributed under the same license as the ktutorial-editor handbook. +# +# Daniel Calviño Sánchez <dan...@gm...>, 2010. +msgid "" +msgstr "" +"Project-Id-Version: ktutorial-editor handbook\n" +"Report-Msgid-Bugs-To: http://sourceforge.net/tracker/?" +"group_id=301227&atid=1270278\n" +"POT-Creation-Date: 2010-03-24 19:34+0000\n" +"PO-Revision-Date: 2010-03-24 20:33+0100\n" +"Last-Translator: Daniel Calviño Sánchez <dan...@gm...>\n" +"Language-Team: Spanish <>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.0\n" + +#. Tag: title +#: index.docbook:22 +#, no-c-format +msgid "The &ktutorial-editor; Handbook" +msgstr "Manual de &ktutorial-editor;" + +#. Tag: author +#: index.docbook:25 +#, no-c-format +msgid "" +"<personname> <firstname>Daniel</firstname> <surname>Calviño Sánchez</" +"surname> </personname> <email>dan...@gm...</email>" +msgstr "" +"<personname> <firstname>Daniel</firstname> <surname>Calviño Sánchez</" +"surname> </personname> <email>dan...@gm...</email>" + +#. Tag: trans_comment +#: index.docbook:34 +#, no-c-format +msgid "ROLES_OF_TRANSLATORS" +msgstr "" +"<othercredit role=\"translator\"> <firstname>Daniel</firstname> " +"<surname>Calviño Sánchez</surname> <contrib>Traducción</contrib> " +"<email>dan...@gm...</email></othercredit>" + +#. Tag: holder +#: index.docbook:38 +#, no-c-format +msgid "Daniel Calviño Sánchez" +msgstr "Daniel Calviño Sánchez" + +#. Tag: para +#: index.docbook:58 index.docbook:74 +#, no-c-format +msgid "&ktutorial-editor; is a graphical editor for KTutorial tutorials." +msgstr "&ktutorial-editor; es un editor gráfico de tutoriales para KTutorial." + +#. Tag: keyword +#: index.docbook:62 +#, no-c-format +msgid "<keyword>KDE</keyword>" +msgstr "<keyword>KDE</keyword>" + +#. Tag: keyword +#: index.docbook:63 +#, no-c-format +msgid "KTutorial editor" +msgstr "KTutorial editor" + +#. Tag: keyword +#: index.docbook:64 +#, no-c-format +msgid "KTutorial" +msgstr "KTutorial" + +#. Tag: keyword +#: index.docbook:65 +#, no-c-format +msgid "tutorial" +msgstr "tutorial" + +#. Tag: keyword +#: index.docbook:66 +#, no-c-format +msgid "editor" +msgstr "editor" + +#. Tag: title +#: index.docbook:72 +#, no-c-format +msgid "Introduction" +msgstr "Introducción" + +#. Tag: para +#: index.docbook:75 +#, no-c-format +msgid "" +"KTutorial is a interactive tutorial system for KDE 4. You can get more " +"information about KTutorial in its webpage: <ulink url=\"http://ktutorial." +"sourceforge.net\">http://ktutorial.sourceforge.net</ulink>." +msgstr "" +"Ktutorial es un sistema de tutoriales interactivos para KDE 4. Puedes " +"conseguir más información sobre KTutorial en su página web: <ulink url=" +"\"http://ktutorial.sourceforge.net\">http://ktutorial.sourceforge.net</" +"ulink>." + +#. Tag: para +#: index.docbook:76 +#, no-c-format +msgid "" +"Using &ktutorial-editor; you can design a tutorial for some application " +"specifying the steps that it will be composed of. For each step, you can " +"specify how the tutorial will react, for example, when the user selects an " +"option, closes a dialog, writes some text..." +msgstr "" +"Mediante &ktutorial-editor; puedes diseñar un tutorial para cierta " +"aplicación indicando los pasos de los que estará compuesto. Para cada paso, " +"puedes indicar cómo reaccionará el tutorial, por ejemplo, cuando el usuario " +"seleccione una opción, cierre un diálogo, escriba cierto texto..." + +#. Tag: para +#: index.docbook:77 +#, no-c-format +msgid "" +"Once the tutorial has been designed, it can be exported by &ktutorial-" +"editor; to a scripted tutorial. Once the scripted tutorial is placed in the " +"appropriate directory, it can be read by KTutorial library and started by " +"the user of the application." +msgstr "" +"Una vez que el tutorial haya sido diseñado, puede ser exportado mediante " +"&ktutorial-editor; a un tutorial en script. Una vez colocado el tutorial en " +"script en el directorio apropiado éste puede ser leído por la biblioteca de " +"KTutorial y el usuario de la aplicación podrá comenzar el tutorial." + +#. Tag: para +#: index.docbook:78 +#, no-c-format +msgid "" +"Tutorials created by &ktutorial-editor; are not as powerful as fully hand " +"made tutorials. However, they are way easier to create and the generated " +"source code can be used as a skeleton to be manually completed if the " +"tutorial requires something not supported by &ktutorial-editor;." +msgstr "" +"Los tutoriales creados mediante &ktutorial-editor; no son tan potentes como " +"los tutoriales hechos completamente a mano. Sin embargo, son mucho más " +"fáciles de crear y el código fuente generado puede utilizarse como un " +"esqueleto a completar manualmente si el tutorial requiere algo no soportado " +"por &ktutorial-editor;." + +#. Tag: title +#: index.docbook:89 +#, no-c-format +msgid "Credits and License" +msgstr "Créditos y licencia" + +#. Tag: para +#: index.docbook:91 +#, no-c-format +msgid "&ktutorial-editor;" +msgstr "&ktutorial-editor;" + +#. Tag: para +#: index.docbook:94 +#, no-c-format +msgid "" +"Program Copyright 2010 Daniel Calviño Sánchez <email>dan...@gm...</" +"email>" +msgstr "" +"Programa Copyright 2010 Daniel Calviño Sánchez <email>dan...@gm...</" +"email>" + +#. Tag: para +#: index.docbook:98 +#, no-c-format +msgid "" +"Documentation Copyright 2010 Daniel Calviño Sánchez <email>danxuliu@gmail." +"com</email>" +msgstr "" +"Documentación Copyright 2010 Daniel Calviño Sánchez <email>danxuliu@gmail." +"com</email>" + +#. Tag: trans_comment +#: index.docbook:102 +#, no-c-format +msgid "CREDIT_FOR_TRANSLATORS" +msgstr "" +"<para>Traducción Daniel Calviño Sánchez <email>dan...@gm...</email></" +"para>" + +#. Tag: chapter +#: index.docbook:102 +#, no-c-format +msgid "&underFDL; &underGPL;" +msgstr "&underFDL; &underGPL;" + +#. Tag: title +#: using.docbook:8 +#, no-c-format +msgid "Using &ktutorial-editor;" +msgstr "Utilización de &ktutorial-editor;" + +#. Tag: para +#: using.docbook:10 +#, no-c-format +msgid "" +"In this chapter you should find all the information you need to use " +"&ktutorial-editor;. However, some general information about KTutorial is " +"also given here, as it is needed to fully understand the purpose of " +"&ktutorial-editor;." +msgstr "" +"En este capítulo encontrarás toda la información que necesitas para utilizar " +"&ktutorial-editor;. No obstante, también se ofrece algo de información " +"general sobre KTutorial, ya que es necesaria para comprender bien el " +"propósito de &ktutorial-editor;." + +#. Tag: title +#: using.docbook:13 +#, no-c-format +msgid "Getting extended information" +msgstr "Obtener información extendida" + +#. Tag: para +#: using.docbook:15 +#, no-c-format +msgid "" +"You can also get extended information about a lot of widgets throughout " +"&ktutorial-editor; using the <emphasis>What's This?</emphasis> help. " +"<emphasis>What's This?</emphasis> help can be shown with the keyboard " +"shortcut <keycombo action=\"simul\">&Shift;<keycap>F1</keycap></keycombo>, " +"selecting <guimenuitem>What's This?</guimenuitem> from the <guimenu>Help</" +"guimenu> menu or, with some window decorations, clicking on the What's This? " +"button in the window's titlebar (usually a question mark), and then clicking " +"on the widget to get its extended help." +msgstr "" +"También puedes obtener información extendida sobre un montón de elementos de " +"pantalla de &ktutorial-editor; utilizando la ayuda <emphasis>¿Qué es esto?</" +"emphasis>. La ayuda <emphasis>¿Qué es esto?</emphasis> puede mostrarse con " +"el atajo de teclado <keycombo action=\"simul\">&Shift;<keycap>F1</keycap></" +"keycombo>, seleccionando <guimenuitem>¿Qué es esto?</guimenuitem> desde el " +"menú <guimenu>Ayuda</guimenu> o, en ciertas decoraciones de ventanas, " +"haciendo click en el botón de ¿Qué es esto? del título de la ventana " +"(generalmente un signo de interrogación), y luego haciendo click en el " +"elemento de pantalla del que se desea ver la ayuda extendida." + +#. Tag: title +#: using.docbook:19 +#, no-c-format +msgid "Understanding KTutorial" +msgstr "Entendiendo KTutorial" + +#. Tag: para +#: using.docbook:21 +#, no-c-format +msgid "" +"&ktutorial-editor; is just a graphical editor to create tutorials to be used " +"by KTutorial. That is why you should at least have some little notions of " +"how KTutorial works to fully understand the purpose of &ktutorial-editor;." +msgstr "" +"&ktutorial-editor; es simplemente un editor gráfico que permite crear " +"tutoriales para ser usados por KTutorial. Es por esto que deberías tener al " +"menos una pequeña noción de cómo funciona KTutorial para entender bien el " +"propósito de &ktutorial-editor;." + +#. Tag: para +#: using.docbook:23 +#, no-c-format +msgid "" +"A tutorial is a little guide to help the user to learn how to use an " +"application. For example, it shows the user how some feature works, or how " +"to accomplish some task. A tutorial is composed of several steps, each one " +"containing a bit of information." +msgstr "" +"Un tutorial es una pequeña guía para ayudar al usuario a aprender a usar una " +"aplicación. Por ejemplo, muestra al usuario cómo funciona cierta " +"característica, o cómo llevar a cabo cierta tarea. Un tutorial está formado " +"por varios pasos, y cada uno contiene un poco de información." + +#. Tag: para +#: using.docbook:25 +#, no-c-format +msgid "" +"The most interesting feature is that, with KTutorial, applications can " +"explain to the user how to do something in an interactive way. Each step " +"contains one or more reactions. A reaction is composed by a trigger and a " +"response: when the reaction is triggered, the response is executed." +msgstr "" +"La característica más interesante es que, mediante KTutorial, las " +"aplicaciones pueden explicar al usuario cómo hacer algo de manera " +"interactiva. Cada paso contiene una o más reacciones. Una reacción está " +"formada por un activador y una respuesta: cuando se activa la reacción, se " +"ejecuta la respuesta." + +#. Tag: para +#: using.docbook:27 +#, no-c-format +msgid "" +"There are two types of triggers: options and conditions to wait for. Options " +"are shown to the user as buttons below the text of the step, and the " +"response is executed when the user selects the option. Conditions to wait " +"for are not show in any way to the user, and the response is executed when " +"the condition is met. For example, when an object receives an event, or when " +"an object emits a signal." +msgstr "" +"Hay dos tipos de activadores: opciones y condiciones por las que esperar. " +"Las opciones se muestran al usuario como botones bajo el texto del paso, y " +"la respuesta se ejecuta cuando el usuario selecciona la opción. Las " +"condiciones por las que esperar no se muestran en modo alguno al usuario, y " +"la respuesta se ejecuta cuando se cumple la condición. Por ejemplo, cuando " +"un objeto recibe un evento, o cuando un objeto emite una señal." + +#. Tag: para +#: using.docbook:29 +#, no-c-format +msgid "" +"There are also two types of responses: changing to another step, or " +"executing some custom code." +msgstr "" +"Hay también dos tipos de respuestas: cambiar a otro paso, o ejecutar un " +"código propio." + +#. Tag: para +#: using.docbook:31 +#, no-c-format +msgid "" +"Finally, KTutorial provides a system to execute some actions when a tutorial " +"starts or finishes, or when the tutorial enters or exists from a step." +msgstr "" +"Finalmente, KTutorial tiene un sistema para llevar a cabo ciertas acciones " +"cuando un tutorial comienza o termina, o cuando el tutorial entra o sale de " +"un paso." + +#. Tag: para +#: using.docbook:33 +#, no-c-format +msgid "" +"All this abstract concepts are fine but, how do you tell KTutorial all those " +"things? KTutorial is a software package, how does it know that it has to " +"wait for something to happen, or show the user some text, or whatever? " +"KTutorial tutorials are specified as source code, be it C++ or a script " +"language." +msgstr "" +"Todos estos conceptos abstractos están muy bien, pero ¿cómo haces para " +"decirle a KTutorial todas esas cosas? Ktutorial es un paquete de software, " +"¿cómo sabe que tiene que esperar a que ocurra algo, o mostrar un texto al " +"usuario, o lo que sea? Los tutoriales de KTutorial se especifican en código " +"fuente, ya sea C++ o un lenguaje de script." + +#. Tag: para +#: using.docbook:35 +#, no-c-format +msgid "" +"C++ tutorials must be embedded in the application source code itself, and " +"they have to be compiled with it when the application is compiled." +msgstr "" +"Los tutoriales en C++ deben incluirse en el código fuente de la aplicación " +"misma, y tienen que ser compilados con ella cuando se compila la propia " +"aplicación." + +#. Tag: para +#: using.docbook:37 +#, no-c-format +msgid "" +"On the other hand, scripted tutorials are external data to the application. " +"When an application that supports KTutorial starts, it looks for scripted " +"tutorials in some specific directories and loads those found. If you add new " +"scripted tutorials to the directories, the next time the application starts " +"they will be available. You don't have to compile again the application, not " +"even to reinstall it." +msgstr "" +"En cambio, los tutoriales en script son datos externos a la aplicación. " +"Cuando arranca una aplicación que soporta KTutorial, busca tutoriales en " +"script en unos directorios concretos y carga los que encuentre. Si añades " +"nuevos tutoriales en script a esos directorios, dichos tutoriales estarán " +"disponibles la próxima vez que arranques la aplicación. No tienes que " +"compilar la aplicación de nuevo, ni siquiera reinstalarla." + +#. Tag: para +#: using.docbook:39 +#, no-c-format +msgid "" +"Scripted tutorials are looked for in the <filename class=\"directory" +"\">tutorials/</filename> subdirectory of the application data directory. The " +"application data directory is <filename class=\"directory\">KDE_PREFIX/share/" +"apps/applicationName/</filename>. Special cases aside, the " +"<emphasis>KDE_PREFIX</emphasis> can be the &kde; installation prefix " +"(usually <filename class=\"directory\">/usr/</filename>) or the user &kde; " +"configuration directory (<filename class=\"directory\">/home/userName/.kde4/" +"</filename>)." +msgstr "" +"Los tutoriales en script se buscan en el subdirectorio <filename class=" +"\"directory\">tutorials/</filename> del directorio de datos de la " +"aplicación. El directorio de datos de la aplicación es <filename class=" +"\"directory\">KDE_PREFIX/share/apps/applicationName/</filename>. Dejando a " +"un lado las situaciones especiales, <emphasis>KDE_PREFIX</emphasis> puede " +"ser el prefijo de instalación de &kde; (generalmente <filename class=" +"\"directory\">/usr/</filename>) o el directorio de configuración de &kde; " +"del usuario (<filename class=\"directory\">/home/userName/.kde4/</filename>)." + +#. Tag: para +#: using.docbook:41 +#, no-c-format +msgid "" +"When the scripted tutorial is part of an application (it is installed with " +"the rest of the application data when the application is installed), the " +"strings in the scripted tutorial can be extracted to be localized before the " +"installation like any other string in the C++ code, as explained in " +"KTutorial documentation. Scripted tutorials that are added after the " +"application was installed, however, can not be localized, as KTutorial uses " +"the same translation file as the rest of the application where it is used." +msgstr "" +"Cuando el tutorial en script es parte de una aplicación (se instala junto al " +"resto de la aplicación cuando se instala la aplicación), las cadenas " +"contenidas en el tutorial pueden extraerse para ser localizadas antes de la " +"instalación como cualquier otra cadena en el código C++, como se explica en " +"la documentación de KTutorial. Los tutoriales en script que se añaden una " +"vez la aplicación fue instalada, sin embargo, no pueden localizarse, ya que " +"KTutorial utiliza el mismo archivo de traducción que el resto de la " +"aplicación en que se utiliza." + +#. Tag: para +#: using.docbook:43 +#, no-c-format +msgid "" +"As you may have guessed already, &ktutorial-editor; creates scripted " +"tutorials. Right now, only Javascript is supported, as &kde; libraries offer " +"out of the box support for Javascript scripts. Python or Ruby, on the other " +"hand, require some specific packages to be installed in the system." +msgstr "" +"Como puede que ya te hayas imaginado, &ktutorial-editor; crea tutoriales en " +"script. Por ahora, sólo hay soporte para Javascript, ya que las bibliotecas " +"de &kde; ofrecen soporte de serie para scripts en Javascript. Python o Ruby, " +"en cambio, necesitan que ciertos paquetes concretos estén instalados en el " +"sistema." + +#. Tag: title +#: using.docbook:47 +#, no-c-format +msgid "Main Window" +msgstr "Ventana principal" + +#. Tag: para +#: using.docbook:49 +#, no-c-format +msgid "" +"&ktutorial-editor; main window shows the tutorial being worked on, and " +"provides actions to modify it." +msgstr "" +"La ventana principal de &ktutorial-editor; muestra el tutorial en el que se " +"está trabajando, y proporciona acciones para modificarlo." + +#. Tag: para +#: using.docbook:51 +#, no-c-format +msgid "" +"A tutorial can be seen as a hierarchical structure: a tutorial contains " +"several steps, each step may contain several reactions, and each reaction " +"may contain a composed condition. Also, tutorial, step and reactions contain " +"other properties, like the name in a tutorial or the response code in a " +"reaction, that can be seen as children of their element. With all this, a " +"tutorial is shown as a tree in the main window." +msgstr "" +"Un tutorial puede verse como una estructura jerárquica: un tutorial contiene " +"varios pasos, cada paso puede contener varias reacciones, y cada reacción " +"puede contener una condición compuesta. Además, los tutoriales, pasos y " +"reacciones contienen otras propiedades, como el nombre del tutorial o el " +"código de respuesta de la reacción, que pueden verse como hijos del elemento " +"al que pertenecen. Con todo esto, un tutorial se muestra en forma de árbol " +"en la ventana principal." + +#. Tag: para +#: using.docbook:53 +#, no-c-format +msgid "" +"The tree only shows properties already set. For example, if there is no " +"custom setup code for a step, no item is shown, not even to say that there " +"is no setup code. The exception to this behavior happens when a property is " +"mandatory, for example, the id of a step. In that case, if the property is " +"not set, an item with a warning is shown." +msgstr "" +"El árbol sólo muestra las propiedades que ya están establecidas. Por " +"ejemplo, si no hay código propio de inicialización para un paso, no se " +"muestra ninguna entrada para él, ni siquiera para indicar que no hay código " +"de inicialización. La excepción que confirma la regla son las propiedades " +"obligatorias, por ejemplo, el identificador de un paso. En ese caso, si la " +"propiedad no está establecida, se muestra una entrada con una advertencia." + +#. Tag: para +#: using.docbook:55 +#, no-c-format +msgid "" +"The actions to modify the tutorial and its elements can be always accessed " +"from the <guimenu>Edit</guimenu> menu. Most actions will open a edition " +"dialog to edit the desired element, which means that, in some cases, you " +"have to select an element before being able to use an action. For example, " +"to use <action>Set reaction data</action>, you first have to select the " +"reaction to edit in the tutorial. Otherwise, the action will be disabled and " +"it could not be executed (which is logical, as it will not know which " +"reaction to edit)." +msgstr "" +"Para acceder a las acciones que modifican el tutorial y sus elementos puede " +"usarse siempre el menu <guimenu>Edit</guimenu>. La mayoría de las acciones " +"abrirán un diálogo de edición para el elemento deseado, lo que implica que, " +"en algunos casos, tendrás que seleccionar un elemento antes de poder " +"utilizar la acción. Por ejemplo, para utilizar <action>Establecer datos de " +"la reacción</action> antes tendrás que haber seleccionado la reacción a " +"editar en el tutorial. De lo contrario, la acción estará desactivada y no " +"podrá ejecutarse (lo que es lógico, ya que no sabría qué reacción editar)." + +#. Tag: para +#: using.docbook:57 +#, no-c-format +msgid "" +"As well as being shown in the <guimenu>Edit</guimenu> menu, the actions to " +"edit a tutorial, a step and a reaction are shown in three panels provided " +"for convenience. The panels can be shown or hidden from <guimenu>View</" +"guimenu> menu, and can be docked to the top, bottom, right or left side of " +"the main window. If desired, they can also be dragged out of the window to " +"make them floating panels." +msgstr "" +"Además de mostrarse en el menú <guimenu>Edit</guimenu>, por comodidad las " +"acciones para editar un tutorial, un paso y una reacción se muestran en tres " +"paneles. Los paneles pueden mostrarse u ocultarse desde el menú " +"<guimenu>Ver</guimenu>, y pueden acoplarse a la parte superior, inferior, " +"derecha o izquierda de la ventana principal. Si se desea, pueden arrastrarse " +"fuera de la ventana para convertirlos en paneles flotantes." + +#. Tag: screeninfo +#: using.docbook:60 +#, no-c-format +msgid "The main window of &ktutorial-editor; with a tutorial being worked on" +msgstr "" +"La ventana principal de &ktutorial-editor; con un tutorial en el que se está " +"trabajando" + +#. Tag: phrase +#: using.docbook:66 +#, no-c-format +msgid "&ktutorial-editor; Main Window" +msgstr "Ventana principal de &ktutorial-editor;" + +#. Tag: title +#: using.docbook:73 +#, no-c-format +msgid "Edition dialogs" +msgstr "Diálogos de edición" + +#. Tag: para +#: using.docbook:75 +#, no-c-format +msgid "" +"There are several edition dialogs, each one to set some property or " +"properties of an element." +msgstr "" +"Hay varios diálogos de edición, sirviendo cada uno para establecer una " +"propiedad o varias propiedades de un elemento." + +#. Tag: title +#: using.docbook:78 +#, no-c-format +msgid "Tutorial edition" +msgstr "Edición de tutoriales" + +#. Tag: para +#: using.docbook:80 +#, no-c-format +msgid "" +"The tutorial information dialog is used to set the name and description of a " +"tutorial. The name and description are mandatory properties, as through the " +"name the user can identify a tutorial and with the description he can know " +"the purpose of the tutorial." +msgstr "" +"El diálogo de información del tutorial se utiliza para establecer el nombre " +"y la descripción de un tutorial. El nombre y la descripción son propiedades " +"obligatorias, ya que mediante el nombre el usuario puede identificar un " +"tutorial y con la descripción puede saber de qué va el tutorial." + +#. Tag: screeninfo +#: using.docbook:83 +#, no-c-format +msgid "The dialog to set the name and description of a tutorial" +msgstr "El diálogo para establecer el nombre y la descripción de un tutorial" + +#. Tag: phrase +#: using.docbook:89 +#, no-c-format +msgid "Tutorial information edition dialog" +msgstr "Diálogo de edición de la información de un tutorial" + +#. Tag: para +#: using.docbook:94 +#, no-c-format +msgid "" +"The license text dialog is used to set a license for the tutorial, for " +"example, if the exported scripted tutorial is going to be distributed with " +"its application. When the tutorial is exported, the license text is " +"automatically wrapped in comments appropriate for the script language. For " +"example, the following license text: <programlisting>The license text, which " +"should be\n" +"wrapped\n" +"</programlisting> is exported to Javascript as:" +msgstr "" +"El diálogo del texto de licencia se utiliza para establecer la licencia del " +"tutorial, por ejemplo, si el tutorial en script exportado va a ser " +"distribuido con su aplicación. Cuando se exporta el tutorial, el texto de " +"licencia se enmarca automáticamente en comentarios apropiados para el " +"lenguaje de script. Por ejemplo, el siguiente texto de licencia: " +"<programlisting>El texto de licencia, que debería\n" +"enmarcarse\n" +"</programlisting> se exporta en Javascript como:" + +#. Tag: programlisting +#: using.docbook:96 +#, no-c-format +msgid "" +"/*****************************************\n" +" * The license text, which should be *\n" +" * wrapped *\n" +" *****************************************/" +msgstr "" +"/*****************************************\n" +" * El texto de licencia, que debería *\n" +" * enmarcarse *\n" +" *****************************************/" + +#. Tag: para +#: using.docbook:99 +#, no-c-format +msgid "" +"The setup and tear down code dialogs just provide a text editor to write the " +"custom code to be executed when the tutorial starts or finishes. Note that " +"you have to provide just the body of the function, as the signature is " +"automatically written when exported. For example, the following setup code: " +"<programlisting>alert(\"Hello world!\");</programlisting> is exported to " +"Javascript as:" +msgstr "" +"Los diálogos para el código de inicialización y finalización simplemente " +"proporcionan un editor de texto en el que escribir el código propio que será " +"ejecutado cuando el tutorial comienza o termina. Ten en cuenta que sólo " +"tienes que escribir el cuerpo de la función, ya que la signatura se escribe " +"automáticamente al exportar. Por ejemplo, el siguiente código de " +"inicialización: <programlisting>alert(\"¡Hola mundo!\");</programlisting> se " +"exporta en Javascript como:" + +#. Tag: programlisting +#: using.docbook:101 +#, no-c-format +msgid "" +"function tutorialSetup(tutorial) {\n" +" alert(\"Hello world!\");\n" +"}" +msgstr "" +"function tutorialSetup(tutorial) {\n" +" alert(\"¡Hola mundo!\");\n" +"}" + +#. Tag: title +#: using.docbook:106 +#, no-c-format +msgid "Step edition" +msgstr "Edición de pasos" + +#. Tag: para +#: using.docbook:108 +#, no-c-format +msgid "" +"The step data dialog is used to set the id and text of a step. The id and " +"text are mandatory properties, as the id is used by other steps to change to " +"this step, and the text is shown to the user to explain him what must be " +"done. Thus, the id must be unique for every step in the same tutorial." +msgstr "" +"El diálogo de datos del paso se utiliza para establecer el identificador y " +"el texto de un paso. El identificador y el texto son propiedades " +"obligatorias, ya que el identificador lo utilizan otros pasos para cambiar a " +"este paso, y el texto se muestra al usuario para explicarle qué se debe " +"hacer. Por tanto, el identificador debe ser único para cada paso que " +"pertenezca al mismo tutorial." + +#. Tag: para +#: using.docbook:109 +#, no-c-format +msgid "" +"The step data dialog is also shown when a new step is added. If the dialog " +"is accepted, the step is added. If the dialog is cancelled, the step is not " +"added." +msgstr "" +"El diálogo de datos del paso se muestra también cuando se añade un nuevo " +"paso. Si se acepta el diálogo, el paso se añade. Si se cancela el diálogo, " +"el paso no se añade." + +#. Tag: para +#: using.docbook:110 +#, no-c-format +msgid "" +"Also note that, in every tutorial, there must be one step with id " +"<emphasis>start</emphasis>, so KTutorial knows where to start the tutorial." +msgstr "" +"Ten en cuenta también que, en todos los tutoriales, debe haber un paso con " +"el identificador <emphasis>start</emphasis>, para que KTutorial sepa dónde " +"empieza el tutorial." + +#. Tag: screeninfo +#: using.docbook:113 +#, no-c-format +msgid "The dialog to set the id and text of a step" +msgstr "El diálogo para establecer el identificador y el texto de un paso" + +#. Tag: phrase +#: using.docbook:119 +#, no-c-format +msgid "Step data edition dialog" +msgstr "Diálogo de edición de los datos de un paso" + +#. Tag: para +#: using.docbook:124 +#, no-c-format +msgid "" +"The setup and tear down code dialogs behave like the tutorial ones. The only " +"difference is that the code is executed when the tutorial changes to the " +"step or when the tutorial changes from this step to another one." +msgstr "" +"Los diálogos del código de inicialización y finalización funcionan como los " +"del tutorial. La única diferencia es que el código se ejecuta cuando el " +"tutorial cambia a este paso o cuando el tutorial cambia desde este paso a " +"otro." + +#. Tag: para +#: using.docbook:125 +#, no-c-format +msgid "" +"Also note that the exported scripted tutorial creates all the reactions in " +"the setup method of a step. The custom setup code is added after that code." +msgstr "" +"Ten en cuenta también que el tutorial en script exportado crea todas las " +"reacciones en el método de inicialización del paso. El código propio de " +"inicialización se añade tras ese código." + +#. Tag: title +#: using.docbook:129 +#, no-c-format +msgid "Reaction edition" +msgstr "Edición de reacciones" + +#. Tag: para +#: using.docbook:131 +#, no-c-format +msgid "" +"The reaction dialog is used to set the trigger and response of a reaction. " +"The trigger and response are mandatory properties, as they define how the " +"reaction behaves." +msgstr "" +"El diálogo de reacciones se utiliza para establecer el activador y la " +"respuesta de una reacción. El activador y la respuesta son propiedades " +"obligatorias, ya que definen el funcionamiento de la reacción." + +#. Tag: para +#: using.docbook:132 +#, no-c-format +msgid "" +"The trigger can be either an option selected or a condition met, but not " +"both. If the trigger type is the option, its name will be shown to the user " +"in the step and the response will be executed when the user selects it. If " +"the type is the condition, the response will be executed when the condition " +"is met." +msgstr "" +"El activador puede ser tanto una opción seleccionada o una condición " +"cumplida, pero no ambas. Si el tipo de la reacción es la opción, su nombre " +"se mostrará al usuario en el paso y la respuesta se ejecutará cuando el " +"usuario la seleccione. Si el tipo es la condición, la respuesta se ejecutará " +"cuando se cumpla la condición." + +#. Tag: para +#: using.docbook:133 +#, no-c-format +msgid "" +"Likely, the response can be changing to another step or executing some " +"custom code, but not both. If the response type is the custom code, it will " +"be used as the body of a function called when the reaction is triggered. " +"Again, the signature of the function is automatically provided and you have " +"to set only the body." +msgstr "" +"De manera similar, la respuesta puede ser cambiar a otro paso o ejecutar " +"cierto código propio, pero no ambas. Si el tipo de la respuesta es el código " +"propio, se utilizará como el cuerpo de la función llamada cuando se active " +"la reacción. De nuevo, la signatura de la función se añade automáticamente y " +"sólo tienes que establecer el cuerpo." + +#. Tag: screeninfo +#: using.docbook:136 +#, no-c-format +msgid "The dialog to set the trigger and response of a reaction" +msgstr "El diálogo para establecer el activador y la respuesta de una reacción" + +#. Tag: phrase +#: using.docbook:142 +#, no-c-format +msgid "Set reaction data edition dialog" +msgstr "Diálogo de edición para establecer los datos de una reacción" + +#. Tag: title +#: using.docbook:148 +#, no-c-format +msgid "Condition edition" +msgstr "Edición de condiciones" + +#. Tag: para +#: using.docbook:150 +#, no-c-format +msgid "" +"The condition that acts as a trigger of a reaction can be a simple condition " +"or a composed condition. Simple conditions wait for something to happen, " +"like a signal emitted by an object. Composed conditions wait for its child " +"conditions. For example, waiting until a signal is emitted by an object or " +"an event is received in another object, whatever comes first." +msgstr "" +"La condición que actúa como activador de una reacción puede ser una " +"condición simple o compuesta. Las condiciones simples esperan a que ocurra " +"algo, como una señal emitida por un objeto. Las condiciones compuestas " +"esperan por sus condiciones hijas. Por ejemplo, esperar hasta que un objeto " +"emita una señal o hasta que otro objeto reciba un evento, lo que ocurra " +"primero." + +#. Tag: para +#: using.docbook:151 +#, no-c-format +msgid "" +"Due to this, conditions are represented in a tree, and it also affects how " +"they are edited." +msgstr "" +"Debido a esto, las condiciones se representan como un árbol, y también a la " +"manera en que son editadas." + +#. Tag: para +#: using.docbook:152 +#, no-c-format +msgid "" +"A condition can be added as the root condition when there are no other " +"conditions set, or as a child of the selected composed condition, but not " +"when a simple condition is selected. When a new condition is added, you must " +"select its type. Note that the type of the condition can not be changed " +"later, you will have to remove the condition and set a new one." +msgstr "" +"Una condición puede añadirse como la condición raíz cuando no hay ninguna " +"otra condición establecida, o como un hijo de la condición compuesta " +"seleccionada, pero no cuando una condición simple está seleccionada. Cuando " +"se añade una nueva condición, debes seleccionar su tipo. Ten en cuenta que " +"el tipo de la condición no puede cambiarse luego, tendrás que eliminar la " +"condición y establecer una nueva." + +#. Tag: screeninfo +#: using.docbook:155 +#, no-c-format +msgid "The dialog to select the type of the new condition to add" +msgstr "El diálogo para seleccionar el tipo de la nueva condición a añadir." + +#. Tag: phrase +#: using.docbook:161 +#, no-c-format +msgid "New condition dialog" +msgstr "Diálogo de nueva condición" + +#. Tag: para +#: using.docbook:166 +#, no-c-format +msgid "" +"Only simple conditions (waiting for an event and waiting for a signal) can " +"be edited, showing specific dialogs for it. Composed conditions only group " +"other conditions, so they don't have properties to be edited." +msgstr "" +"Sólo las condiciones simples (esperar por un evento y esperar por una señal) " +"pueden editarse, lo que muestra diálogos específicos para ello. Las " +"condiciones compuestas sólo agrupan otras condiciones, por lo que no tienen " +"propiedades que editar." + +#. Tag: para +#: using.docbook:167 +#, no-c-format +msgid "" +"Any condition can be removed from its parent composed condition, or from the " +"reaction if it is the root condition." +msgstr "" +"Cualquier condición puede eliminarse de la condición compuesta que la " +"contiene, o de la reacción si es la condición raíz." + +#. Tag: para +#: using.docbook:169 +#, no-c-format +msgid "" +"There is a special type of condition that verifies that its negated " +"condition wasn't met which purpose is to be used only as a child of a " +"composed condition that waits until all its child conditions were met. The " +"idea is that, when the negated condition wasn't met, the special condition " +"is met. When the negated condition is met, the special condition is no " +"longer met. It can be used, for example, to make a reaction wait for the " +"user to write something in a text line, provided he has not pressed a button " +"before. Note that a fallback reaction should be added in cases like this one." +msgstr "" +"Hay un tipo especial de condición que verifica que su condición negada no se " +"cumplió cuyo propósito es ser usada sólo como hija de una condición " +"compuesta que espera hasta que todas sus condiciones hijas se cumplieron. La " +"idea es que, cuando la condición negada no se cumplió, la condición especial " +"sí está cumplida. Cuando se cumple la condición negada, la condición " +"especial deja de estar cumplida. Puede utilizarse, por ejemplo, para hacer " +"que una reacción espere a que el usuario escriba algo en una línea de texto, " +"pero sólo si no presionó un botón antes. Ten en cuenta que en casos como " +"éste debe añadirse una reacción que pueda cumplirse si la otra no." + +#. Tag: title +#: using.docbook:175 +#, no-c-format +msgid "Exporting the tutorial" +msgstr "Exportación del tutorial" + +#. Tag: para +#: using.docbook:177 +#, no-c-format +msgid "" +"Once you have finished designing the tutorial you can export it to a " +"scripted tutorial. To do this, just use <menuchoice><guimenu>File</" +"guimenu><guimenuitem>Export...</guimenuitem></menuchoice>, select where to " +"save the file and you are done. Remember that you have to export the file to " +"some specific directory to be found by KTutorial, as explained in <xref " +"linkend=\"understanding-ktutorial\"/>." +msgstr "" +"Una vez que hayas terminado de diseñar el tutorial puedes exportarlo a un " +"tutorial en script. Para hacer esto, simplemente utiliza " +"<menuchoice><guimenu>Archivo</guimenu><guimenuitem>Exportar...</" +"guimenuitem></menuchoice>, selecciona dónde salvar el archivo y listo. " +"Recuerda que tienes que exportar el archivo a unos directorios concretos " +"para que pueda encontrarlo KTutorial, como se explica en <xref linkend=" +"\"understanding-ktutorial\"/>." + +#. Tag: para +#: using.docbook:178 +#, no-c-format +msgid "" +"The export dialog supports exporting to remote directories (via " +"<acronym>FTP</acronym>, <acronym>SSH</acronym>, etc), although it will be " +"very strange that you need to use that." +msgstr "" +"El diálogo de exportación tiene soporte para exportar a directorios remotos " +"(mediante <acronym>FTP</acronym>, <acronym>SSH</acronym>, etcétera), aunque " +"sería muy extraño que necesitases hacer eso." + +#. Tag: title +#: using.docbook:182 +#, no-c-format +msgid "Command Line Options" +msgstr "Opciones de la línea de órdenes" + +#. Tag: para +#: using.docbook:184 +#, no-c-format +msgid "" +"Though &ktutorial-editor; will be usually started from the &kde; program " +"menu, or a desktop icon, it can also be opened from the command line prompt " +"of a terminal window. There are a few options that are available when doing " +"this." +msgstr "" +"Aunque &ktutorial-editor; se arrancará generalmente desde el menú de " +"programas de &kde;, o desde un icono de escritorio, puede abrirse también " +"desde la línea de órdenes de una terminal. Hay unas pocas opciones " +"disponibles en este caso." + +#. Tag: title +#: using.docbook:187 +#, no-c-format +msgid "Default &kde; Command Line Options" +msgstr "Opciones por defecto de &kde; de la línea de órdenes" + +#. Tag: para +#: using.docbook:189 +#, no-c-format +msgid "The following command line help options are available:" +msgstr "" +"Las siguientes opciones de ayuda en la línea de órdenes están disponibles:" + +#. Tag: command +#: using.docbook:194 +#, no-c-format +msgid "ktutorial-editor <option>--help</option>" +msgstr "ktutorial-editor <option>--help</option>" + +#. Tag: para +#: using.docbook:197 +#, no-c-format +msgid "This lists the most basic options available at the command line." +msgstr "Lista las opciones más básicas disponibles en la línea de órdenes." + +#. Tag: command +#: using.docbook:203 +#, no-c-format +msgid "ktutorial-editor <option>--help-qt</option>" +msgstr "ktutorial-editor <option>--help-qt</option>" + +#. Tag: para +#: using.docbook:206 +#, no-c-format +msgid "" +"This lists the options available for changing the way &ktutorial-editor; " +"interacts with &Qt;." +msgstr "" +"Lista las opciones disponibles para cambiar la forma en que &ktutorial-" +"editor; interacciona con &Qt;." + +#. Tag: command +#: using.docbook:212 +#, no-c-format +msgid "ktutorial-editor <option>--help-kde</option>" +msgstr "ktutorial-editor <option>--help-kde</option>" + +#. Tag: para +#: using.docbook:215 +#, no-c-format +msgid "" +"This lists the options available for changing the way &ktutorial-editor; " +"interacts with &kde;." +msgstr "" +"Lista las opciones disponibles para cambiar la forma en que &ktutorial-" +"editor; interacciona con &kde;." + +#. Tag: command +#: using.docbook:221 +#, no-c-format +msgid "ktutorial-editor <option>--help-all</option>" +msgstr "ktutorial-editor <option>--help-all</option>" + +#. Tag: para +#: using.docbook:224 +#, no-c-format +msgid "This lists all of the command line options." +msgstr "Lista todas las opciones de la línea de órdenes." + +#. Tag: command +#: using.docbook:230 +#, no-c-format +msgid "ktutorial-editor <option>--author</option>" +msgstr "ktutorial-editor <option>--author</option>" + +#. Tag: para +#: using.docbook:233 +#, no-c-format +msgid "Lists &ktutorial-editor;'s author in the terminal window." +msgstr "Lista los autores de &ktutorial-editor; en la terminal." + +#. Tag: command +#: using.docbook:239 +#, no-c-format +msgid "ktutorial-editor <option>--version</option>" +msgstr "ktutorial-editor <option>--version</option>" + +#. Tag: para +#: using.docbook:242 +#, no-c-format +msgid "" +"Lists version information for &Qt;, &kde;, and &ktutorial-editor;. Also " +"available through <command>ktutorial-editor <option>-v</option></command>." +msgstr "" +"Lista la información de versión de &Qt;, &kde;, y &ktutorial-editor;. " +"También disponible mediante <command>ktutorial-editor <option>-v</option></" +"command>." + +#. Tag: command +#: using.docbook:248 +#, no-c-format +msgid "ktutorial-editor <option>--license</option>" +msgstr "ktutorial-editor <option>--license</option>" + +#. Tag: para +#: using.docbook:251 +#, no-c-format +msgid "Shows &ktutorial-editor;'s license text in the terminal window." +msgstr "Muestra el texto de la licencia de &ktutorial-editor; en la terminal." + +#. Tag: title +#: commands.docbook:8 +#, no-c-format +msgid "Command Reference" +msgstr "Referencia de órdenes" + +#. Tag: title +#: commands.docbook:11 +#, no-c-format +msgid "The main &ktutorial-editor; window" +msgstr "La ventana principal de &ktutorial-editor;" + +#. Tag: title +#: commands.docbook:14 +#, no-c-format +msgid "The <guimenu>File</guimenu> Menu" +msgstr "El menú <guimenu>Archivo</guimenu>" + +#. Tag: menuchoice +#: commands.docbook:19 +#, no-c-format +msgid "<guimenu>File</guimenu> <guimenuitem>Export...</guimenuitem>" +msgstr "<guimenu>Archivo</guimenu> <guimenuitem>Exportar...</guimenuitem>" + +#. Tag: action +#: commands.docbook:26 +#, no-c-format +msgid "Exports the tutorial to a script." +msgstr "Exporta el tutorial a un script." + +#. Tag: menuchoice +#: commands.docbook:32 +#, no-c-format +msgid "" +"<shortcut> <keycombo action=\"simul\">&Ctrl;<keycap>Q</keycap></keycombo> </" +"shortcut> <guimenu>File</guimenu> <guimenuitem>Quit</guimenuitem>" +msgstr "" +"<shortcut> <keycombo action=\"simul\">&Ctrl;<keycap>Q</keycap></keycombo> </" +"shortcut> <guimenu>Archivo</guimenu> <guimenuitem>Salir</guimenuitem>" + +#. Tag: action +#: commands.docbook:42 +#, no-c-format +msgid "Quits &ktutorial-editor;." +msgstr "Sale de &ktutorial-editor;." + +#. Tag: title +#: commands.docbook:51 +#, no-c-format +msgid "The <guimenu>Edit</guimenu> Menu" +msgstr "El menú <guimenu>Editar</guimenu>" + +#. Tag: menuchoice +#: commands.docbook:56 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Tutorial</guimenu> <guimenuitem>Set " +"information...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Tutorial</guimenu> " +"<guimenuitem>Establecer información...</guimenuitem>" + +#. Tag: action +#: commands.docbook:64 +#, no-c-format +msgid "Opens the dialog to set the name and description of the tutorial." +msgstr "" +"Abre el diálogo para establecer el nombre y la descripción del tutorial." + +#. Tag: menuchoice +#: commands.docbook:70 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Tutorial</guimenu> <guimenuitem>Set " +"license...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Tutorial</guimenu> " +"<guimenuitem>Establecer licencia...</guimenuitem>" + +#. Tag: action +#: commands.docbook:78 +#, no-c-format +msgid "Opens the dialog to set the license text of the tutorial." +msgstr "Abre el diálogo para establecer el texto de la licencia del tutorial." + +#. Tag: menuchoice +#: commands.docbook:84 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Tutorial</guimenu> <guimenuitem>Set setup " +"code...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Tutorial</guimenu> " +"<guimenuitem>Establecer código de inicialización...</guimenuitem>" + +#. Tag: action +#: commands.docbook:92 +#, no-c-format +msgid "" +"Opens the dialog to set the custom code to be executed when the tutorial " +"starts." +msgstr "" +"Abre el diálogo para establecer el código propio que se ejecutará cuando " +"comience el tutorial." + +#. Tag: menuchoice +#: commands.docbook:98 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Tutorial</guimenu> <guimenuitem>Set tear " +"down code...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Tutorial</guimenu> " +"<guimenuitem>Establecer código de finalización...</guimenuitem>" + +#. Tag: action +#: commands.docbook:106 +#, no-c-format +msgid "" +"Opens the dialog to set the custom code to be executed when the tutorial " +"finishes." +msgstr "" +"Abre el diálogo para establecer el código propio que se ejecutará cuando " +"termine el tutorial." + +#. Tag: menuchoice +#: commands.docbook:112 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Step</guimenu> <guimenuitem>Add step...</" +"guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Paso</guimenu> <guimenuitem>Añadir paso..." +"</guimenuitem>" + +#. Tag: action +#: commands.docbook:120 +#, no-c-format +msgid "Opens the dialog to add a new step to the tutorial." +msgstr "Abre el diálogo para añadir un nuevo paso al tutorial." + +#. Tag: menuchoice +#: commands.docbook:126 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Step</guimenu> <guimenuitem>Set data...</" +"guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Paso</guimenu> <guimenuitem>Establecer " +"datos...</guimenuitem>" + +#. Tag: action +#: commands.docbook:134 +#, no-c-format +msgid "" +"Opens the dialog to set the name and text of the currently selected step." +msgstr "" +"Abre el diálogo para establecer el nombre y el texto del paso seleccionado " +"actualmente." + +#. Tag: menuchoice +#: commands.docbook:140 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Step</guimenu> <guimenuitem>Set setup " +"code...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Paso</guimenu> <guimenuitem>Establecer " +"código de inicialización...</guimenuitem>" + +#. Tag: action +#: commands.docbook:148 +#, no-c-format +msgid "" +"Opens the dialog to set the custom code to be executed when the tutorial " +"passes to the currently selected step." +msgstr "" +"Abre el diálogo para establecer el código propio que se ejecutará cuando el " +"tutorial cambie al paso seleccionado actualmente." + +#. Tag: menuchoice +#: commands.docbook:154 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Step</guimenu> <guimenuitem>Set tear down " +"code...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Paso</guimenu> <guimenuitem>Establecer " +"código de finalización...</guimenuitem>" + +#. Tag: action +#: commands.docbook:162 +#, no-c-format +msgid "" +"Opens the dialog to set the custom code to be executed when the tutorial " +"changes from the currently selected step to another step." +msgstr "" +"Abre el diálogo para establecer el código propio que se ejecutará cuando el " +"tutorial cambie del paso seleccionado actualmente a otro paso." + +#. Tag: menuchoice +#: commands.docbook:168 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Step</guimenu> <guimenuitem>Remove step</" +"guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Paso</guimenu> <guimenuitem>Eliminar " +"paso</guimenuitem>" + +#. Tag: action +#: commands.docbook:176 +#, no-c-format +msgid "Removes the currently selected step from the tutorial." +msgstr "Elimina del tutorial el paso seleccionado actualmente." + +#. Tag: menuchoice +#: commands.docbook:182 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Reaction</guimenu> <guimenuitem>Add " +"reaction...</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Reacción</guimenu> <guimenuitem>Añadir " +"reacción...</guimenuitem>" + +#. Tag: action +#: commands.docbook:190 +#, no-c-format +msgid "Opens the dialog to add a new reaction to the selected step." +msgstr "Abre el diálogo para añadir una nueva reacción al paso seleccionado." + +#. Tag: menuchoice +#: commands.docbook:196 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Reaction</guimenu> <guimenuitem>Set data..." +"</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Reacción</guimenu> " +"<guimenuitem>Establecer datos...</guimenuitem>" + +#. Tag: action +#: commands.docbook:204 +#, no-c-format +msgid "" +"Opens the dialog to set the trigger and response of the currently selected " +"reaction." +msgstr "" +"Abre el diálogo para establecer el activador y la respuesta de la reacción " +"seleccionada actualmente." + +#. Tag: menuchoice +#: commands.docbook:210 +#, no-c-format +msgid "" +"<guimenu>Edit</guimenu> <guimenu>Reaction</guimenu> <guimenuitem>Remove " +"reaction</guimenuitem>" +msgstr "" +"<guimenu>Editar</guimenu> <guimenu>Reacción</guimenu> <guimenuitem>Eliminar " +"reacción</guimenuitem>" + +#. Tag: action +#: commands.docbook:218 +#, no-c-format +msgid "Removes the currently selected reaction from its step." +msgstr "Elimina de su paso la reacción seleccionada actualmente." + +#. Tag: title +#: commands.docbook:227 +#, no-c-format +msgid "The <guimenu>View</guimenu> Menu" +msgstr "El menú <guimenu>Ver</guimenu>" + +#. Tag: menuchoice +#: commands.docbook:232 +#, no-c-format +msgid "" +"<guimenu>View</guimenu> <guimenuitem>Panels</guimenuitem> <guimenuitem>Edit " +"tutorial</guimenuitem>" +msgstr "" +"<guimenu>Ver</guimenu> <guimenuitem>Paneles</guimenuitem> " +"<guimenuitem>Editar tutorial</guimenuitem>" + +#. Tag: action +#: commands.docbook:240 +#, no-c-format +msgid "Shows or hides the panel with the shorcuts to tutorial edition actions." +msgstr "" +"Muestra u oculta el panel con los accesos directos a las acciones de edición " +"del tutorial." + +#. Tag: menuchoice +#: commands.docbook:246 +#, no-c-format +msgid "" +"<guimenu>View</guimenu> <guimenuitem>Panels</guimenuitem> <guimenuitem>Edit " +"step</guimenuitem>" +msgstr "" +"<guimenu>Ver</guimenu> <guimenuitem>Paneles</guimenuitem> " +"<guimenuitem>Editar paso</guimenuitem>" + +#. Tag: action +#: commands.docbook:254 +#, no-c-format +msgid "Shows or hides the panel with the shorcuts to step edition actions." +msgstr "" +"Muestra u oculta el panel con los accesos directos a las acciones de edición " +"de los pasos." + +#. Tag: menuchoice +#: commands.docbook:260 +#, no-c-format +msgid "" +"<guimenu>View</guimenu> <guimenuitem>Panels</guimenuitem> <guimenuitem>Edit " +"reaction</guimenuitem>" +msgstr "" +"<guimenu>Ver</guimenu> <guimenuitem>Paneles</guimenuitem> " +"<guimenuitem>Editar reacción</guimenuitem>" + +#. Tag: action +#: commands.docbook:268 +#, no-c-format +msgid "Shows or hides the panel with the shorcuts to reaction edition actions." +msgstr "" +"Muestra u oculta el panel con los accesos directos a las acciones de edición " +"de las reacciones." + +#. Tag: title +#: commands.docbook:277 +#, no-c-format +msgid "The <guimenu>Settings</guimenu> Menu" +msgstr "El menú <guimenu>Preferencias</guimenu>" + +#. Tag: menuchoice +#: commands.docbook:282 +#, no-c-format +msgid "<guimenu>Settings</guimenu> <guimenuitem>Show Toolbar</guimenuitem>" +msgstr "" +"<guimenu>Preferencias</guimenu> <guimenuitem>Mostrar la barra de " +"herramientas</guimenuitem>" + +#. Tag: action +#: commands.docbook:289 +#, no-c-format +msgid "Shows or hides the main toolbar." +msgstr "Muestra u oculta la barra de herramientas principal." + +#. Tag: menuchoice +#: commands.docbook:295 +#, no-c-format +msgid "<guimenu>Settings</guimenu> <guimenuitem>Show Statusbar</guimenuitem>" +msgstr "" +"<guimenu>Preferencias</guimenu> <guimenuitem>Mostrar barra de estado</" +"guimenuitem>" + +#. Tag: action +#: commands.docbook:302 +#, no-c-format +msgid "Shows or hides the statusbar." +msgstr "Muestra u oculta la barra de estado." + +#. Tag: menuchoice +#: commands.docbook:308 +#, no-c-format +msgid "" +"<guimenu>Settings</guimenu> <guimenuitem>Configure Shortcuts...</guimenuitem>" +msgstr "" +"<guimenu>Preferencias</guimenu> <guimenuitem>Configurar los accesos " +"rápidos...</guimenuitem>" + +#. Tag: action +#: commands.docbook:315 +#, no-c-format +msgid "Opens a configure dialog for binding keys to actions." +msgstr "Abre el diálogo de configuración para asociar teclas con acciones." + +#. Tag: menuchoice +#: commands.docbook:321 +#, no-c-format +msgid "" +"<guimenu>Settings</guimenu> <guimenuitem>Configure Toolbars...</guimenuitem>" +msgstr "" +"<guimenu>Preferencias</guimenu> <guimenuitem>Configurar las barras de " +"herramientas...</guimenuitem>" + +#. Tag: action +#: commands.docbook:328 +#, no-c-format +msgid "" +"Opens a configure dialog for selecting the actions to show in the toolbar." +msgstr "" +"Abre el diálogo de configuración para seleccionar las acciones a mostrar en " +"la barra de herramientas." + +#. Tag: title +#: commands.docbook:337 +#, no-c-format +msgid "The <guimenu>Help</guimenu> Menu" +msgstr "El menú <guimenu>Ayuda</guimenu>" + +#. Tag: sect2 +#: commands.docbook:337 +#, no-c-format +msgid "&help.menu.documentation;" +msgstr "&hel... [truncated message content] |