~ubuntu-branches/ubuntu/hardy/codeblocks/hardy-backports

« back to all changes in this revision

Viewing changes to src/plugins/todo/todolist.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 
3
 * http://www.gnu.org/licenses/gpl-3.0.html
 
4
 *
 
5
 * $Revision: 4909 $
 
6
 * $Id: todolist.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
 
7
 * $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/plugins/todo/todolist.cpp $
 
8
 */
 
9
 
 
10
#include "sdk.h"
 
11
#ifndef CB_PRECOMP
 
12
  #include <wx/event.h>
 
13
  #include <wx/frame.h> // GetMenuBar
 
14
  #include <wx/fs_zip.h>
 
15
  #include <wx/intl.h>
 
16
  #include <wx/menu.h>
 
17
  #include <wx/menuitem.h>
 
18
  #include <wx/string.h>
 
19
  #include <wx/utils.h>
 
20
  #include <wx/xrc/xmlres.h>
 
21
  #include "cbeditor.h"
 
22
  #include "configmanager.h"
 
23
  #include "editormanager.h"
 
24
  #include "manager.h"
 
25
  #include "projectmanager.h"
 
26
  #include "logmanager.h"
 
27
  #include "sdk_events.h"
 
28
#endif
 
29
#include "cbstyledtextctrl.h"
 
30
 
 
31
#include "addtododlg.h"
 
32
#include "asktypedlg.h"
 
33
#include "todolist.h"
 
34
#include "todolistview.h"
 
35
#include "todosettingsdlg.h"
 
36
 
 
37
#include <wx/arrimpl.cpp>
 
38
WX_DEFINE_OBJARRAY(ToDoItems);
 
39
 
 
40
namespace
 
41
{
 
42
    PluginRegistrant<ToDoList> reg(_T("ToDoList"));
 
43
}
 
44
 
 
45
const int idViewTodo = wxNewId();
 
46
const int idAddTodo = wxNewId();
 
47
const int idStartParsing = wxNewId();
 
48
 
 
49
BEGIN_EVENT_TABLE(ToDoList, cbPlugin)
 
50
    EVT_UPDATE_UI(idViewTodo, ToDoList::OnUpdateUI)
 
51
    EVT_MENU(idViewTodo, ToDoList::OnViewList)
 
52
    EVT_MENU(idAddTodo, ToDoList::OnAddItem)
 
53
END_EVENT_TABLE()
 
54
 
 
55
ToDoList::ToDoList() :
 
56
m_InitDone(false),
 
57
m_ParsePending(false),
 
58
m_StandAlone(true)
 
59
{
 
60
    //ctor
 
61
    if(!Manager::LoadResource(_T("todo.zip")))
 
62
    {
 
63
        NotifyMissingFile(_T("todo.zip"));
 
64
    }
 
65
}
 
66
 
 
67
ToDoList::~ToDoList()
 
68
{
 
69
    //dtor
 
70
}
 
71
 
 
72
void ToDoList::OnAttach()
 
