2 * Copyright (C) 2008 David Greaves
4 * This software is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 2.1 of
7 * the License, or (at your option) any later version.
9 * This software is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this software; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 #define DEBUG_SHOPPER 1
22 #include "shopper.h" // automake, i8n, gettext
24 #include "mainwindow.h"
25 #include "CatListModel.h"
26 #include "CategoryDialog.h"
27 #include "ItemDialog.h"
31 Shopper::Notify
*notify
;
33 // class MainWindow : public QMainWindow
34 MainWindow::MainWindow(QString file
) :
41 init_MainWindow(NULL
);
43 MainWindow::MainWindow(Shopper::List
&l
) :
53 void MainWindow::init_MainWindow(Shopper::List
*l
)
55 // The constructor handles only 'one off' stuff - main menu,
56 // buttons etc. Anything List specific is seperated off to
57 // handle_list() so it can be reused when opening new lists
59 // xrandr detection from adv-backlight...
62 int xrr_event_base
, xrr_error_base
;
63 int xrr_major
, xrr_minor
;
64 dpy
= XOpenDisplay (NULL
);
67 DEBUG("Couldn't open display\n");
70 if (XRRQueryExtension (dpy
, &xrr_event_base
, &xrr_error_base
) == false
71 || XRRQueryVersion (dpy
, &xrr_major
, &xrr_minor
) == 0 || xrr_major
!= 1 || xrr_minor
< 1)
80 QAction
*addItemAct
= new QAction(QIcon(":/images/new.png"), tr("Add Item"), this);
81 addItemAct
->setStatusTip(tr("Add an item to the list"));
82 connect(addItemAct
, SIGNAL(triggered()), this, SLOT(on_action_add_item()));
84 QAction
*manageCatAct
= new QAction(QIcon(":/images/new.png"), tr("Manage Categories"), this);
85 manageCatAct
->setStatusTip(tr("Manage the list of categories"));
86 connect(manageCatAct
, SIGNAL(triggered()), this, SLOT(on_action_manage_category()));
88 QAction
*clearWantedAct
= new QAction(QIcon(":/images/new.png"), tr("Clear Wanted"), this);
89 clearWantedAct
->setStatusTip(tr("Clear the items marked as 'wanted'"));
90 connect(clearWantedAct
, SIGNAL(triggered()), this, SLOT(on_action_clear_wanted()));
92 QAction
*emptyBasketAct
= new QAction(QIcon(":/images/new.png"), tr("Empty Basket"), this);
93 emptyBasketAct
->setStatusTip(tr("Clear the items marked as 'in the basket'"));
94 connect(emptyBasketAct
, SIGNAL(triggered()), this, SLOT(on_action_clear_bought()));
96 QAction
*fullListAct
= new QAction(QIcon(":/images/new.png"), tr("Out Shopping: Full List"), this);
97 fullListAct
->setStatusTip(tr("Show the full list (items in the basket will be visible and ticked)"));
98 connect(fullListAct
, SIGNAL(triggered()), this, SLOT(on_action_fullList()));
100 QAction
*whatsLeftAct
= new QAction(QIcon(":/images/new.png"), tr("Out Shopping: What's Left"), this);
101 whatsLeftAct
->setStatusTip(tr("Show what's left to get"));
102 connect(whatsLeftAct
, SIGNAL(triggered()), this, SLOT(on_action_whatsLeft()));
104 QAction
*makingListAct
= new QAction(QIcon(":/images/new.png"), tr("Making List"), this);
105 makingListAct
->setStatusTip(tr("Pick items to get when you go shopping"));
106 connect(makingListAct
, SIGNAL(triggered()), this, SLOT(on_action_makingList()));
108 QAction
*newAct
= new QAction(QIcon(":/images/new.png"), tr("Add Item"), this);
109 newAct
->setStatusTip(tr("Add an item to the list"));
110 connect(newAct
, SIGNAL(triggered()), this, SLOT(on_action_file_new()));
112 QAction
*openAct
= new QAction(QIcon(":/images/new.png"), tr("Open List"), this);
113 openAct
->setStatusTip(tr("Open a new list"));
114 connect(openAct
, SIGNAL(triggered()), this, SLOT(on_action_file_open()));
116 QAction
*saveAct
= new QAction(QIcon(":/images/new.png"), tr("Save List"), this);
117 saveAct
->setStatusTip(tr("Save the list"));
118 connect(saveAct
, SIGNAL(triggered()), this, SLOT(on_action_file_save()));
120 QAction
*saveAsAct
= new QAction(QIcon(":/images/new.png"), tr("Save List As..."), this);
121 saveAsAct
->setStatusTip(tr("Save the list with a new name"));
122 connect(saveAsAct
, SIGNAL(triggered()), this, SLOT(on_action_file_saveas()));
124 QAction
*quitAct
= new QAction(QIcon(":/images/new.png"), tr("Quit"), this);
125 quitAct
->setStatusTip(tr("Finish"));
126 connect(quitAct
, SIGNAL(triggered()), this, SLOT(on_action_file_quit()));
128 QAction
*aboutAct
= new QAction(QIcon(":/images/new.png"), tr("About..."), this);
129 aboutAct
->setStatusTip(tr("About Shopper..."));
130 connect(aboutAct
, SIGNAL(triggered()), this, SLOT(on_action_about()));
132 // Defined in class to be available elsewhere
133 nextAct
= new QAction(QIcon(":/images/new.png"), tr("Next Category"), this);
134 nextAct
->setStatusTip(tr("View the next category"));
135 connect(nextAct
, SIGNAL(triggered()), this, SLOT(on_action_next()));
137 QAction
*prevAct
= new QAction(QIcon(":/images/new.png"), tr("Prev Category"), this);
138 prevAct
->setStatusTip(tr("View the previous category"));
139 connect(prevAct
, SIGNAL(triggered()), this, SLOT(on_action_prev()));
142 menuBar()->addAction(addItemAct
);
143 menuBar()->addAction(manageCatAct
);
145 QMenu
*clearMenu
= menuBar()->addMenu(tr("Clear List"));
146 clearMenu
->addAction(clearWantedAct
);
147 clearMenu
->addAction(emptyBasketAct
);
149 QMenu
*modeMenu
= menuBar()->addMenu(tr("Mode"));
150 modeMenu
->addAction(fullListAct
);
151 modeMenu
->addAction(whatsLeftAct
);
152 modeMenu
->addAction(makingListAct
);
154 menuBar()->addSeparator();
156 QMenu
*fileMenu
= menuBar()->addMenu(tr("File"));
157 fileMenu
->addAction(newAct
);
158 fileMenu
->addAction(openAct
);
159 fileMenu
->addAction(saveAct
);
160 fileMenu
->addAction(saveAsAct
);
161 fileMenu
->addAction(quitAct
);
163 QMenu
*helpMenu
= menuBar()->addMenu(tr("Help"));
164 helpMenu
->addAction(aboutAct
);
167 buttonBar
= addToolBar(tr("Buttons"));
168 addToolBar(Qt::BottomToolBarArea
, buttonBar
); // move it to the right area
169 buttonBar
->addAction(addItemAct
);
170 buttonBar
->addAction(manageCatAct
);
171 buttonBar
->addSeparator();
172 buttonBar
->addAction(fullListAct
);
173 buttonBar
->addAction(whatsLeftAct
);
174 buttonBar
->addAction(makingListAct
);
175 buttonBar
->addSeparator();
176 buttonBar
->addAction(prevAct
);
177 buttonBar
->addAction(nextAct
);
180 statusBar()->showMessage(tr("Ready"));
182 // Notify is a SystemTrayIcon used for notify messages
183 // Note this is a globally accessible object - nothing to do with MainWin except we parent it
184 notify
=new Shopper::Notify(style()->standardIcon(QStyle::SP_FileDialogListView
));
190 // If we got a filename then read it in...
192 l
= Shopper::List::from_file(filename
);
193 if (l
) { // If filename valid
195 } else { // If filename wasn't read
196 on_action_file_new();
199 // Hildon::Banner::show_information(*this, "Created a new shopping list");
200 // while (!mylist) { // mylist and list_view are done in a file_open()
201 // DEBUG("Couldn't open " << filename << " for reading\n");
202 // on_action_file_open();
203 // FIXME :: Popup dialog box and allow new/open
207 // Now do List specific stuff
212 void MainWindow::create_list_view(Shopper::List
*list
)
214 // Remove the old listview... and any data
218 // and use a list and a new main shopperList widget
220 lv
= new Shopper::ListView(*list
);
221 setCentralWidget(lv
);
222 // GUI: set title, add the view, update the menu
223 setWindowTitle(mylist
->modeText());
224 // Make sure there's a menu to show to enable the popup functionality
226 catCombo
= new QComboBox();
227 Shopper::CatListModel
*clmodel
= new Shopper::CatListModel(*mylist
);
228 catCombo
->setModel(clmodel
);
229 catCombo
->setModelColumn(1);
230 catCombo
->setCurrentIndex(clmodel
->currentIndex());
231 connect(catCombo
, SIGNAL(activated(int)),
232 this, SLOT(cat_selected(int)));
233 connect(clmodel
, SIGNAL(currentChanged(int)),
234 catCombo
, SLOT(setCurrentIndex(int)));
235 buttonBar
->insertWidget(nextAct
, catCombo
);
240 void MainWindow::cat_selected(int i
)
243 QVariant v
= catCombo
->itemData(catCombo
->currentIndex());
244 Shopper::Category
*c
= v
.value
<Shopper::Category
*>();
245 mylist
->make_category_active(*c
);
249 void MainWindow::closeEvent(QCloseEvent
*event
)
254 void MainWindow::on_action_about()
256 QMessageBox::about(this, tr("About Application"),
257 tr("The <b>Application</b> example demonstrates how to "
258 "write modern GUI applications using Qt, with a menu bar, "
259 "toolbars, and a status bar."));
263 void MainWindow::readSettings()
265 QSettings
settings("dgreaves", "Shopper");
266 QPoint pos
= settings
.value("pos", QPoint(200, 200)).toPoint();
267 QSize size
= settings
.value("size", QSize(400, 400)).toSize();
272 void MainWindow::writeSettings()
274 QSettings
settings("dgreaves", "shopper");
275 settings
.setValue("pos", pos());
276 settings
.setValue("size", size());
281 void MainWindow::on_action_add_item()
283 Shopper::ItemAdd
itemD(this, mylist
);
284 if (itemD
.exec() == QDialog::Accepted
) {
289 void MainWindow::on_action_manage_category()
291 Shopper::CategoryManage
catD(this, mylist
);
296 void MainWindow::on_action_next(){ mylist
->make_next_category_active(); }
297 void MainWindow::on_action_prev(){ mylist
->make_prev_category_active(); }
300 void MainWindow::on_action_clear_wanted() { clear_list(CLEAR_WANTED
); }
301 void MainWindow::on_action_clear_bought() { clear_list(CLEAR_BOUGHT
); }
302 void MainWindow::clear_list(clear_list_mode m
)
304 for (Shopper::List::pItemIter it
= mylist
->itemsI(); it
!= mylist
->itemsEnd(); it
++) {
305 (*it
)->set_bought(false); // Always clear bought
306 if (m
== CLEAR_WANTED
) {
307 (*it
)->set_wanted(false);
310 if (m
== CLEAR_WANTED
) {
311 set_state(Shopper::MAKING_LIST
);
315 void MainWindow::on_action_fullList() { set_state(Shopper::OUT_SHOPPING
); }
316 void MainWindow::on_action_whatsLeft() { set_state(Shopper::WHATS_LEFT
); }
317 void MainWindow::on_action_makingList() { set_state(Shopper::MAKING_LIST
); }
318 void MainWindow::set_state(Shopper::sState s
)
320 Shopper::sState old
= mylist
->get_state();
321 mylist
->set_state(s
); // Set the state
322 if (s
== Shopper::MAKING_LIST
) { // And go to category '1'
323 if (mylist
->get_active_category() == NULL
) { // show category 1 rather than 'Everything'
324 mylist
->make_category_active(**(mylist
->categoriesI()));
327 // And go to category 'Everything' if switching to an 'out shopping' state.
328 if (s
== Shopper::WHATS_LEFT
|| s
== Shopper::OUT_SHOPPING
) {
329 if (old
== Shopper::MAKING_LIST
) mylist
->no_category_active();
331 // set_title(mylist->modeText()); // Gtk
333 ////////////////////////////////////////////////////////////////
335 void MainWindow::on_action_file_new()
337 // FIXME: This really ought to check if the user *WANTS* to save...
339 on_action_file_save();
341 create_list_view(new Shopper::List(
343 "<list name='Supermarket' state='0'>"
344 "<category name='Aisle 1 - Dairy'>"
345 "<item desc='Cheese' note='note, no smelly cheese' wanted='1' bought='0'/>"
346 "<item desc='Bacon' note='Extra needed for Gary's butties' wanted='1' bought='0'/>"
348 "<category name='Frozen'>"
349 "<item desc='Peas' note='' wanted='1' bought='0'/>"
350 "<item desc='Prawns' note='' wanted='1' bought='0'/>"
352 "<category name='Veg'>"
353 "<item desc='Potatoes' note='' wanted='0' bought='0'/>"
354 "<item desc='Brocolli' note='' wanted='1' bought='0'/>"
359 void MainWindow::on_action_file_open()
363 Hildon::FileChooserDialog dialog(*this, Gtk::FILE_CHOOSER_ACTION_OPEN);
364 int response = dialog.run();
367 //Handle the response:
368 if (response == Gtk::RESPONSE_OK) {
369 // Open file and create a view from it.
370 create_list_view(Shopper::List::from_file(filename=dialog.get_filename()));
371 save_filename(filename); // FIXME this should be on success
373 if (mylist == NULL) on_action_file_new(); // If CANCEL pressed and there's no list, make a new one
377 ////////////////////////////////////////////////////////////////
378 void MainWindow::on_action_file_save()
380 DEBUG("Saving....\n");
382 on_action_file_saveas();
384 mylist
->to_file(filename
);
387 void MainWindow::on_action_file_saveas()
391 Hildon::FileChooserDialog dialog(*this, Gtk::FILE_CHOOSER_ACTION_SAVE);
393 dialog.set_current_name("ShoppingList");
395 dialog.set_filename(filename);
397 int response = dialog.run();
399 if (response == Gtk::RESPONSE_OK)
401 QString filename = dialog.get_filename();
402 save_filename(filename);
403 mylist->to_file(filename);
407 void MainWindow::on_action_file_quit()
409 on_action_file_save();
411 hide(); //Closes the main window to stop the Gtk::Main::run().
414 bool MainWindow::on_signal_window_closed()
416 on_action_file_quit();
417 return true; // propogate signal so hide() happens
420 bool MainWindow::on_key_pressed()
426 switch (event->keyval)
437 case GDK_F6: // Fullscreen
438 on_action_fullscreen();
440 case GDK_F7: // Zoom in
441 case GDK_F8: // Zoom out
446 // Returning true would stop the event now
451 void MainWindow::on_action_fullscreen()
454 // unfullscreen(); // gtk
456 // fullscreen(); // gtk
458 full_screen
= !full_screen
;
460 void MainWindow::save_filename(QString name
)
464 void MainWindow::on_action_rotate()
466 if (! has_rotation
) return;
468 XRRScreenConfiguration
*scr_config
;
469 // Rotation current_rotation;
475 dpy
= XOpenDisplay (NULL
);
476 screen
= DefaultScreen (dpy
);
477 scr_config
= XRRGetScreenInfo (dpy
, RootWindow (dpy
, screen
));
478 size
= XRRConfigCurrentConfiguration (scr_config
, &rotation
);
480 if (rotation
== RR_Rotate_0
) {
481 rotation
= RR_Rotate_90
;
483 rotation
= RR_Rotate_0
; // always rotate back to 0
486 XRRSetScreenConfig (dpy
, scr_config
, RootWindow (dpy
, screen
), size
, rotation
, CurrentTime
);
487 XRRFreeScreenConfigInfo (scr_config
);
492 void MainWindow::on_action_help()