/* * Copyright 2008 Ben Boeckel * * 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 . */ // Header include #include "PokeModrUI.h" // PokeModr includes #include "ObjectUI.h" #include "PokemodTreeModel.h" // Pokemod includes #include "../pokemod/Pokemod.h" #include "../pokemod/Rules.h" // Qt includes #include #include // KDE includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include PokeModrUI::PokeModrUI(KConfigGroup config, QWidget* parent) : KMainWindow(parent), m_config(config) { setupUi(this); setupActions(); splitter->setSizes(QList() << config.readEntry("treeWidth", 100) << config.readEntry("panelWidth", 100)); connect(buttonApply, SIGNAL(clicked()), this, SLOT(update())); KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); if (args) { for(int i = 0; i < args->count(); ++i) openPokemod(args->url(i)); args->clear(); } if (config.readEntry("reloadOnStart", false)) { for (int i = 0; i < config.readEntry("openedFiles", 0); ++i) openPokemod(m_recent->urls().at(i)); } setAutoSaveSettings("MainWindow", true); } PokeModrUI::~PokeModrUI() { closeAllPokemods(true); m_recent->saveEntries(m_config); } void PokeModrUI::update() { treePokemod->update(treePokemod->currentIndex()); } void PokeModrUI::closeEvent(QCloseEvent* event) { if (closeAllPokemods()) event->accept(); else event->ignore(); } void PokeModrUI::setChangedTitle(const bool changed) { setWindowTitle(QString::fromUtf8("%1%2 - PokéModr").arg(treePokemod->description(treePokemod->currentIndex()), changed ? "*" : "")); } void PokeModrUI::setDirty(const bool dirty) { const Pokemod* pokemod = static_cast(static_cast(treePokemod->currentIndex().internalPointer())->pokemod()); treePokemod->setDirty(pokemod, dirty); } void PokeModrUI::newPokemod() { treePokemod->addPokemod(new Pokemod()); } void PokeModrUI::openPokemod() { KUrl::List urls(KFileDialog::getOpenUrls(KUrl("kfiledialog:///pokemod"), QString::fromUtf8("*.pmod|PokéMod files"), this)); foreach (KUrl url, urls) { if (!url.isEmpty()) { if (openPokemod(url)) { m_recent->addUrl(url); m_recent->saveEntries(m_config); } } } } bool PokeModrUI::openPokemod(const KUrl& url) { if (url.isLocalFile()) return openPokemod(url.path()); else { QString temp; if (KIO::NetAccess::download(url, temp, this)) { const bool opened = openPokemod(temp, true); KIO::NetAccess::removeTempFile(temp); return opened; } else KMessageBox::error(this, KIO::NetAccess::lastErrorString(), "KIO Error"); } return false; } bool PokeModrUI::openPokemod(const QString& path, const bool isRemote) { QFile file(path); if (file.open(QIODevice::ReadOnly)) { QDomDocument xml; if (xml.setContent(&file)) { if (xml.doctype().name() == "Pokemod") { treePokemod->addPokemod(new Pokemod(xml.documentElement()), isRemote ? KUrl() : KUrl(path)); return true; } else KMessageBox::error(this, QString::fromUtf8("The file is not a PokéMod."), QString::fromUtf8("Invalid PokéMod")); } else KMessageBox::error(this, "The file is not a valid XML file.", QString::fromUtf8("Invalid PokéMod")); file.close(); } else KMessageBox::error(this, QString("Cannot open file:\n%1").arg(path), "No such file"); return false; } void PokeModrUI::savePokemod() { savePokemod(treePokemod->currentPokemod()); } void PokeModrUI::savePokemod(const Pokemod* pokemod) { const KUrl url = treePokemod->url(pokemod); if (url.isEmpty()) saveAsPokemod(pokemod); else savePokemod(pokemod, url); } bool PokeModrUI::savePokemod(const Pokemod* pokemod, const KUrl& url) { if (pokemod) { if (url.isLocalFile()) { QFile file(url.path()); if (file.open(QIODevice::ReadWrite)) { file.write(Object::xml(pokemod).toByteArray()); file.close(); return true; } else KMessageBox::error(this, QString::fromUtf8("Error saving the PokéMod!"), "Save error"); } else { KTemporaryFile temp; if (temp.open()) { temp.write(Object::xml(pokemod).toByteArray()); if (KIO::NetAccess::upload(temp.fileName(), url, this)) return true; else KMessageBox::error(this, KIO::NetAccess::lastErrorString(), "KIO Error"); } else KMessageBox::error(this, QString::fromUtf8("Error saving the PokéMod!"), "Save error"); } } return false; } void PokeModrUI::saveAsPokemod() { saveAsPokemod(treePokemod->currentPokemod()); } void PokeModrUI::saveAsPokemod(const Pokemod* pokemod) { if (pokemod) { KUrl url = KFileDialog::getSaveUrl(KUrl("kfiledialog:///pokemod"), QString::fromUtf8("*.pmod|PokéMod files"), this, QString::fromUtf8("Open PokéMod")); if (!url.isEmpty()) { if (savePokemod(pokemod, url)) treePokemod->setUrl(pokemod, url); } } } void PokeModrUI::closePokemod() { closePokemod(treePokemod->currentPokemod()); } bool PokeModrUI::closePokemod(const Pokemod* pokemod, const bool force) { if (pokemod) { if (treePokemod->dirty(pokemod)) { int result; if (force) result = KMessageBox::questionYesNo(this, "You have unsaved changes, would you like to save them?", QString::fromUtf8("Unsaved PokéMod")); else result = KMessageBox::questionYesNoCancel(this, "You have unsaved changes, would you like to save them?", QString::fromUtf8("Unsaved PokéMod")); switch (result) { case KMessageBox::Yes: savePokemod(pokemod); case KMessageBox::No: break; case KMessageBox::Cancel: return false; } } treePokemod->deletePokemod(pokemod); if (formPanel->widget()) delete formPanel->takeWidget(); } return true; } bool PokeModrUI::closeAllPokemods(const bool force) { QList pokemods = treePokemod->openedPokemods(); for (int i = 0; i < pokemods.size(); ) { if (closePokemod(pokemods[i], force)) pokemods.removeAt(i); else ++i; } if (!pokemods.size() || force) close(); return !pokemods.size(); } void PokeModrUI::copyObject() { m_clipboard = treePokemod->copy(treePokemod->currentIndex()); } void PokeModrUI::pasteObject() { treePokemod->paste(treePokemod->currentIndex(), m_clipboard); } void PokeModrUI::preferences() { // TODO: preferences } void PokeModrUI::on_splitter_splitterMoved() { m_config.writeEntry("treeWidth", splitter->sizes()[0]); m_config.writeEntry("panelWidth", splitter->sizes()[1]); } void PokeModrUI::on_treePokemod_clicked(const QModelIndex& index) { if (!(treePokemod->model()->flags(index) & Qt::ItemIsSelectable)) return; ObjectUI* widget = treePokemod->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(static_cast(formPanel->widget())->original()->className()))) { case KMessageBox::Yes: static_cast(formPanel->widget())->apply(); break; case KMessageBox::No: static_cast(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(buttonDiscard, SIGNAL(clicked()), widget, SLOT(discard())); setChangedTitle(false); formPanel->setWidget(widget); formPanel->show(); } } void PokeModrUI::on_treePokemod_customContextMenuRequested(const QPoint& position) { QModelIndex index = treePokemod->indexAt(position); KMenu* menu = treePokemod->contextMenu(index); if (menu) { QString type = treePokemod->model()->data(index, BaseModel::TypeRole).toString(); KAction* paste = new KAction("&Paste", this); connect(paste, SIGNAL(triggered()), this, SLOT(pasteObject())); menu->addSeparator(); if (!type.isEmpty()) { KAction* copy = new KAction("&Copy", this); connect(copy, SIGNAL(triggered()), this, SLOT(copyObject())); menu->addAction(copy); paste->setEnabled(m_clipboard.doctype().name() == type); } menu->addAction(paste); menu->popup(treePokemod->mapToGlobal(position)); } } void PokeModrUI::setupActions() { KAction* openNew = KStandardAction::openNew(this, SLOT(newPokemod()), this); KAction* open = KStandardAction::open(this, SLOT(openPokemod()), this); m_recent = KStandardAction::openRecent(this, SLOT(openPokemod(const KUrl&)), this); m_recent->loadEntries(m_config); KAction* close = KStandardAction::close(this, SLOT(closePokemod()), this); KAction* save = KStandardAction::save(this, SLOT(savePokemod()), this); KAction* saveAs = KStandardAction::saveAs(this, SLOT(saveAsPokemod()), this); KAction* quit = KStandardAction::quit(this, SLOT(closeAllPokemods()), this); KAction* cut = KStandardAction::cut(this); KAction* copy = KStandardAction::copy(this); KAction* paste = KStandardAction::paste(this); KAction* preferences = KStandardAction::preferences(this, SLOT(preferences()), this); KMenuBar* menubar = new KMenuBar(this); KMenu* menuFile = new KMenu("&File", menubar); menuFile->addAction(openNew); menuFile->addAction(open); menuFile->addAction(m_recent); menuFile->addAction(close); menuFile->addSeparator(); menuFile->addAction(save); menuFile->addAction(saveAs); menuFile->addSeparator(); menuFile->addAction(quit); menubar->addMenu(menuFile); KMenu* menuEdit = new KMenu("&Edit", menubar); menuEdit->addAction(cut); menuEdit->addAction(copy); menuEdit->addAction(paste); menuEdit->addSeparator(); menuEdit->addAction(preferences); menubar->addMenu(menuEdit); menubar->addMenu(customHelpMenu(false)); setMenuBar(menubar); KToolBar* toolbar = new KToolBar("toolbar", this, Qt::TopToolBarArea, false, true, true); toolbar->addAction(openNew); toolbar->addAction(open); toolbar->addAction(m_recent); toolbar->addAction(close); toolbar->addSeparator(); toolbar->addAction(save); toolbar->addAction(saveAs); toolbar->addSeparator(); toolbar->addAction(cut); toolbar->addAction(copy); toolbar->addAction(paste); toolbar->addSeparator(); toolbar->addAction(preferences); toolbar->addSeparator(); toolbar->addAction(quit); addToolBar(toolbar); }