73
{
 
74
    // create ToDo in bottom view
 
75
    wxArrayString titles;
 
76
    wxArrayInt widths;
 
77
    titles.Add(_("Type"));
 
78
    titles.Add(_("Text"));
 
79
    titles.Add(_("User"));
 
80
    titles.Add(_("Prio."));
 
81
    titles.Add(_("Line"));
 
82
    titles.Add(_("File"));
 
83
    widths.Add(64);
 
84
    widths.Add(320);
 
85
    widths.Add(64);
 
86
    widths.Add(48);
 
87
    widths.Add(48);
 
88
    widths.Add(640);
 
89
 
 
90
    m_pListLog = new ToDoListView(titles, widths, m_Types);
 
91
 
 
92
    bool standalone = Manager::Get()->GetConfigManager(_T("todo_list"))->ReadBool(_T("stand_alone"), true);
 
93
    m_StandAlone = standalone;
 
94
 
 
95
    if(!standalone)
 
96
    {
 
97
        LogManager* msgMan = Manager::Get()->GetLogManager();
 
98
        m_ListPageIndex = msgMan->SetLog(m_pListLog);
 
99
        msgMan->Slot(m_ListPageIndex).title = _("To-Do");
 
100
 
 
101
        CodeBlocksLogEvent evt(cbEVT_ADD_LOG_WINDOW, m_pListLog, msgMan->Slot(m_ListPageIndex).title, msgMan->Slot(m_ListPageIndex).icon);
 
102
        Manager::Get()->ProcessEvent(evt);
 
103
    }
 
104
    else
 
105
    {
 
106
        m_pListLog->CreateControl(Manager::Get()->GetAppWindow());
 
107
        m_pListLog->GetWindow()->SetSize(wxSize(352,94));
 
108
        m_pListLog->GetWindow()->SetInitialSize(wxSize(352,94));
 
109
 
 
110
        CodeBlocksDockEvent evt(cbEVT_ADD_DOCK_WINDOW);
 
111
        evt.name = _T("TodoListPanev2.0.0");
 
112
        evt.title = _("To-Do list");
 
113
        evt.pWindow = m_pListLog->GetWindow();
 
114
        evt.dockSide = CodeBlocksDockEvent::dsFloating;
 
115
        evt.desiredSize.Set(352, 94);
 
116
        evt.floatingSize.Set(352, 94);
 
117
        evt.minimumSize.Set(352, 94);
 
118
        Manager::Get()->ProcessEvent(evt);
 
119
    }
 
120
 
 
121
    m_AutoRefresh = Manager::Get()->GetConfigManager(_T("todo_list"))->ReadBool(_T("auto_refresh"), true);
 
122
    LoadTypes();
 
123
 
 
124
    // register event sink
 
125
    Manager::Get()->RegisterEventSink(cbEVT_APP_STARTUP_DONE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnAppDoneStartup));
 
126
    Manager::Get()->RegisterEventSink(cbEVT_EDITOR_OPEN, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
 
127
    Manager::Get()->RegisterEventSink(cbEVT_EDITOR_SAVE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
 
128
    Manager::Get()->RegisterEventSink(cbEVT_EDITOR_ACTIVATED, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
 
129
    Manager::Get()->RegisterEventSink(cbEVT_EDITOR_CLOSE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparseCurrent));
 
130
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_CLOSE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
 
131
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_ACTIVATE, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
 
132
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_FILE_ADDED, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
 
133
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_FILE_REMOVED, new cbEventFunctor<ToDoList, CodeBlocksEvent>(this, &ToDoList::OnReparse));
 
134
}
 
135
 
 
136
void ToDoList::OnRelease(bool appShutDown)
 
137
{
 
138
    if(m_StandAlone)
 
139
    {
 
140
        CodeBlocksDockEvent evt(cbEVT_REMOVE_DOCK_WINDOW);
 
141
        evt.pWindow = m_pListLog->GetWindow();
 
142
        Manager::Get()->ProcessEvent(evt);
 
143
//        delete m_pListLog;
 
144
    }
 
145
    else
 
146
    {
 
147
        CodeBlocksLogEvent evt(cbEVT_REMOVE_LOG_WINDOW, m_pListLog);
 
148
        evt.window = m_pListLog->GetWindow();
 
149
        Manager::Get()->ProcessEvent(evt);
 
150
    }
 
151
    m_pListLog = 0;
 
152
}
 
153
 
 
154
void ToDoList::BuildMenu(wxMenuBar* menuBar)
 
155
{
 
156
    int idx = menuBar->FindMenu(_("View"));
 
157
    if (idx != wxNOT_FOUND)
 
158
    {
 
159
        wxMenu* view = menuBar->GetMenu(idx);
 
160
        wxMenuItemList& items = view->GetMenuItems();
 
161
        // find the first separator and insert before it
 
162
        for (size_t i = 0; i < items.GetCount(); ++i)
 
163
        {
 
164
            if (items[i]->IsSeparator())
 
165
            {
 
166
                view->InsertCheckItem(i, idViewTodo, _("To-Do list"), _("Toggle displaying the To-Do list"));
 
167
                return;
 
168
            }
 
169
        }
 
170
        // not found, just append
 
171
        view->AppendCheckItem(idViewTodo, _("To-Do list"), _("Toggle displaying the To-Do list"));
 
172
    }
 
173
}
 
