diff --git a/src/templates/C++/kpartapp/README b/src/templates/C++/kpartapp/README index 08c5ae1..b6a9137 100644 --- a/src/templates/C++/kpartapp/README +++ b/src/templates/C++/kpartapp/README @@ -1,52 +1,53 @@ How To Build This Template -=-=-=-=-=-=-=-=-=-=-=-=-= --- On Unix: cd mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=$KDEDIRS -DCMAKE_BUILD_TYPE=Debug .. <- do not forget the .. make make install or su -c 'make install' where $KDEDIRS points to your KDE installation prefix. to uninstall the project: make uninstall or su -c 'make uninstall' Note: you can use another build path. Then cd in your build dir and: export KDE_SRC=path_to_your_src cmake $KDE_SRC -DCMAKE_INSTALL_PREFIX=$KDEDIRS -DCMAKE_BUILD_TYPE=Debug --- On Windows: cd mkdir build cd build cmake -DCMAKE_INSTALL_PREFIX=%KDEDIRS% -DCMAKE_BUILD_TYPE=Debug .. <- do not forget the .. [n]make [n]make install where %KDEDIRS% points to your KDE installation prefix. to uninstall the project: [n]make uninstall Note: use nmake if you're building with the Visual Studio compiler, or make if you're using the minGW compiler Tutorials -=-=-=-=- Kpart docs -http://techbase.kde.org/index.php?title=Development/Architecture/KDE4/KParts +https://techbase.kde.org/Development/Architecture/KDE4/KParts +https://api.kde.org/frameworks/kparts/html/index.html Tutorial -http://techbase.kde.org/Development/Architecture/KDE3/KParts +https://techbase.kde.org/Development/Tutorials/Using_KParts ---------------------------- Please send all comments to: Anne-Marie Mahfouf annma@kde.org Last update: July 2009 \ No newline at end of file diff --git a/src/templates/C++/kpartapp/src/%{APPNAMELC}.cpp b/src/templates/C++/kpartapp/src/%{APPNAMELC}.cpp index 36c6307..90b6fac 100644 --- a/src/templates/C++/kpartapp/src/%{APPNAMELC}.cpp +++ b/src/templates/C++/kpartapp/src/%{APPNAMELC}.cpp @@ -1,152 +1,144 @@ /*************************************************************************** * Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}> * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "%{APPNAMELC}.h" // KF headers #include #include #include #include #include #include #include #include // Qt headers #include #include #include %{APPNAME}::%{APPNAME}() : KParts::MainWindow( ) { // set the shell's ui resource file setXMLFile(QStringLiteral("%{APPNAMELC}_shell.rc")); // then, setup our actions setupActions(); // this routine will find and load our Part. it finds the Part by // name which is a bad idea usually.. but it's alright in this // case since our Part is made for this Shell KPluginLoader loader(QStringLiteral("%{APPNAMELC}part")); KPluginFactory* factory = loader.factory(); if (factory) { // now that the Part is loaded, we cast it to a Part to get // our hands on it m_part = factory->create(this); if (m_part) { // tell the KParts::MainWindow that this is indeed the main widget setCentralWidget(m_part->widget()); // and integrate the part's GUI with the shell's setupGUI(ToolBar | Keys | StatusBar | Save); createGUI(m_part); } } else { // if we couldn't find our Part, we exit since the Shell by // itself can't do anything useful KMessageBox::error(this, i18n("Could not find our Part!")); qApp->quit(); // we return here, cause qApp->quit() only means "exit the // next time we enter the event loop... return; } - - // apply the saved mainwindow settings, if any, and ask the mainwindow - // to automatically save settings if changed: window size, toolbar - // position, icon size, etc. - setAutoSaveSettings(); } %{APPNAME}::~%{APPNAME}() { } void %{APPNAME}::load(const QUrl& url) { m_part->openUrl(url); } void %{APPNAME}::setupActions() { KStandardAction::openNew(this, SLOT(fileNew()), actionCollection()); KStandardAction::open(this, SLOT(fileOpen()), actionCollection()); KStandardAction::quit(qApp, SLOT(closeAllWindows()), actionCollection()); - - createStandardStatusBarAction(); - setStandardToolBarMenuEnabled(true); } void %{APPNAME}::saveProperties(KConfigGroup & /*config*/) { // the 'config' object points to the session managed // config file. anything you write here will be available // later when this app is restored } void %{APPNAME}::readProperties(const KConfigGroup & /*config*/) { // the 'config' object points to the session managed // config file. this function is automatically called whenever // the app is being restored. read in here whatever you wrote // in 'saveProperties' } void %{APPNAME}::fileNew() { // this slot is called whenever the File->New menu is selected, // the New shortcut is pressed (usually CTRL+N) or the New toolbar // button is clicked // About this function, the style guide ( // http://developer.kde.org/documentation/standards/kde/style/basics/index.html ) // says that it should open a new window if the document is _not_ // in its initial state. This is what we do here.. if (!m_part->url().isValid() || m_part->isModified()) { (new %{APPNAME})->show(); }; } void %{APPNAME}::fileOpen() { // this slot is called whenever the File->Open menu is selected, // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar // button is clicked const QUrl url = QFileDialog::getOpenFileUrl(this); if (url.isValid()) { // About this function, the style guide ( // http://developer.kde.org/documentation/standards/kde/style/basics/index.html ) // says that it should open a new window if the document is _not_ // in its initial state. This is what we do here.. if (m_part->url().isEmpty() && ! m_part->isModified()) { // we open the file in this window... load(url); } else { // we open the file in a new window... %{APPNAME}* newWin = new %{APPNAME}; newWin->load(url); newWin->show(); } } } diff --git a/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.cpp b/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.cpp index de43372..7880272 100644 --- a/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.cpp +++ b/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.cpp @@ -1,170 +1,174 @@ /*************************************************************************** * Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}> * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "%{APPNAMELC}_part.h" // KF headers #include #include #include #include #include // Qt headers #include #include #include #include #include K_PLUGIN_FACTORY(%{APPNAME}PartFactory, registerPlugin<%{APPNAME}Part>();) %{APPNAME}Part::%{APPNAME}Part(QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/) : KParts::ReadWritePart(parent) { // we need a component data - setComponentData(createAboutData()); + // the first arg here must be the same as the subdirectory in + // which the part's rc file is installed + KAboutData aboutData("%{APPNAMELC}part", i18n("%{APPNAME}Part"), QStringLiteral("%{VERSION}")); + aboutData.addAuthor(i18n("%{AUTHOR}"), i18n("Author"), QStringLiteral("%{EMAIL}")); + setComponentData(aboutData); // this should be your custom internal widget m_widget = new QTextEdit(parentWidget); // notify the part that this is our internal widget setWidget(m_widget); // create our actions + m_saveAction = KStandardAction::save(this, SLOT(fileSave()), actionCollection()); KStandardAction::saveAs(this, SLOT(fileSaveAs()), actionCollection()); - m_saveAction = KStandardAction::save(this, SLOT(save()), actionCollection()); // set our XML-UI resource file setXMLFile("%{APPNAMELC}_part.rc"); // we are read-write by default setReadWrite(true); // we are not modified since we haven't done anything yet setModified(false); } %{APPNAME}Part::~%{APPNAME}Part() { } void %{APPNAME}Part::setReadWrite(bool rw) { // notify your internal widget of the read-write state m_widget->setReadOnly(!rw); QTextDocument* document = m_widget->document(); if (rw) { connect(document, &QTextDocument::modificationChanged, this, &%{APPNAME}Part::setModified); } else { disconnect(document, &QTextDocument::modificationChanged, this, &%{APPNAME}Part::setModified); } ReadWritePart::setReadWrite(rw); } void %{APPNAME}Part::setModified(bool modified) { // get a handle on our Save action and make sure it is valid if (!m_saveAction) { return; } // if so, we either enable or disable it based on the current // state m_saveAction->setEnabled(modified); // in any event, we want our parent to do it's thing ReadWritePart::setModified(modified); } -KAboutData %{APPNAME}Part::createAboutData() -{ - // the first arg here must be the same as the subdirectory in - // which the part's rc file is installed - KAboutData aboutData("%{APPNAMELC}part", i18n("%{APPNAME}Part"), QStringLiteral("%{VERSION}")); - aboutData.addAuthor(i18n("%{AUTHOR}"), i18n("Author"), QStringLiteral("%{EMAIL}")); - return aboutData; -} - bool %{APPNAME}Part::openFile() { // localFilePath() is always local so we can use QFile on it QFile file(localFilePath()); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return false; } // our example widget is text-based, so we use QTextStream instead // of a raw QDataStream QTextStream stream(&file); QString str; while (!stream.atEnd()) { str += stream.readLine() + "\n"; } file.close(); // now that we have the entire file, display it m_widget->setPlainText(str); // just for fun, set the status bar //emit setStatusBarText( m_url.prettyUrl() ); return true; } bool %{APPNAME}Part::saveFile() { // if we aren't read-write, return immediately if (!isReadWrite()) { return false; } // localFilePath() is always local, so we use QFile QFile file(localFilePath()); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } // use QTextStream to dump the text to the file QTextStream stream(&file); - stream << m_widget->document(); + stream << m_widget->toPlainText(); file.close(); m_widget->document()->setModified(false); return true; } +void %{APPNAME}Part::fileSave() +{ + if (url().isValid()) { + save(); + } else { + fileSaveAs(); + } +} + void %{APPNAME}Part::fileSaveAs() { // this slot is called whenever the File->Save As menu is selected, const QUrl file_name = QFileDialog::getSaveFileUrl(); if (file_name.isValid()) { saveAs(file_name); } } // needed for K_PLUGIN_FACTORY #include "%{APPNAMELC}_part.moc" diff --git a/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.h b/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.h index 5edc8ec..c28adac 100644 --- a/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.h +++ b/src/templates/C++/kpartapp/src/%{APPNAMELC}_part.h @@ -1,86 +1,84 @@ /*************************************************************************** * Copyright (C) %{CURRENT_YEAR} by %{AUTHOR} <%{EMAIL}> * * * * 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 2 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #ifndef %{APPNAMEUC}PART_H #define %{APPNAMEUC}PART_H // KF headers #include class QWidget; class QTextEdit; -class KAboutData; class QAction; /** * This is a "Part". It does all the real work in a KPart * application. * * @short Main Part * @author %{AUTHOR} <%{EMAIL}> * @version %${VERSION} */ class %{APPNAME}Part : public KParts::ReadWritePart { Q_OBJECT public: /** * Default constructor */ %{APPNAME}Part(QWidget *parentWidget, QObject *parent, const QVariantList &); /** * Destructor */ ~%{APPNAME}Part() override; /** * This is a virtual function inherited from KParts::ReadWritePart. * A shell will use this to inform this Part if it should act * read-only */ void setReadWrite(bool rw) override; /** * Reimplemented to disable and enable Save action */ void setModified(bool modified) override; - static KAboutData createAboutData(); - protected: /** * This must be implemented by each part */ bool openFile() override; /** * This must be implemented by each read-write part */ bool saveFile() override; protected Q_SLOTS: + void fileSave(); void fileSaveAs(); private: QTextEdit *m_widget; QAction *m_saveAction; }; #endif // %{APPNAMEUC}PART_H