summaryrefslogtreecommitdiffstats
path: root/sigmodr/SigmodrUI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sigmodr/SigmodrUI.cpp')
-rw-r--r--sigmodr/SigmodrUI.cpp451
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();
+}