174
 
 
175
void ToDoList::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data)
 
176
{
 
177
    if (!menu || !IsAttached())
 
178
        return;
 
179
    if (type == mtEditorManager)
 
180
    {
 
181
        menu->AppendSeparator();
 
182
        menu->Append(idAddTodo, _("Add To-Do item..."), _("Add new To-Do item..."));
 
183
    }
 
184
}
 
185
 
 
186
bool ToDoList::BuildToolBar(wxToolBar* toolBar)
 
187
{
 
188
    return false;
 
189
}
 
190
 
 
191
cbConfigurationPanel* ToDoList::GetConfigurationPanel(wxWindow* parent)
 
192
{
 
193
    ToDoSettingsDlg* dlg = new ToDoSettingsDlg(parent);
 
194
    return dlg;
 
195
}
 
196
 
 
197
int ToDoList::Configure()
 
198
{
 
199
    return 0;
 
200
//    ToDoSettingsDlg dlg;
 
201
//    PlaceWindow(&dlg);
 
202
//    if (dlg.ShowModal() == wxID_OK)
 
203
//        m_AutoRefresh = Manager::Get()->GetConfigManager(_T("todo_list"))->ReadBool(_T("auto_refresh"), true);
 
204
//    return 0;
 
205
}
 
206
 
 
207
void ToDoList::LoadTypes()
 
208
{
 
209
    m_Types.Clear();
 
210
 
 
211
    Manager::Get()->GetConfigManager(_T("todo_list"))->Read(_T("types"), &m_Types);
 
212
 
 
213
    if(m_Types.GetCount() == 0)
 
214
    {
 
215
        m_Types.Add(_T("TODO"));
 
216
        m_Types.Add(_T("@todo"));
 
217
        m_Types.Add(_T("\\todo"));
 
218
        m_Types.Add(_T("FIXME"));
 
219
        m_Types.Add(_T("NOTE"));
 
220
        m_Types.Add(_T("@note"));
 
221
        m_Types.Add(_T("\\note"));
 
222
    }
 
223
    SaveTypes();
 
224
}
 
225
 
 
226
void ToDoList::SaveTypes()
 
227
{
 
228
    Manager::Get()->GetConfigManager(_T("todo_list"))->Write(_T("types"), m_Types);
 
229
}
 
230
 
 
231
// events
 
232
 
 
233
void ToDoList::OnAppDoneStartup(CodeBlocksEvent& event)
 
234
{
 
235
    m_InitDone = true;
 
236
    Parse();
 
237
    event.Skip();
 
238
}
 
239
 
 
240
void ToDoList::OnUpdateUI(wxUpdateUIEvent& event)
 
241
{
 
242
    Manager::Get()->GetAppFrame()->GetMenuBar()->Check(idViewTodo, IsWindowReallyShown(m_pListLog->GetWindow()));
 
243
}
 
244
 
 
245
void ToDoList::OnViewList(wxCommandEvent& event)
 
