KShutdown – graphical shutdown utility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
7.2KB

  1. /*
  2. extras.cpp - Extras
  3. Copyright (C) 2004 Konrad Twardowski <kdtonline@poczta.onet.pl>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  15. */
  16. #include <sys/types.h>
  17. #include "extras.h"
  18. #include "miscutils.h"
  19. #include "mmainwindow.h"
  20. #include <tqdir.h>
  21. #include <kdebug.h>
  22. #include <kdesktopfile.h>
  23. #include <kiconloader.h>
  24. #include <tdelocale.h>
  25. #include <tdemessagebox.h>
  26. #include <kmimetype.h>
  27. #include <tdepopupmenu.h>
  28. #include <kpushbutton.h>
  29. #include <krun.h>
  30. #include <kstandarddirs.h>
  31. #include <kstringhandler.h>
  32. Extras *Extras::_instance = 0;
  33. // public
  34. Extras::~Extras()
  35. {
  36. if (_idToFileMap)
  37. delete _idToFileMap;
  38. if (_menu)
  39. delete _menu;
  40. }
  41. void Extras::createButton(TQWidget *parent)
  42. {
  43. _button = new KPushButton(parent, "KPushButton::_button");
  44. _button->hide();
  45. _button->setPopup(_menu);
  46. MiscUtils::setHint(_button, i18n("More actions..."));
  47. setAction(TQString::null, TQString::null); /* evil */
  48. }
  49. bool Extras::execAction() const
  50. {
  51. if (_fileToExecute.isNull())
  52. return false; // error
  53. if (!execFile())
  54. {
  55. MiscUtils::showRunErrorMessage(_fileToExecute);
  56. return false; // error
  57. }
  58. return true; // ok
  59. }
  60. TQString Extras::getActionDescription() const
  61. {
  62. return
  63. _description.isEmpty()
  64. ? TQString::null
  65. // "Substitute characters at the middle of a string by \"...\""
  66. : KStringHandler::csqueeze(_description, 100);
  67. }
  68. void Extras::setAction(const TQString &fileToExecute, const TQString &description, TQIconSet *icon)
  69. {
  70. _description = description;
  71. _fileToExecute = fileToExecute;
  72. if (_fileToExecute.isNull())
  73. {
  74. _button->setText(i18n("Select a command..."));
  75. _button->setIconSet(ks_actions->getIcon(Action::Extras));
  76. }
  77. else
  78. {
  79. _button->setText(getActionDescription());
  80. if (!icon)
  81. _button->setIconSet(ks_actions->getIcon(Action::Extras));
  82. else
  83. _button->setIconSet(*icon);
  84. }
  85. }
  86. // private
  87. Extras::Extras()
  88. : TQObject(ks_main, "Extras"),
  89. _idToFileMap(0) // initialized in getIdToFileMap()
  90. {
  91. _menu = new TDEPopupMenu(0, "TDEPopupMenu::_menu");
  92. connect(_menu, SIGNAL(aboutToShow()), SLOT(slotShowMenu()));
  93. connect(_menu, SIGNAL(activated(int)), SLOT(slotActivated(int)));
  94. }
  95. // TODO: 2.0: recent items
  96. void Extras::buildMenu(TDEPopupMenu *parentMenu, const TQString &subdir)
  97. {
  98. int id;
  99. TQDir d(subdir);
  100. TQFileInfo fi;
  101. TQString
  102. description,
  103. icon,
  104. mimeType,
  105. name,
  106. path;
  107. TQStringList list = d.entryList(TQDir::DefaultFilter, TQDir::Name | TQDir::DirsFirst);
  108. list.remove(".");
  109. list.remove("..");
  110. uint count = list.count();
  111. for (uint i = 0; i < count; i++)
  112. {
  113. fi.setFile(d, list[i]);
  114. path = fi.filePath();
  115. // dir
  116. if (fi.isDir())
  117. {
  118. TDEPopupMenu *submenu = new TDEPopupMenu(parentMenu, "TDEPopupMenu::submenu");
  119. connect(submenu, SIGNAL(activated(int)), SLOT(slotActivated(int)));
  120. KDesktopFile *desktopFile = new KDesktopFile(path + "/.directory", true);
  121. if (desktopFile->getConfigState() != TDEConfigBase::NoAccess)
  122. {
  123. icon = desktopFile->readIcon();
  124. if (icon.isEmpty())
  125. icon = "folder";
  126. name = desktopFile->readName();
  127. if (name.isEmpty())
  128. name = fi.baseName();
  129. description = desktopFile->readComment();
  130. // add item
  131. parentMenu->insertItem(
  132. SmallIcon(icon),
  133. description.isEmpty() ? name : description,
  134. submenu
  135. );
  136. }
  137. else
  138. {
  139. // add item
  140. parentMenu->insertItem(SmallIcon("folder"), fi.baseName(), submenu);
  141. }
  142. delete desktopFile;
  143. // recurse
  144. buildMenu(submenu, fi.filePath());
  145. }
  146. // file
  147. else if (fi.isFile())
  148. {
  149. mimeType = KMimeType::findByPath(path)->name();
  150. if (mimeType == "application/x-trash")
  151. continue;
  152. if (mimeType != "application/x-desktop")
  153. {
  154. // add item
  155. id = parentMenu->insertItem(
  156. KMimeType::pixmapForURL(KURL::fromPathOrURL(path)),
  157. fi.baseName()
  158. );
  159. // map item
  160. getIdToFileMap()->insert(id, path);
  161. continue;
  162. }
  163. // application/x-desktop
  164. KDesktopFile *desktopFile = new KDesktopFile(path, true);
  165. if (desktopFile->getConfigState() != TDEConfigBase::NoAccess)
  166. {
  167. name = desktopFile->readName();
  168. if (name.isEmpty())
  169. name = desktopFile->readEntry("Exec");
  170. description = desktopFile->readComment();
  171. // add item
  172. id = parentMenu->insertItem(
  173. SmallIcon(desktopFile->readIcon()),
  174. description.isEmpty()
  175. ? name
  176. : (description + " (" + name + ")")
  177. );
  178. // map item
  179. getIdToFileMap()->insert(id, path);
  180. }
  181. delete desktopFile;
  182. }
  183. }
  184. }
  185. bool Extras::execFile() const
  186. {
  187. if (_fileToExecute.isNull())
  188. {
  189. // kdDebug() << "Extras::execFile(): No file to execute" << endl;
  190. return false;
  191. }
  192. // HACK: It seems that KRun::runURL sometimes does not work for hibernate :/ ?
  193. TQFileInfo fi(_fileToExecute);
  194. if (fi.fileName() == "hibernate.desktop") {
  195. kdDebug() << "Extras::execFile(): Using hacked run..." << endl;
  196. pid_t pid = KRun::runCommand("kfmclient exec \"" + _fileToExecute + "\"");
  197. return pid;
  198. }
  199. else {
  200. pid_t pid = KRun::runURL(
  201. KURL::fromPathOrURL(_fileToExecute),
  202. KMimeType::findByPath(_fileToExecute)->name()
  203. );
  204. return pid;
  205. }
  206. }
  207. TQMap<int, TQString> *Extras::getIdToFileMap()
  208. {
  209. if (!_idToFileMap)
  210. _idToFileMap = new TQMap<int, TQString>;
  211. return _idToFileMap;
  212. }
  213. // public slots
  214. void Extras::slotModify()
  215. {
  216. KMessageBox::information(
  217. 0,
  218. MiscUtils::HTML(
  219. i18n("Use context menu to add/edit/remove links.") +
  220. "<ul>" +
  221. "<li>" + i18n("Use <b>Context Menu</b> to create a new link to application") + "</li>" +
  222. "<li>" + i18n("Use <b>Create New|Folder...</b> to create a new submenu") + "</li>" +
  223. "<li>" + i18n("Use <b>Properties</b> to change icon, name, or comment") + "</li>" +
  224. "</ul>"
  225. ),
  226. i18n("Extras"), // title
  227. "ModifyExtras" // config key
  228. );
  229. // launch Konqueror as an item editor
  230. MiscUtils::runCommand("konqueror \"" + TDEGlobal::dirs()->saveLocation("data", "kshutdown/extras") + "\"");
  231. }
  232. // private slots
  233. void Extras::slotActivated(int id)
  234. {
  235. TQMap<int, TQString>::iterator i = getIdToFileMap()->find(id);
  236. if (i == getIdToFileMap()->end())
  237. {
  238. setAction(TQString::null, TQString::null);
  239. KMessageBox::error(
  240. 0,
  241. "Internal error!\nSelected menu item is broken.",
  242. i18n("Extras")
  243. );
  244. }
  245. else
  246. {
  247. setAction(i.data(), _menu->text(id), _menu->iconSet(id));
  248. }
  249. }
  250. void Extras::slotShowMenu()
  251. {
  252. setAction(TQString::null, TQString::null);
  253. _menu->clear(); // reset menu
  254. getIdToFileMap()->clear(); // reset map
  255. TQStringList extrasDirs(TDEGlobal::dirs()->findDirs("data", "kshutdown/extras"));
  256. TQStringList::ConstIterator
  257. begin = extrasDirs.begin(),
  258. end = extrasDirs.end();
  259. for (TQStringList::ConstIterator it = begin; it != end; ++it)
  260. {
  261. if ((it != begin) && (_menu->count() > 0))
  262. _menu->insertSeparator();
  263. buildMenu(_menu, *it);
  264. }
  265. }
  266. #include "extras.moc"