diff options
Diffstat (limited to 'sigmodr/SigmodrUI.cpp')
| -rw-r--r-- | sigmodr/SigmodrUI.cpp | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/sigmodr/SigmodrUI.cpp b/sigmodr/SigmodrUI.cpp new file mode 100644 index 00000000..59efb604 --- /dev/null +++ b/sigmodr/SigmodrUI.cpp @@ -0,0 +1,451 @@ +/* + * Copyright 2008 Ben Boeckel <MathStuf@gmail.com> + * + * 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/>. + */ + +// Header include +#include "SigmodrUI.h" + +// Sigmodr includes +#include "ObjectUI.h" +#include "SigmodrPreferences.h" +#include "SigmodTreeModel.h" + +// Sigmod includes +#include "../sigmod/Rules.h" +#include "../sigmod/Sigmod.h" + +// Qt includes +#include <QtCore/QString> +#include <QtGui/QCloseEvent> + +// KDE includes +#include <KAction> +#include <KActionCollection> +#include <KCmdLineArgs> +#include <KFileDialog> +#include <KIcon> +#include <KLocalizedString> +#include <KMenu> +#include <KMenuBar> +#include <KMessageBox> +#include <KRecentFilesAction> +#include <KShortcutsDialog> +#include <KStandardAction> +#include <KStandardDirs> +#include <KStatusBar> +#include <KTemporaryFile> +#include <KToolBar> +#include <KUrl> +#include <KXMLGUIFactory> +#include <KIO/NetAccess> +#include <KNS/Engine> + +Sigmodr::SigmodrUI::SigmodrUI(QWidget* parent) : + KXmlGuiWindow(parent), + m_config(KGlobal::config()->group("sigmodr")) +{ + setupUi(this); + setupActions(); + buttonApply->setIcon(KIcon("dialog-ok-apply")); + buttonReset->setIcon(KIcon("edit-undo")); + splitter->setSizes(QList<int>() << m_config.readEntry("treeWidth", 100) << m_config.readEntry("panelWidth", 100)); + connect(buttonApply, SIGNAL(clicked()), this, SLOT(update())); + KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); + if (args && args->count()) + { + for(int i = 0; i < args->count(); ++i) + openSigmod(args->url(i)); + args->clear(); + } + else if (m_config.readEntry("reloadOnStart", false)) + { + QStringList urls = m_config.readEntry("Opened Files", QStringList()); + foreach (QString url, urls) + openSigmod(KUrl(url)); + } + setAutoSaveSettings("MainWindow", true); +} + +Sigmodr::SigmodrUI::~SigmodrUI() +{ + m_config.config()->sync(); + closeAllSigmods(true); +} + +void Sigmodr::SigmodrUI::update() +{ + treeSigmod->update(treeSigmod->currentIndex()); +} + +void Sigmodr::SigmodrUI::closeEvent(QCloseEvent* event) +{ + KRecentFilesAction *recent = qobject_cast<KRecentFilesAction*>(actionCollection()->action(KStandardAction::name(KStandardAction::OpenRecent))); + recent->saveEntries(m_config.group("Recent Files")); + if (closeAllSigmods()) + event->accept(); + else + event->ignore(); +} + +void Sigmodr::SigmodrUI::setChangedTitle(const bool changed) +{ + setCaption(treeSigmod->description(treeSigmod->currentIndex()), changed); +} + +void Sigmodr::SigmodrUI::setDirty(const bool dirty) +{ + const Sigmod::Sigmod* sigmod = qobject_cast<const Sigmod::Sigmod*>(static_cast<Sigmod::Object*>(treeSigmod->currentIndex().internalPointer())->sigmod()); + treeSigmod->setDirty(sigmod, dirty); + actionCollection()->action("file_save")->setEnabled(dirty); +} + +void Sigmodr::SigmodrUI::newSigmod() +{ + treeSigmod->addSigmod(new Sigmod::Sigmod); +} + +void Sigmodr::SigmodrUI::openSigmod() +{ + KUrl::List urls = KFileDialog::getOpenUrls(KUrl("kfiledialog:///sigmod"), "*.smod|Sigmod files", this); + foreach (KUrl url, urls) + { + if (!url.isEmpty()) + openSigmod(url); + } +} + +bool Sigmodr::SigmodrUI::openSigmod(const KUrl& url) +{ + bool opened = false; + if (treeSigmod->isOpen(url)) + { + KMessageBox::error(this, "File is already opened", "Sigmod error"); + return false; + } + if (url.isLocalFile()) + opened = openSigmod(url.path()); + else + { + QString temp; + if (KIO::NetAccess::download(url, temp, this)) + { + opened = openSigmod(temp, true); + KIO::NetAccess::removeTempFile(temp); + } + else + KMessageBox::error(this, KIO::NetAccess::lastErrorString(), "KIO Error"); + } + if (opened) + qobject_cast<KRecentFilesAction*>(actionCollection()->action(KStandardAction::name(KStandardAction::OpenRecent)))->addUrl(url); + return opened; +} + +bool Sigmodr::SigmodrUI::openSigmod(const QString& path, const bool isRemote) +{ + QFile file(path); + if (file.open(QIODevice::ReadOnly)) + { + QDomDocument xml; + if (xml.setContent(&file)) + { + if (xml.doctype().name() == "Sigmod") + { + treeSigmod->addSigmod(new Sigmod::Sigmod(xml.documentElement()), isRemote ? KUrl() : KUrl(path)); + return true; + } + else + KMessageBox::error(this, "The file is not a Sigmod.", "Invalid Sigmod"); + } + else + KMessageBox::error(this, "The file is not a valid XML file.", "Invalid Sigmod"); + file.close(); + } + else + KMessageBox::error(this, QString("Cannot open file:\n%1").arg(path), "No such file"); + return false; +} + +void Sigmodr::SigmodrUI::saveSigmod() +{ + saveSigmod(treeSigmod->currentSigmod()); +} + +void Sigmodr::SigmodrUI::saveSigmod(const Sigmod::Sigmod* sigmod) +{ + const KUrl url = treeSigmod->url(sigmod); + if (url.isEmpty()) + saveAsSigmod(sigmod); + else + saveSigmod(sigmod, url); +} + +bool Sigmodr::SigmodrUI::saveSigmod(const Sigmod::Sigmod* sigmod, const KUrl& url) +{ + if (sigmod) + { + if (url.isLocalFile()) + { + QFile file(url.path()); + if (file.open(QIODevice::WriteOnly)) + { + file.write(Sigmod::Object::xml(sigmod).toByteArray()); + treeSigmod->setDirty(sigmod, false); + file.close(); + return true; + } + else + KMessageBox::error(this, "Error saving the Sigmod!", "Save error"); + } + else + { + KTemporaryFile temp; + if (temp.open()) + { + temp.write(Sigmod::Object::xml(sigmod).toByteArray()); + if (KIO::NetAccess::upload(temp.fileName(), url, this)) + { + treeSigmod->setDirty(sigmod, false); + return true; + } + else + KMessageBox::error(this, KIO::NetAccess::lastErrorString(), "KIO Error"); + } + else + KMessageBox::error(this, "Error saving the Sigmod!", "Save error"); + } + } + return false; +} + +void Sigmodr::SigmodrUI::saveAsSigmod() +{ + saveAsSigmod(treeSigmod->currentSigmod()); +} + +void Sigmodr::SigmodrUI::saveAsSigmod(const Sigmod::Sigmod* sigmod) +{ + if (sigmod) + { + KUrl url = KFileDialog::getSaveUrl(KUrl("kfiledialog:///sigmod"), "*.smod|Sigmod files", this, "Open Sigmod"); + if (!url.isEmpty()) + { + if (saveSigmod(sigmod, url)) + treeSigmod->setUrl(sigmod, url); + } + } +} + +void Sigmodr::SigmodrUI::downloadSigmod() +{ + KNS::Engine engine(this); + if (engine.init("sigmod.knsrc")) + engine.downloadDialogModal(); +} + +void Sigmodr::SigmodrUI::uploadSigmod() +{ + uploadSigmod(treeSigmod->currentSigmod()); +} + +void Sigmodr::SigmodrUI::uploadSigmod(const Sigmod::Sigmod* sigmod) +{ + KUrl url = treeSigmod->url(sigmod); + if (url == KUrl()) + { + KMessageBox::error(this, "The Sigmod has not been saved!", "Upload error"); + return; + } + if (!url.isLocalFile()) + { + KMessageBox::error(this, "The Sigmod is not local!", "Upload error"); + return; + } + KNS::Engine engine(this); + if (engine.init("sigmod.knsrc")) + { + if (!engine.uploadDialogModal(url.path())) + KMessageBox::error(this, "An error occured attempting to upload!", "Upload error"); + } +} + +void Sigmodr::SigmodrUI::closeSigmod() +{ + closeSigmod(treeSigmod->currentSigmod()); +} + +bool Sigmodr::SigmodrUI::closeSigmod(const Sigmod::Sigmod* sigmod, const bool force) +{ + if (sigmod) + { + if (treeSigmod->dirty(sigmod)) + { + int result; + if (force) + result = KMessageBox::questionYesNo(this, "You have unsaved changes, would you like to save them?", "Unsaved Sigmod"); + else + result = KMessageBox::questionYesNoCancel(this, "You have unsaved changes, would you like to save them?", "Unsaved Sigmod"); + switch (result) + { + case KMessageBox::Yes: + saveSigmod(sigmod); + case KMessageBox::No: + break; + case KMessageBox::Cancel: + return false; + } + } + treeSigmod->deleteSigmod(sigmod); + if (formPanel->widget()) + delete formPanel->takeWidget(); + } + return true; +} + +bool Sigmodr::SigmodrUI::closeAllSigmods(const bool force) +{ + QList<const Sigmod::Sigmod*> sigmods = treeSigmod->openedSigmods(); + if (sigmods.size()) + m_config.writeEntry("Opened Files", treeSigmod->urls()); + for (int i = 0; i < sigmods.size(); ) + { + if (closeSigmod(sigmods[i], force)) + sigmods.removeAt(i); + else + ++i; + } + if (!sigmods.size() || force) + close(); + return !sigmods.size(); +} + +void Sigmodr::SigmodrUI::copyObject() +{ + m_clipboard = treeSigmod->copy(treeSigmod->currentIndex()); +} + +void Sigmodr::SigmodrUI::pasteObject() +{ + treeSigmod->paste(treeSigmod->currentIndex(), m_clipboard); +} + +void Sigmodr::SigmodrUI::preferences() +{ + SigmodrPreferences* dialog = new SigmodrPreferences(this, m_config); + connect(dialog, SIGNAL(okClicked()), dialog, SLOT(save())); + dialog->exec(); +} + +void Sigmodr::SigmodrUI::toggleMenubar() +{ + if (menuBar()->isVisible()) + menuBar()->hide(); + else + menuBar()->show(); +} + +void Sigmodr::SigmodrUI::on_splitter_splitterMoved() +{ + m_config.writeEntry("treeWidth", splitter->sizes()[0]); + m_config.writeEntry("panelWidth", splitter->sizes()[1]); +} + +void Sigmodr::SigmodrUI::on_treeSigmod_clicked(const QModelIndex& index) +{ + if (!(treeSigmod->model()->flags(index) & Qt::ItemIsSelectable)) + return; + ObjectUI* widget = treeSigmod->editorWidget(index); + if (widget) + { + if (formPanel->widget() && boxButtons->isEnabled()) + { + switch (KMessageBox::questionYesNoCancel(this, "You have unsaved changes, would you like to save them?", QString("Unsaved %1").arg(qobject_cast<ObjectUI*>(formPanel->widget())->original()->className()))) + { + case KMessageBox::Yes: + qobject_cast<ObjectUI*>(formPanel->widget())->apply(); + break; + case KMessageBox::No: + qobject_cast<ObjectUI*>(formPanel->widget())->discard(); + break; + case KMessageBox::Cancel: + return; + } + } + boxButtons->setEnabled(false); + connect(widget, SIGNAL(changed(bool)), this, SLOT(setChangedTitle(bool))); + connect(widget, SIGNAL(changed(bool)), boxButtons, SLOT(setEnabled(bool))); + connect(buttonApply, SIGNAL(clicked()), widget, SLOT(apply())); + connect(buttonApply, SIGNAL(clicked()), treeSigmod, SLOT(setDirty())); + connect(buttonReset, SIGNAL(clicked()), widget, SLOT(discard())); + setChangedTitle(false); + formPanel->setWidget(widget); + formPanel->show(); + } +} + +void Sigmodr::SigmodrUI::on_treeSigmod_customContextMenuRequested(const QPoint& position) +{ + QModelIndex index = treeSigmod->indexAt(position); + KMenu* menu = treeSigmod->contextMenu(index); + if (menu) + { + QString type = treeSigmod->model()->data(index, BaseModel::TypeRole).toString(); + KAction* paste = new KAction("&Paste", this); + connect(paste, SIGNAL(triggered()), this, SLOT(pasteObject())); + menu->addSeparator(); + if (!type.isEmpty()) + { + menu->addAction("&Copy", this, SLOT(copyObject())); + paste->setEnabled(m_clipboard.doctype().name() == type); + } + menu->addAction(paste); + connect(menu, SIGNAL(triggered(QAction*)), treeSigmod, SLOT(setDirty())); + menu->popup(treeSigmod->mapToGlobal(position)); + } +} + +void Sigmodr::SigmodrUI::setupActions() +{ + KStandardAction::openNew(this, SLOT(newSigmod()), actionCollection()); + KStandardAction::open(this, SLOT(openSigmod()), actionCollection()); + KRecentFilesAction* recent = KStandardAction::openRecent(this, SLOT(openSigmod(const KUrl&)), actionCollection()); + recent->loadEntries(m_config.group("Recent Files")); + KStandardAction::save(this, SLOT(saveSigmod()), actionCollection()); + KStandardAction::saveAs(this, SLOT(saveAsSigmod()), actionCollection()); + KStandardAction::close(this, SLOT(closeSigmod()), actionCollection()); + KStandardAction::quit(this, SLOT(closeAllSigmods()), actionCollection()); + KStandardAction::cut(actionCollection()); + KStandardAction::copy(actionCollection()); + KStandardAction::paste(actionCollection()); + KAction* download = actionCollection()->addAction("download_sigmod"); + download->setText(i18n("Download")); + download->setIcon(KIcon("arrow-down-double")); + download->setShortcut(Qt::CTRL + Qt::Key_D); + connect(download, SIGNAL(triggered()), this, SLOT(downloadSigmod())); + KAction* upload = actionCollection()->addAction("upload_sigmod"); + upload->setText(i18n("Upload")); + upload->setIcon(KIcon("arrow-up-double")); + upload->setShortcut(Qt::CTRL + Qt::Key_U); + upload->setEnabled(false); + connect(upload, SIGNAL(triggered()), this, SLOT(uploadSigmod())); + KStandardAction::showMenubar(this, SLOT(toggleMenubar()), actionCollection()); + KStandardAction::configureToolbars(this, SLOT(configureToolbars()), actionCollection()); + createStandardStatusBarAction(); + setStandardToolBarMenuEnabled(true); + KStandardAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection()); + KStandardAction::preferences(this, SLOT(preferences()), actionCollection()); + setHelpMenuEnabled(true); + createGUI(); +} |