246
{
 
247
    if(m_StandAlone)
 
248
    {
 
249
        CodeBlocksDockEvent evt(event.IsChecked() ? cbEVT_SHOW_DOCK_WINDOW : cbEVT_HIDE_DOCK_WINDOW);
 
250
        evt.pWindow = m_pListLog->GetWindow();
 
251
        Manager::Get()->ProcessEvent(evt);
 
252
    }
 
253
    else
 
254
    {
 
255
        if(event.IsChecked())
 
256
        {
 
257
                CodeBlocksLogEvent evtShow(cbEVT_SHOW_LOG_MANAGER);
 
258
                Manager::Get()->ProcessEvent(evtShow);
 
259
                CodeBlocksLogEvent event(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
 
260
                Manager::Get()->ProcessEvent(event);
 
261
        }
 
262
    }
 
263
}
 
264
 
 
265
void ToDoList::OnAddItem(wxCommandEvent& event)
 
266
{
 
267
    cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
 
268
    if (!ed)
 
269
        return;
 
270
 
 
271
    // display todo dialog
 
272
    AddTodoDlg dlg(Manager::Get()->GetAppWindow(), m_Types);
 
273
    PlaceWindow(&dlg);
 
274
    if (dlg.ShowModal() != wxID_OK)
 
275
        return;
 
276
    SaveTypes();
 
277
 
 
278
    cbStyledTextCtrl* control = ed->GetControl();
 
279
 
 
280
    // calculate insertion point
 
281
    int idx = 0;
 
282
    int crlfLen = 0; // length of newline chars
 
283
    int origPos = control->GetCurrentPos(); // keep current position in the document
 
284
    int line = control->GetCurrentLine(); // current line
 
285
    ToDoCommentType CmtType = dlg.GetCommentType();
 
286
    if (dlg.GetPosition() == tdpCurrent)
 
287
    {
 
288
        idx = control->GetCurrentPos(); // current position in the document
 
289
        // if the style is cpp comments (// ...), there's the possibility that the current position
 
290
        // is somewhere in the middle of a line of code; this would result
 
291
        // in everything after the insertion point to turn into comments
 
292
        // let's double check this with the user
 
293
        if(idx != control->GetLineEndPosition(line))
 
294
        {
 
295
            // let's ask the user, and present as options
 
296
            // keep cpp style at current position, switch to c style, add the todo at the end (keeping cpp style)
 
297
            // if user cancels out / do nothing : just return
 
298
            // future idea : check if there's any non white space character
 
299
            // if yes -> in the middle of code
 
300
            // if no -> then only whitespace after the insertion point -> no harm to turn that into comments
 
301
            AskTypeDlg dlg(Manager::Get()->GetAppWindow());
 
302
            PlaceWindow(&dlg);
 
303
            if (dlg.ShowModal() != wxID_OK)
 
304
                return;
 
305
            switch(dlg.GetTypeCorrection())
 
306
            {
 
307
                case tcCppStay:
 
308
                    break; // do nothing, leave things as they are
 
309
                case tcCpp2C:
 
310
                    CmtType = tdctC;
 
311
                    break;
 
312
                case tcCppMove:
 
313
                default:
 
314
                    idx = control->GetLineEndPosition(line);
 
315
                    break;
 
316
            } // end switch
 
317
        }
 
318
    }
 
319
    else
 
320
    {
 
321
        if (dlg.GetPosition() == tdpAbove)
 
322
            idx = control->GetLineEndPosition(line - 1); // get previous line's end
 
323
        else if (dlg.GetPosition() == tdpBelow)
 
324
            idx = control->GetLineEndPosition(line); // get current line's end
 
325
        // calculate insertion point by skipping next newline
 
326
        switch (control->GetEOLMode())
 
327
        {
 
328
            case wxSCI_EOL_CR:
 
329
            case wxSCI_EOL_LF: crlfLen = 1; break;
 
330
            case wxSCI_EOL_CRLF: crlfLen = 2; break;
 
331
        }
 
332
        if (idx > 0)
 
333
            idx += crlfLen;
 
334
    }
 
335
    // make sure insertion point is valid (bug #1300981)
 
336
    if (idx > control->GetLength())
 
337
        idx = control->GetLength();
 
338
 
 
339
    // ok, construct todo line text like this:
 
340
    // TODO (mandrav#0#): Implement code to do this and the other...
 
341
    wxString buffer;
 
342
 
 
343
    // start with the comment
 
344
    switch(CmtType)
 
345
    {
 
346
        case tdctCpp:
 
347
            buffer << _T("// ");
 
348
            break;
 
349
        case tdctDoxygen:
 
350
            buffer << _T("/// ");
 
351
            break;
 
352
        case tdctWarning:
 
353
            buffer << _T("#warning ");
 
354
            break;
 
355
        case tdctError:
 
356
            buffer << _T("#error ");
 
357
            break;
 
358
        default:
 
359
            buffer << _T("/* ");
 
360
            break;
 
361
    } // end switch
 
362
 
 
363
    // continue with the type
 
364
    buffer << dlg.GetType() << _T(" ");
 
365
    wxString priority = wxString::Format(_T("%d"), dlg.GetPriority()); // do it like this (wx bug with int and streams)
 
366
 
 
367
    // now do the () part
 
368
    buffer << _T("(") << dlg.GetUser() << _T("#") << priority << _T("#): ");
 
369
 
 
370
    wxString text = dlg.GetText();
 
371
    if (CmtType != tdctC)
 
372
    {
 
373
        // make sure that multi-line notes, don't break the to-do
 
374
        if (text.Replace(_T("\r\n"), _T("\\\r\n")) == 0)
 
375
            text.Replace(_T("\n"), _T("\\\n"));
 
376
        // now see if there were already a backslash before newline
 
377
        if (text.Replace(_T("\\\\\r\n"), _T("\\\r\n")) == 0)
 
378
            text.Replace(_T("\\\\\n"), _T("\\\n"));
 
379
    }
 
380
 
 
381
    // add the actual text
 
382
    buffer << text;
 
383
 
 
384
    if (CmtType == tdctWarning || CmtType == tdctError)
 
385
        buffer << _T("");
 
386
 
 
387
    else if (CmtType == tdctC)
 
388
        buffer << _T(" */");
 
389
 
 
390
    // add newline char(s), only if dlg.GetPosition() != tdpCurrent
 
391
    if (dlg.GetPosition() != tdpCurrent)
 
392
    {
 
393
        switch (control->GetEOLMode())
 
394
        {
 
395
            // NOTE: maybe this switch, should make it in the SDK (maybe as cbStyledTextCtrl::GetEOLString())???
 
396
            case wxSCI_EOL_CR: buffer << _T("\n"); break;
 
397
            case wxSCI_EOL_CRLF: buffer << _T("\r\n"); break;
 
398
            case wxSCI_EOL_LF: buffer << _T("\r"); break;
 
399
        }
 
400
    }
 
401
 
 
402
    // ok, insert the todo line text
 
403
    control->InsertText(idx, buffer);
 
404
    if (dlg.GetPosition() == tdpAbove)
 
405
        origPos += buffer.Length() + crlfLen;
 
406
    control->GotoPos(origPos);
 
407
    control->EnsureCaretVisible();
 
408
 
 
409
    ParseCurrent(true);
 
410
} // end of OnAddItem
 
411
 
 
412
void ToDoList::OnReparse(CodeBlocksEvent& event)
 
413
{
 
414
    if (m_InitDone && m_AutoRefresh && !(ProjectManager::IsBusy()))
 
415
    {
 
416
        Parse();
 
417
    }
 
418
    else
 
419
    {
 
420
        m_ParsePending = true;
 
421
        m_pListLog->Clear();
 
422
    }
 
423
    event.Skip();
 
424
}
 
425
 
 
426
void ToDoList::OnReparseCurrent(CodeBlocksEvent& event)
 
427
{
 
428
    bool forced = (event.GetEventType() == cbEVT_EDITOR_OPEN || event.GetEventType() == cbEVT_EDITOR_SAVE);
 
429
    if (m_InitDone && m_AutoRefresh && !(ProjectManager::IsBusy()))
 
430
    {
 
431
        if(m_ParsePending)
 
432
        {
 
433
            m_ParsePending = false;
 
434
            Parse();
 
435
        }
 
436
        else
 
437
        {
 
438
            ParseCurrent(forced);
 
439
        }
 
440
    }
 
441
    event.Skip();
 
442
}
 
443
 
 
444
void ToDoList::ParseCurrent(bool forced)
 
445
{
 
446
    m_pListLog->ParseCurrent(forced);
 
447
}
 
448
 
 
449
void ToDoList::Parse()
 
450
{
 
451
    m_pListLog->Parse();
 
452
}